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
64 changes: 63 additions & 1 deletion src/FreeDSx/Ldap/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@
use FreeDSx\Ldap\Server\PasswordPolicy\Constraint\PasswordChangeConstraintChain;
use FreeDSx\Ldap\Server\PasswordPolicy\Constraint\QualityConstraint;
use FreeDSx\Ldap\Server\PasswordPolicy\Constraint\SafeModifyConstraint;
use FreeDSx\Ldap\Server\PasswordPolicy\PasswordPolicyComponentFactory;
use FreeDSx\Ldap\Server\PasswordPolicy\PasswordPolicyEngine;
use FreeDSx\Ldap\Server\Backend\Auth\PasswordHashService;
use FreeDSx\Ldap\Server\Backend\Write\WriteOperationDispatcher;
use FreeDSx\Ldap\Server\PasswordModify\PasswordModifyTargetResolver;
use FreeDSx\Ldap\Server\RequestHandler\HandlerFactory;
use FreeDSx\Ldap\Server\ServerProtocolFactory;
use FreeDSx\Ldap\Server\ServerRunner\PcntlServerRunner;
Expand All @@ -55,7 +58,6 @@ class Container
private const FACTORY_ONLY = [
HandlerFactoryInterface::class,
ServerAuthorization::class,
ServerProtocolHandlerFactory::class,
];

/**
Expand Down Expand Up @@ -174,6 +176,26 @@ className: ClockInterface::class,
className: PasswordPolicyEngine::class,
factory: $this->makePasswordPolicyEngine(...),
);
$this->registerFactory(
className: ServerProtocolHandlerFactory::class,
factory: $this->makeServerProtocolHandlerFactory(...),
);
$this->registerFactory(
className: PasswordModifyTargetResolver::class,
factory: $this->makePasswordModifyTargetResolver(...),
);
$this->registerFactory(
className: PasswordHashService::class,
factory: $this->makePasswordHashService(...),
);
$this->registerFactory(
className: WriteOperationDispatcher::class,
factory: $this->makeWriteOperationDispatcher(...),
);
$this->registerFactory(
className: PasswordPolicyComponentFactory::class,
factory: $this->makePasswordPolicyComponentFactory(...),
);
}

private function makePasswordPolicyEngine(): PasswordPolicyEngine
Expand Down Expand Up @@ -250,6 +272,46 @@ private function makeServerProtocolFactory(): ServerProtocolFactory
options: $this->get(ServerOptions::class),
serverAuthorization: $this->get(ServerAuthorization::class),
passwordPolicyEngine: $this->get(PasswordPolicyEngine::class),
routeResolver: $this->get(ServerProtocolHandlerFactory::class),
targetResolver: $this->get(PasswordModifyTargetResolver::class),
hashService: $this->get(PasswordHashService::class),
writeDispatcher: $this->get(WriteOperationDispatcher::class),
policyComponentFactory: $this->get(PasswordPolicyComponentFactory::class),
);
}

private function makeServerProtocolHandlerFactory(): ServerProtocolHandlerFactory
{
return new ServerProtocolHandlerFactory($this->get(ServerOptions::class));
}

private function makePasswordModifyTargetResolver(): PasswordModifyTargetResolver
{
$handlerFactory = $this->get(HandlerFactoryInterface::class);

return new PasswordModifyTargetResolver(
$handlerFactory->makeBackend(),
$handlerFactory->makeIdentityResolverChain(),
);
}

private function makePasswordHashService(): PasswordHashService
{
return new PasswordHashService($this->get(ServerOptions::class)->getPasswordHashScheme());
}

private function makeWriteOperationDispatcher(): WriteOperationDispatcher
{
return $this->get(HandlerFactoryInterface::class)->makeWriteDispatcher();
}

private function makePasswordPolicyComponentFactory(): PasswordPolicyComponentFactory
{
return new PasswordPolicyComponentFactory(
handlerFactory: $this->get(HandlerFactoryInterface::class),
options: $this->get(ServerOptions::class),
writeDispatcher: $this->get(WriteOperationDispatcher::class),
passwordPolicyEngine: $this->get(PasswordPolicyEngine::class),
);
}

Expand Down
165 changes: 165 additions & 0 deletions src/FreeDSx/Ldap/Protocol/Factory/ProtocolHandlerProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
<?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\Protocol\Factory;

use FreeDSx\Ldap\Control\ControlBag;
use FreeDSx\Ldap\Operation\Request\RequestInterface;
use FreeDSx\Ldap\Protocol\Queue\ServerQueue;
use FreeDSx\Ldap\Protocol\ServerProtocolHandler;
use FreeDSx\Ldap\Protocol\ServerProtocolHandler\ServerProtocolHandlerInterface;
use FreeDSx\Ldap\Server\Backend\Auth\PasswordHashService;
use FreeDSx\Ldap\Server\Backend\Write\WriteOperationDispatcher;
use FreeDSx\Ldap\Server\HandlerFactoryInterface;
use FreeDSx\Ldap\Server\Logging\EventLogger;
use FreeDSx\Ldap\Server\PasswordModify\PasswordModifyService;
use FreeDSx\Ldap\Server\PasswordModify\PasswordModifyTargetResolver;
use FreeDSx\Ldap\Server\PasswordPolicy\PasswordPolicyComponentFactory;
use FreeDSx\Ldap\Server\PasswordPolicy\PasswordPolicyContext;
use FreeDSx\Ldap\Server\RequestHistory;
use FreeDSx\Ldap\ServerOptions;

/**
* Builds the per-request protocol handler, wiring per-connection state to shared services.
*
* @internal
* @author Chad Sikorra <Chad.Sikorra@gmail.com>
*/
final readonly class ProtocolHandlerProvider implements ProtocolHandlerProviderInterface
{
public function __construct(
private HandlerRouteResolverInterface $routeResolver,
private HandlerFactoryInterface $handlerFactory,
private ServerOptions $options,
private PasswordModifyTargetResolver $targetResolver,
private PasswordHashService $hashService,
private WriteOperationDispatcher $writeDispatcher,
private PasswordPolicyComponentFactory $policyComponentFactory,
private ServerQueue $queue,
private EventLogger $eventLogger,
private RequestHistory $requestHistory,
private ?PasswordPolicyContext $passwordPolicyContext = null,
) {}

public function get(
RequestInterface $request,
ControlBag $controls,
): ServerProtocolHandlerInterface {
return match ($this->routeResolver->routeIdFor($request, $controls)) {
HandlerId::Abandon => new ServerProtocolHandler\ServerAbandonHandler(),
HandlerId::Cancel => new ServerProtocolHandler\ServerCancelHandler($this->queue),
HandlerId::WhoAmI => new ServerProtocolHandler\ServerWhoAmIHandler($this->queue),
HandlerId::PasswordModify => $this->getPasswordModifyHandler(),
HandlerId::StartTls => $this->getStartTlsHandler(),
HandlerId::UnsupportedExtended => new ServerProtocolHandler\ServerUnsupportedExtendedHandler($this->queue),
HandlerId::RootDse => $this->getRootDseHandler(),
HandlerId::Subschema => $this->getSubschemaHandler(),
HandlerId::Paging => $this->getPagingHandler(),
HandlerId::Search => $this->getSearchHandler(),
HandlerId::Unbind => new ServerProtocolHandler\ServerUnbindHandler($this->queue),
HandlerId::Dispatch => $this->getDispatchHandler(),
};
}

private function getPasswordModifyHandler(): ServerProtocolHandler\ServerPasswordModifyHandler
{
return new ServerProtocolHandler\ServerPasswordModifyHandler(
queue: $this->queue,
service: new PasswordModifyService(
targetResolver: $this->targetResolver,
accessControl: $this->options->getAccessControl(),
writeDispatcher: $this->writeDispatcher,
hashService: $this->hashService,
changeGuard: $this->policyComponentFactory->makeChangeGuard(
$this->eventLogger,
$this->passwordPolicyContext,
),
passwordPolicyContext: $this->passwordPolicyContext,
),
eventLogger: $this->eventLogger,
passwordPolicyContext: $this->passwordPolicyContext,
);
}

private function getStartTlsHandler(): ServerProtocolHandler\ServerStartTlsHandler
{
return new ServerProtocolHandler\ServerStartTlsHandler(
options: $this->options,
queue: $this->queue,
eventLogger: $this->eventLogger,
);
}

private function getSubschemaHandler(): ServerProtocolHandler\ServerSubschemaHandler
{
return new ServerProtocolHandler\ServerSubschemaHandler(
options: $this->options,
queue: $this->queue,
);
}

private function getSearchHandler(): ServerProtocolHandler\ServerSearchHandler
{
return new ServerProtocolHandler\ServerSearchHandler(
queue: $this->queue,
backend: $this->handlerFactory->makeBackend(),
filterEvaluator: $this->handlerFactory->makeFilterEvaluator(),
accessControl: $this->options->getAccessControl(),
schema: $this->options->getSchema(),
limits: $this->options->makeSearchLimits(),
eventLogger: $this->eventLogger,
);
}

private function getDispatchHandler(): ServerProtocolHandler\ServerDispatchHandler
{
$policyWriteHandler = $this->policyComponentFactory->makeWriteHandler(
$this->eventLogger,
$this->passwordPolicyContext,
);

return new ServerProtocolHandler\ServerDispatchHandler(
queue: $this->queue,
backend: $this->handlerFactory->makeBackend(),
writeDispatcher: $policyWriteHandler !== null
? $this->handlerFactory->makeWriteDispatcher($policyWriteHandler)
: $this->writeDispatcher,
accessControl: $this->options->getAccessControl(),
eventRecorder: new ServerProtocolHandler\DispatchEventRecorder($this->eventLogger),
passwordPolicyContext: $this->passwordPolicyContext,
);
}

private function getRootDseHandler(): ServerProtocolHandler\ServerRootDseHandler
{
return new ServerProtocolHandler\ServerRootDseHandler(
options: $this->options,
queue: $this->queue,
rootDseHandler: $this->handlerFactory->makeRootDseHandler(),
);
}

private function getPagingHandler(): ServerProtocolHandler\ServerPagingHandler
{
return new ServerProtocolHandler\ServerPagingHandler(
queue: $this->queue,
backend: $this->handlerFactory->makeBackend(),
filterEvaluator: $this->handlerFactory->makeFilterEvaluator(),
accessControl: $this->options->getAccessControl(),
requestHistory: $this->requestHistory,
schema: $this->options->getSchema(),
limits: $this->options->makeSearchLimits(),
eventLogger: $this->eventLogger,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?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\Protocol\Factory;

use FreeDSx\Ldap\Control\ControlBag;
use FreeDSx\Ldap\Operation\Request\RequestInterface;
use FreeDSx\Ldap\Protocol\ServerProtocolHandler\ServerProtocolHandlerInterface;

/**
* Builds the protocol handler for a resolved request route.
*
* @internal
* @author Chad Sikorra <Chad.Sikorra@gmail.com>
*/
interface ProtocolHandlerProviderInterface
{
public function get(
RequestInterface $request,
ControlBag $controls,
): ServerProtocolHandlerInterface;
}
Loading
Loading