diff --git a/DataCollector/LdapToolsDataCollector.php b/DataCollector/LdapToolsDataCollector.php index 3e7c0ce..7e87375 100644 --- a/DataCollector/LdapToolsDataCollector.php +++ b/DataCollector/LdapToolsDataCollector.php @@ -57,7 +57,7 @@ public function getName() /** * {@inheritdoc} */ - public function collect(Request $request, Response $response, \Exception $exception = null) + public function collect(Request $request, Response $response, \Throwable $exception = null) { if (!$this->ldap) { return; diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index fd95704..69408d7 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -39,8 +39,15 @@ public function __construct($debug) */ public function getConfigTreeBuilder() { - $treeBuilder = new TreeBuilder(); - $rootNode = $treeBuilder->root('ldap_tools'); + $treeBuilder = new TreeBuilder('ldap_tools'); + + if (method_exists($treeBuilder, 'getRootNode')) { + $rootNode = $treeBuilder->getRootNode(); + } else { + // BC layer for symfony/config 4.1 and older + $rootNode = $treeBuilder->root('ldap_tools'); + } + $this->addMainSection($rootNode); $this->addDoctrineSection($rootNode); $this->addGeneralSection($rootNode); diff --git a/Doctrine/Subscriber/LdapObjectSubscriber.php b/Doctrine/Subscriber/LdapObjectSubscriber.php index 6b38137..f8c9ee5 100644 --- a/Doctrine/Subscriber/LdapObjectSubscriber.php +++ b/Doctrine/Subscriber/LdapObjectSubscriber.php @@ -255,7 +255,7 @@ protected function queryLdapForObjects(\ReflectionProperty $property, LdapObject */ protected function getObjectFromLifeCycleArgs(LifecycleEventArgs $args) { - $rc = new \ReflectionClass('Doctrine\Common\Persistence\Event\LifecycleEventArgs'); + $rc = new \ReflectionClass('Doctrine\ORM\Event\LifecycleEventArgs'); if ($rc->hasMethod('getObject')) { return $args->getObject(); @@ -272,7 +272,7 @@ protected function getObjectFromLifeCycleArgs(LifecycleEventArgs $args) */ protected function getOmFromLifeCycleArgs(LifecycleEventArgs $args) { - $rc = new \ReflectionClass('Doctrine\Common\Persistence\Event\LifecycleEventArgs'); + $rc = new \ReflectionClass('Doctrine\ORM\Event\LifecycleEventArgs'); if ($rc->hasMethod('getObjectManager')) { return $args->getObjectManager(); diff --git a/Event/AuthenticationHandlerEvent.php b/Event/AuthenticationHandlerEvent.php index 4fba81b..3716348 100644 --- a/Event/AuthenticationHandlerEvent.php +++ b/Event/AuthenticationHandlerEvent.php @@ -10,7 +10,7 @@ namespace LdapTools\Bundle\LdapToolsBundle\Event; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; @@ -21,7 +21,7 @@ * * @author Chad Sikorra */ -class AuthenticationHandlerEvent extends Event +class AuthenticationHandlerEvent extends EventDispatcher { /** * The event name that happens after the default authentication success handler is called. diff --git a/Event/LdapLoginEvent.php b/Event/LdapLoginEvent.php index 831a8d6..c8d75b3 100644 --- a/Event/LdapLoginEvent.php +++ b/Event/LdapLoginEvent.php @@ -11,7 +11,7 @@ namespace LdapTools\Bundle\LdapToolsBundle\Event; use LdapTools\Bundle\LdapToolsBundle\Security\User\LdapUser; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\User\UserInterface; @@ -20,7 +20,7 @@ * * @author Chad Sikorra */ -class LdapLoginEvent extends Event +class LdapLoginEvent extends EventDispatcher { /** * The event name when the login was successful diff --git a/Event/LoadUserEvent.php b/Event/LoadUserEvent.php index 9e49768..b024c97 100644 --- a/Event/LoadUserEvent.php +++ b/Event/LoadUserEvent.php @@ -12,7 +12,7 @@ use LdapTools\Bundle\LdapToolsBundle\Security\User\LdapUser; use LdapTools\Object\LdapObject; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Security\Core\User\UserInterface; /** @@ -20,7 +20,7 @@ * * @author Chad Sikorra */ -class LoadUserEvent extends Event +class LoadUserEvent extends EventDispatcher { /** * The event name that happens before a user is loaded from the user provider. diff --git a/Resources/doc/LDAP-Authentication-Provider.md b/Resources/doc/LDAP-Authentication-Provider.md index 8a6ad73..e8145ef 100644 --- a/Resources/doc/LDAP-Authentication-Provider.md +++ b/Resources/doc/LDAP-Authentication-Provider.md @@ -235,7 +235,7 @@ objects: # app/config/config.yml ldap_tools: general: - schema_folder: "%kernel.root_dir%/Resources/schema" + schema_folder: "%kernel.project_dir%/app/Resources/schema" security: ldap_object_type: 'SymfonyUser' ``` diff --git a/Security/Authentication/Provider/LdapAuthenticationProvider.php b/Security/Authentication/Provider/LdapAuthenticationProvider.php index 6f962fc..44242e6 100644 --- a/Security/Authentication/Provider/LdapAuthenticationProvider.php +++ b/Security/Authentication/Provider/LdapAuthenticationProvider.php @@ -156,7 +156,7 @@ protected function doAuthentication(UserInterface $user, TokenInterface $token) throw new BadCredentialsException($response->getErrorMessage(), $response->getErrorCode()); } - $this->dispatcher->dispatch(LdapLoginEvent::SUCCESS, new LdapLoginEvent($user, $token)); + $this->dispatcher->dispatch(new LdapLoginEvent($user, $token), LdapLoginEvent::SUCCESS); $newToken = new UsernamePasswordToken($user, null, $this->providerKey, $user->getRoles()); $newToken->setAttributes($token->getAttributes()); diff --git a/Security/LdapGuardAuthenticator.php b/Security/LdapGuardAuthenticator.php index 782ab16..c5e3e94 100644 --- a/Security/LdapGuardAuthenticator.php +++ b/Security/LdapGuardAuthenticator.php @@ -211,8 +211,8 @@ public function checkCredentials($credentials, UserInterface $user) $token = new UsernamePasswordToken($user, $credentials['password'], 'ldap-tools', $user->getRoles()); $token->setAttribute('ldap_domain', $credDomain); $this->dispatcher->dispatch( - LdapLoginEvent::SUCCESS, - new LdapLoginEvent($user, $token) + new LdapLoginEvent($user, $token), + LdapLoginEvent::SUCCESS ); } catch (\Exception $e) { $this->hideOrThrow($e, $this->options['hide_user_not_found_exceptions']); @@ -236,7 +236,7 @@ public function onAuthenticationSuccess(Request $request, TokenInterface $token, $token, $providerKey ); - $this->dispatcher->dispatch(AuthenticationHandlerEvent::SUCCESS, $event); + $this->dispatcher->dispatch($event, AuthenticationHandlerEvent::SUCCESS); return $this->options['http_basic'] ? null : $event->getResponse(); } @@ -251,7 +251,7 @@ public function onAuthenticationFailure(Request $request, AuthenticationExceptio $request, $exception ); - $this->dispatcher->dispatch(AuthenticationHandlerEvent::FAILURE, $event); + $this->dispatcher->dispatch($event, AuthenticationHandlerEvent::FAILURE); return $this->options['http_basic'] ? null : $event->getResponse(); } @@ -267,7 +267,7 @@ public function start(Request $request, AuthenticationException $authException = $request, $authException ); - $this->dispatcher->dispatch(AuthenticationHandlerEvent::START, $event); + $this->dispatcher->dispatch($event, AuthenticationHandlerEvent::START); return $event->getResponse(); } diff --git a/Security/User/LdapUser.php b/Security/User/LdapUser.php index ddc1737..b55ec48 100644 --- a/Security/User/LdapUser.php +++ b/Security/User/LdapUser.php @@ -11,14 +11,14 @@ namespace LdapTools\Bundle\LdapToolsBundle\Security\User; use LdapTools\Object\LdapObject; -use Symfony\Component\Security\Core\User\AdvancedUserInterface; +use Symfony\Component\Security\Core\User\UserInterface; /** * Represents a user from LDAP. * * @author Chad Sikorra */ -class LdapUser extends LdapObject implements LdapUserInterface, AdvancedUserInterface, \Serializable +class LdapUser extends LdapObject implements LdapUserInterface, UserInterface, \Serializable { /** * @var array The Symfony roles for this user. diff --git a/Security/User/LdapUserChecker.php b/Security/User/LdapUserChecker.php index 98f0618..cce33fe 100644 --- a/Security/User/LdapUserChecker.php +++ b/Security/User/LdapUserChecker.php @@ -15,16 +15,60 @@ use Symfony\Component\Security\Core\Exception\CredentialsExpiredException; use Symfony\Component\Security\Core\Exception\DisabledException; use Symfony\Component\Security\Core\Exception\LockedException; -use Symfony\Component\Security\Core\User\UserChecker; use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\Security\Core\User\UserCheckerInterface; /** * Interpret extended LDAP codes from authentication to determine the state of the LDAP account. * * @author Chad Sikorra */ -class LdapUserChecker extends UserChecker +class LdapUserChecker implements UserCheckerInterface { + /** + * {@inheritdoc} + */ + public function checkPreAuth(UserInterface $user) + { + if (!$user instanceof LdapUser) { + return; + } + + if (!$user->isAccountNonLocked()) { + $ex = new LockedException('User account is locked.'); + $ex->setUser($user); + throw $ex; + } + + if (!$user->isEnabled()) { + $ex = new DisabledException('User account is disabled.'); + $ex->setUser($user); + throw $ex; + } + + if (!$user->isAccountNonExpired()) { + $ex = new AccountExpiredException('User account has expired.'); + $ex->setUser($user); + throw $ex; + } + } + + /** + * {@inheritdoc} + */ + public function checkPostAuth(UserInterface $user) + { + if (!$user instanceof LdapUser) { + return; + } + + if (!$user->isCredentialsNonExpired()) { + $ex = new CredentialsExpiredException('User credentials have expired.'); + $ex->setUser($user); + throw $ex; + } + } + /** * Based on the LDAP error code and the LDAP type, throw any specific exceptions detected. * diff --git a/Security/User/LdapUserProvider.php b/Security/User/LdapUserProvider.php index 9505f1f..548963c 100644 --- a/Security/User/LdapUserProvider.php +++ b/Security/User/LdapUserProvider.php @@ -88,11 +88,11 @@ public function __construct(LdapManager $ldap, EventDispatcherInterface $dispatc */ public function loadUserByUsername($username) { - $this->dispatcher->dispatch(LoadUserEvent::BEFORE, new LoadUserEvent($username, $this->ldap->getDomainContext())); + $this->dispatcher->dispatch(new LoadUserEvent($username, $this->ldap->getDomainContext()), LoadUserEvent::BEFORE); $ldapUser = $this->getLdapUser('username', $username); $user = $this->constructUserClass($ldapUser); $this->roleMapper->setRoles($user); - $this->dispatcher->dispatch(LoadUserEvent::AFTER, new LoadUserEvent($username, $this->ldap->getDomainContext(), $user, $ldapUser)); + $this->dispatcher->dispatch(new LoadUserEvent($username, $this->ldap->getDomainContext(), $user, $ldapUser), LoadUserEvent::AFTER); return $user; } diff --git a/composer.json b/composer.json index 062857c..03d7ae2 100644 --- a/composer.json +++ b/composer.json @@ -19,15 +19,15 @@ ], "require": { "ldaptools/ldaptools": ">=0.25", - "symfony/framework-bundle": "~2.7|~3.0|~4.0" + "symfony/framework-bundle": "~2.7|~3.0|~4.0|~5.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "~1.0", "phpspec/phpspec": "~3.0", "akeneo/phpspec-skip-example-extension": "~2.0", "doctrine/orm": "~2.4", - "symfony/form": "~2.7|~3.0|~4.0", - "symfony/security-bundle": "~2.7|~3.0|~4.0" + "symfony/form": "~2.7|~3.0|~4.0|~5.0", + "symfony/security-bundle": "~2.7|~3.0|~4.0|~5.0" }, "suggest": { "doctrine/doctrine-bundle": "For LDAP object type integration in Doctrine." diff --git a/spec/LdapTools/Bundle/LdapToolsBundle/Security/Authentication/Provider/LdapAuthenticationProviderSpec.php b/spec/LdapTools/Bundle/LdapToolsBundle/Security/Authentication/Provider/LdapAuthenticationProviderSpec.php index 50aff5a..cb0bd1c 100644 --- a/spec/LdapTools/Bundle/LdapToolsBundle/Security/Authentication/Provider/LdapAuthenticationProviderSpec.php +++ b/spec/LdapTools/Bundle/LdapToolsBundle/Security/Authentication/Provider/LdapAuthenticationProviderSpec.php @@ -211,7 +211,7 @@ function it_should_switch_the_domain_if_the_token_has_the_ldap_domain_set($ldap, function it_should_call_a_login_success_event($token, $dispatcher) { - $dispatcher->dispatch('ldap_tools_bundle.login.success', Argument::type('LdapTools\Bundle\LdapToolsBundle\Event\LdapLoginEvent'))->shouldBeCalled(); + $dispatcher->dispatch(Argument::type('LdapTools\Bundle\LdapToolsBundle\Event\LdapLoginEvent'), 'ldap_tools_bundle.login.success')->shouldBeCalled(); $this->authenticate($token); } diff --git a/spec/LdapTools/Bundle/LdapToolsBundle/Security/LdapGuardAuthenticatorSpec.php b/spec/LdapTools/Bundle/LdapToolsBundle/Security/LdapGuardAuthenticatorSpec.php index 76cb3c3..cd9e29f 100644 --- a/spec/LdapTools/Bundle/LdapToolsBundle/Security/LdapGuardAuthenticatorSpec.php +++ b/spec/LdapTools/Bundle/LdapToolsBundle/Security/LdapGuardAuthenticatorSpec.php @@ -342,26 +342,26 @@ function it_should_call_a_login_success_event($connection, $dispatcher) $connection->execute(new AuthenticationOperation('foo', 'bar'))->shouldBeCalled()->willReturn(new AuthenticationResponse(true)); $this->checkCredentials($credentials, $user)->shouldReturn(true); - $dispatcher->dispatch('ldap_tools_bundle.login.success', new LdapLoginEvent($user, $token))->shouldBeCalled(); + $dispatcher->dispatch(new LdapLoginEvent($user, $token), 'ldap_tools_bundle.login.success')->shouldBeCalled(); } function it_should_call_an_auth_success_handler_event(Request $request, $dispatcher, TokenInterface $token) { - $dispatcher->dispatch('ldap_tools_bundle.guard.login.success', Argument::type('LdapTools\Bundle\LdapToolsBundle\Event\AuthenticationHandlerEvent'))->shouldBeCalled(); + $dispatcher->dispatch(Argument::type('LdapTools\Bundle\LdapToolsBundle\Event\AuthenticationHandlerEvent'), 'ldap_tools_bundle.guard.login.success')->shouldBeCalled(); $this->onAuthenticationSuccess($request, $token, 'foo'); } function it_should_call_an_auth_failure_handler_event(Request $request, $dispatcher) { - $dispatcher->dispatch('ldap_tools_bundle.guard.login.failure', Argument::type('LdapTools\Bundle\LdapToolsBundle\Event\AuthenticationHandlerEvent'))->shouldBeCalled(); + $dispatcher->dispatch(Argument::type('LdapTools\Bundle\LdapToolsBundle\Event\AuthenticationHandlerEvent'), 'ldap_tools_bundle.guard.login.failure')->shouldBeCalled(); $this->onAuthenticationFailure($request, new AuthenticationException('foo')); } function it_should_call_an_auth_start_event(Request $request, $dispatcher) { - $dispatcher->dispatch('ldap_tools_bundle.guard.login.start', Argument::type('LdapTools\Bundle\LdapToolsBundle\Event\AuthenticationHandlerEvent'))->shouldBeCalled(); + $dispatcher->dispatch(Argument::type('LdapTools\Bundle\LdapToolsBundle\Event\AuthenticationHandlerEvent'), 'ldap_tools_bundle.guard.login.start')->shouldBeCalled(); $this->start($request, new AuthenticationException('foo')); } diff --git a/spec/LdapTools/Bundle/LdapToolsBundle/Security/User/LdapUserProviderSpec.php b/spec/LdapTools/Bundle/LdapToolsBundle/Security/User/LdapUserProviderSpec.php index bbd22da..18783c7 100644 --- a/spec/LdapTools/Bundle/LdapToolsBundle/Security/User/LdapUserProviderSpec.php +++ b/spec/LdapTools/Bundle/LdapToolsBundle/Security/User/LdapUserProviderSpec.php @@ -72,8 +72,8 @@ function it_is_initializable() function it_should_load_by_username($dispatcher) { - $dispatcher->dispatch(LoadUserEvent::BEFORE, Argument::type('\LdapTools\Bundle\LdapToolsBundle\Event\LoadUserEvent'))->shouldBeCalledTimes(1); - $dispatcher->dispatch(LoadUserEvent::AFTER, Argument::type('\LdapTools\Bundle\LdapToolsBundle\Event\LoadUserEvent'))->shouldBeCalledTimes(1); + $dispatcher->dispatch(Argument::type('\LdapTools\Bundle\LdapToolsBundle\Event\LoadUserEvent'), LoadUserEvent::BEFORE)->shouldBeCalledTimes(1); + $dispatcher->dispatch(Argument::type('\LdapTools\Bundle\LdapToolsBundle\Event\LoadUserEvent'), LoadUserEvent::AFTER)->shouldBeCalledTimes(1); $this->loadUserByUsername('foo')->shouldBeAnInstanceOf('\LdapTools\Bundle\LdapToolsBundle\Security\User\LdapUser'); }