From a44350407eae78e8d5fcc445b9112c23fbb0c04c Mon Sep 17 00:00:00 2001 From: Roland Gruber Date: Tue, 4 Sep 2018 19:34:03 +0200 Subject: [PATCH] import changetype add --- lam/graphics/importexport.png | Bin 3498 -> 855 bytes lam/lib/import.inc | 125 ++++++++++++++++++++++++++++++++++ lam/tests/lib/importTest.php | 41 +++++++++++ 3 files changed, 166 insertions(+) diff --git a/lam/graphics/importexport.png b/lam/graphics/importexport.png index 00d75f74aabb1bb3b77ed47edffae7fb22879de9..f2445164cff0aae5484a4019717394cec09443e5 100644 GIT binary patch delta 832 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 Ws-8Pl`mgetChangeTypeTask($dn, $currentLines, $type); + $currentLines = array(); + $i++; + $line = $entry[$i]; + $lineTypeData = $this->getLineKeyValue($line); + if ($lineTypeData[Importer::KEY] != Importer::CHANGETYPE) { + throw new LAMException(_('Invalid data'), htmlspecialchars($line)); + } + } + $currentLines[] = $line; + } + $subtasks[] = $this->getChangeTypeTask($dn, $currentLines, $type); + return new MultiTask($subtasks); + } + } + + /** + * Returns a task for LDIF changeType entry. + * + * @param string $dn DN + * @param string $lines lines + * @param string $type change type + * @return ImporterTask task + */ + private function getChangeTypeTask($dn, $lines, $type) { + $attributes = array(); + foreach ($lines as $line) { + $lineData = $this->getLineKeyValue($line); + $attributes[$lineData[Importer::KEY]][] = $lineData[Importer::VALUE]; + } + if ($type === 'add') { + return new AddAttributesTask($dn, $attributes); + } + throw new LAMException(_('Invalid data'), htmlspecialchars($dn) . ' - ' . Importer::CHANGETYPE . ': ' . htmlspecialchars($type)); } /** @@ -293,6 +336,9 @@ class Importer { */ private function getLineKeyValue($line) { $parts = explode(':', $line, 2); + if (sizeof($parts) !== 2) { + throw new LAMException(_('Invalid data'), htmlspecialchars($line)); + } if (substr($parts[Importer::VALUE], 0, 1) == ':') { $value = base64_decode(trim(substr($parts[Importer::VALUE], 1))); } @@ -356,4 +402,83 @@ class AddEntryTask implements ImporterTask { } +/** + * Combines multiple import tasks. + * + * @author Roland Gruber + */ +class MultiTask implements ImporterTask { + + /** + * @var ImporterTask[] tasks + */ + private $tasks = array(); + + /** + * Constructor + * + * @param ImporterTask[] $tasks tasks + */ + public function __construct($tasks) { + $this->tasks = $tasks; + } + + /** + * {@inheritDoc} + * @see \LAM\TOOLS\IMPORT_EXPORT\ImporterTask::run() + */ + public function run() { + foreach ($this->tasks as $task) { + $task->run(); + } + return Importer::formatMessage('INFO', _('LDAP operation successful.'), htmlspecialchars($this->dn)); + } + + /** + * Returns the list of subtasks. + * + * @return ImporterTask[] + */ + public function getTasks() { + return $this->tasks; + } + +} + +/** + * Adds attributes to an existing LDAP entry. + * + * @author Roland Gruber + */ +class AddAttributesTask implements ImporterTask { + + private $dn = ''; + private $attributes = array(); + + /** + * Constructor + * + * @param string $dn DN + * @param array[string[]] $attributes list of attributes + */ + public function __construct($dn, $attributes) { + $this->dn = $dn; + $this->attributes = $attributes; + } + + /** + * {@inheritDoc} + * @see \LAM\TOOLS\IMPORT_EXPORT\ImporterTask::run() + */ + public function run() { + $ldap = $_SESSION['ldap']->server(); + $success = @ldap_mod_add($ldap, $this->dn, $this->attributes); + if ($success) { + return ''; + } + throw new LAMException(sprintf(_('Was unable to create DN: %s.'), $this->dn), getExtendedLDAPErrorMessage($ldap)); + } + +} + ?> diff --git a/lam/tests/lib/importTest.php b/lam/tests/lib/importTest.php index ce579bee..caa5f6b5 100644 --- a/lam/tests/lib/importTest.php +++ b/lam/tests/lib/importTest.php @@ -1,5 +1,7 @@ assertEquals(1, sizeof($tasks)); } + /** + * Change entry with invalid changetype. + */ + public function testChangeInvalidType() { + $lines = array( + "version: 1", + "", + "dn: uid=test,dc=example,dc=com", + "changeType: invalid", + "uid: test", + ); + + $this->setExpectedException(LAMException::class, 'uid=test,dc=example,dc=com - changeType: invalid'); + + $importer = new Importer(); + $tasks = $importer->getTasks($lines); + } + + /** + * Change entry with add changetype. + */ + public function testChangeAdd() { + $lines = array( + "version: 1", + "", + "dn: uid=test,dc=example,dc=com", + "changeType: add", + "uid: test", + ); + + $importer = new Importer(); + $tasks = $importer->getTasks($lines); + $this->assertEquals(1, sizeof($tasks)); + $multiTask = $tasks[0]; + $this->assertEquals(MultiTask::class, get_class($multiTask)); + $this->assertEquals(1, sizeof($multiTask->getTasks())); + $this->assertEquals(AddAttributesTask::class, get_class($multiTask->getTasks()[0])); + } + }