Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions src/FreeDSx/Ldap/Exception/LdifParseException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

/**
* This file is part of the FreeDSx LDAP package.
*
* (c) Chad Sikorra <Chad.Sikorra@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FreeDSx\Ldap\Exception;

use Exception;

/**
* Represents an issue encountered while parsing LDIF.
*
* @author Chad Sikorra <Chad.Sikorra@gmail.com>
*/
class LdifParseException extends Exception
{
public function __construct(
string $message,
private readonly int $lineNumber = 0,
private readonly ?string $sourceLine = null,
) {
parent::__construct(
$lineNumber > 0
? sprintf('%s (LDIF line %d).', $message, $lineNumber)
: $message,
);
}

/**
* The 1-based LDIF line where parsing failed; 0 when not applicable.
*/
public function getLineNumber(): int
{
return $this->lineNumber;
}

/**
* The raw LDIF line that triggered the error, if known.
*/
public function getSourceLine(): ?string
{
return $this->sourceLine;
}
}
44 changes: 43 additions & 1 deletion src/FreeDSx/Ldap/LdapServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@

namespace FreeDSx\Ldap;

use FreeDSx\Ldap\Entry\Dn;
use FreeDSx\Ldap\Exception\InvalidArgumentException;
use FreeDSx\Ldap\Exception\LdifParseException;
use FreeDSx\Ldap\Exception\OperationException;
use FreeDSx\Ldap\Exception\RuntimeException;
use FreeDSx\Ldap\Ldif\LdifParser;
use FreeDSx\Ldap\Ldif\Loader\LdifLoaderInterface;
use FreeDSx\Ldap\Schema\SchemaValidationMode;
use FreeDSx\Ldap\Schema\Validation\SchemaValidator;
use FreeDSx\Ldap\Server\AccessControl\AccessControlInterface;
Expand All @@ -23,6 +30,7 @@
use FreeDSx\Ldap\Server\Backend\Auth\PasswordAuthenticatableInterface;
use FreeDSx\Ldap\Server\Backend\LdapBackendInterface;
use FreeDSx\Ldap\Server\Backend\Storage\EntryStorageInterface;
use FreeDSx\Ldap\Server\Backend\Storage\LdapImporter;
use FreeDSx\Ldap\Server\Backend\Storage\WritableStorageBackend;
use FreeDSx\Ldap\Server\Backend\Write\WriteHandlerInterface;
use FreeDSx\Ldap\Server\RequestHandler\ProxyHandler;
Expand Down Expand Up @@ -133,12 +141,46 @@ public function useStorage(EntryStorageInterface $storage): self
return $this->useBackend(new WritableStorageBackend(
storage: $storage,
limits: $this->options->makeSearchLimits(),
namingContexts: $this->options->getDseNamingContexts(),
validator: $this->buildSchemaValidator(),
namingContexts: $this->options->getDseNamingContexts(),
operationalAttrs: new OperationalAttributeGenerator($schema),
));
}

/**
* Convenience method to bulk-load LDIF entries into the storage configured via {@see useStorage()}.
*
* The LDIF source is pluggable via {@see LdifLoaderInterface} (a file, a string, a database, etc.). Entries are
* validated and stamped with operational attributes the same way the live write path would.
*
* @param Dn $creatorDn DN recorded as creatorsName/modifiersName on imported entries; defaults to the anonymous (empty) DN.
* @throws LdifParseException when the LDIF cannot be parsed
* @throws RuntimeException when no storage backend is configured (or the loader fails to load)
* @throws InvalidArgumentException when the creator DN is malformed or an entry's parent is missing
* @throws OperationException when an entry violates the schema and validation mode is strict
*/
public function seed(
LdifLoaderInterface $loader,
Dn $creatorDn = new Dn(''),
): self {
$backend = $this->options->getBackend();

if (!$backend instanceof WritableStorageBackend) {
throw new RuntimeException('seed() requires a storage backend configured via useStorage().');
}

$entries = (new LdifParser())
->parse($loader->load());
(new LdapImporter(
$backend->getStorage(),
$backend->getOperationalAttributeGenerator(),
$backend->getSchemaValidator(),
$creatorDn,
))->importEntries($entries->toArray());

return $this;
}

private function buildSchemaValidator(): ?SchemaValidator
{
$mode = $this->options->getSchemaValidationMode();
Expand Down
78 changes: 78 additions & 0 deletions src/FreeDSx/Ldap/Ldif/LdifOutputOptions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

declare(strict_types=1);

/**
* This file is part of the FreeDSx LDAP package.
*
* (c) Chad Sikorra <Chad.Sikorra@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FreeDSx\Ldap\Ldif;

/**
* Output options for {@see LdifWriter}.
*
* @author Chad Sikorra <Chad.Sikorra@gmail.com>
*/
final class LdifOutputOptions
{
private bool $includeVersion = true;

private bool $lineFolding = true;

private int $maxLineLength = 76;

private string $lineEnding = "\n";

public function isIncludeVersion(): bool
{
return $this->includeVersion;
}

public function setIncludeVersion(bool $includeVersion): self
{
$this->includeVersion = $includeVersion;

return $this;
}

public function isLineFolding(): bool
{
return $this->lineFolding;
}

public function setLineFolding(bool $lineFolding): self
{
$this->lineFolding = $lineFolding;

return $this;
}

public function getMaxLineLength(): int
{
return $this->maxLineLength;
}

public function setMaxLineLength(int $maxLineLength): self
{
$this->maxLineLength = $maxLineLength;

return $this;
}

public function getLineEnding(): string
{
return $this->lineEnding;
}

public function setLineEnding(string $lineEnding): self
{
$this->lineEnding = $lineEnding;

return $this;
}
}
Loading
Loading