From a49a4a9e050b7fa2cb3924103b6bdc29b30009dc Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Thu, 15 Jan 2015 23:50:13 -0330 Subject: [PATCH 01/17] Update AdapterChainEvent to take identity/credential rather than request --- .../Authentication/Adapter/AdapterChain.php | 5 ++- .../Adapter/AdapterChainEvent.php | 39 ++++++------------- src/ZfcUser/Controller/UserController.php | 5 ++- 3 files changed, 18 insertions(+), 31 deletions(-) diff --git a/src/ZfcUser/Authentication/Adapter/AdapterChain.php b/src/ZfcUser/Authentication/Adapter/AdapterChain.php index be74abce..60af5792 100644 --- a/src/ZfcUser/Authentication/Adapter/AdapterChain.php +++ b/src/ZfcUser/Authentication/Adapter/AdapterChain.php @@ -44,10 +44,11 @@ public function authenticate() * @return Response|bool * @throws Exception\AuthenticationEventException */ - public function prepareForAuthentication(Request $request) + public function prepareForAuthentication($identity, $credential) { $e = $this->getEvent(); - $e->setRequest($request); + $e->setIdentity($identity); + $e->setCredential($credential); $this->getEventManager()->trigger('authenticate.pre', $e); diff --git a/src/ZfcUser/Authentication/Adapter/AdapterChainEvent.php b/src/ZfcUser/Authentication/Adapter/AdapterChainEvent.php index 232e4f33..b2f29145 100644 --- a/src/ZfcUser/Authentication/Adapter/AdapterChainEvent.php +++ b/src/ZfcUser/Authentication/Adapter/AdapterChainEvent.php @@ -7,11 +7,6 @@ class AdapterChainEvent extends Event { - /** - * @var Request - */ - private $request; - /** * getIdentity * @@ -38,6 +33,17 @@ public function setIdentity($identity = null) $this->setParam('identity', $identity); return $this; } + + public function getCredential() + { + return $this->getParam('credential'); + } + + public function setCredential($credential) + { + $this->setParam('credential', $credential); + return $this; + } /** * getCode @@ -82,27 +88,4 @@ public function setMessages($messages = array()) $this->setParam('messages', $messages); return $this; } - - /** - * getRequest - * - * @return Request - */ - public function getRequest() - { - return $this->getParam('request'); - } - - /** - * setRequest - * - * @param Request $request - * @return AdapterChainEvent - */ - public function setRequest(Request $request) - { - $this->setParam('request', $request); - $this->request = $request; - return $this; - } } diff --git a/src/ZfcUser/Controller/UserController.php b/src/ZfcUser/Controller/UserController.php index c7811feb..d745c08c 100644 --- a/src/ZfcUser/Controller/UserController.php +++ b/src/ZfcUser/Controller/UserController.php @@ -161,7 +161,10 @@ public function authenticateAction() $adapter = $this->zfcUserAuthentication()->getAuthAdapter(); $redirect = $this->params()->fromPost('redirect', $this->params()->fromQuery('redirect', false)); - $result = $adapter->prepareForAuthentication($this->getRequest()); + $result = $adapter->prepareForAuthentication( + $this->params()->fromPost('identity'), + $this->params()->fromPost('credential') + ); // Return early if an adapter returned a response if ($result instanceof Response) { From c8cd71652b6a7de5a9b1aa5e79e6faade8cad500 Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Thu, 15 Jan 2015 23:55:05 -0330 Subject: [PATCH 02/17] Simplified Authentication Storage - Renamed from `Db` to `Mapper` - Added SM aliases for easier overriding (Mapper and Session) --- Module.php | 1 - config/module.config.php | 5 +- src/ZfcUser/Authentication/Storage/Db.php | 179 ------------------ src/ZfcUser/Authentication/Storage/Mapper.php | 104 ++++++++++ .../Factory/AuthenticationServiceFactory.php | 2 +- 5 files changed, 109 insertions(+), 182 deletions(-) delete mode 100644 src/ZfcUser/Authentication/Storage/Db.php create mode 100644 src/ZfcUser/Authentication/Storage/Mapper.php diff --git a/Module.php b/Module.php index c3537950..4e0114b0 100644 --- a/Module.php +++ b/Module.php @@ -64,7 +64,6 @@ public function getServiceConfig() return array( 'invokables' => array( 'ZfcUser\Authentication\Adapter\Db' => 'ZfcUser\Authentication\Adapter\Db', - 'ZfcUser\Authentication\Storage\Db' => 'ZfcUser\Authentication\Storage\Db', 'ZfcUser\Form\Login' => 'ZfcUser\Form\Login', 'zfcuser_user_service' => 'ZfcUser\Service\User', ), diff --git a/config/module.config.php b/config/module.config.php index 8263fa3c..79bc4516 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -40,14 +40,15 @@ 'service_manager' => array( 'invokables' => array( 'ZfcUser\Authentication\Adapter\Db' => 'ZfcUser\Authentication\Adapter\Db', - 'ZfcUser\Authentication\Storage\Db' => 'ZfcUser\Authentication\Storage\Db', 'ZfcUser\Form\Login' => 'ZfcUser\Form\Login', 'zfcuser_user_service' => 'ZfcUser\Service\User', + 'zfcuser_authentication_storage_backend_session' => 'Zend\Authentication\Storage\Session', ), 'factories' => array( 'zfcuser_module_options' => 'ZfcUser\Factory\ModuleOptionsFactory', 'zfcuser_auth_service' => 'ZfcUser\Factory\AuthenticationServiceFactory', 'ZfcUser\Authentication\Adapter\AdapterChain' => 'ZfcUser\Authentication\Adapter\AdapterChainServiceFactory', + 'ZfcUser\Authentication\Storage\Mapper' => 'ZfcUser\Factory\Authentication\Storage\MapperFactory', 'zfcuser_login_form' => 'ZfcUser\Factory\Form\LoginFormFactory', 'zfcuser_register_form' => 'ZfcUser\Factory\Form\RegisterFormFactory', 'zfcuser_change_password_form' => 'ZfcUser\Factory\Form\ChangePasswordFormFactory', @@ -58,6 +59,8 @@ 'aliases' => array( 'zfcuser_register_form_hydrator' => 'zfcuser_user_hydrator', 'zfcuser_zend_db_adapter' => 'Zend\Db\Adapter\Adapter', + 'zfcuser_authentication_storage' => 'ZfcUser\Authentication\Storage\Mapper', + 'zfcuser_authentication_storage_backend' => 'zfcuser_authentication_storage_backend_session', ), ), 'controller_plugins' => array( diff --git a/src/ZfcUser/Authentication/Storage/Db.php b/src/ZfcUser/Authentication/Storage/Db.php deleted file mode 100644 index 3a5b1d36..00000000 --- a/src/ZfcUser/Authentication/Storage/Db.php +++ /dev/null @@ -1,179 +0,0 @@ -getStorage()->isEmpty()) { - return true; - } - $identity = $this->read(); - if ($identity === null) { - $this->clear(); - return true; - } - - return false; - } - - /** - * Returns the contents of storage - * - * Behavior is undefined when storage is empty. - * - * @throws \Zend\Authentication\Exception\InvalidArgumentException If reading contents from storage is impossible - * @return mixed - */ - public function read() - { - if (null !== $this->resolvedIdentity) { - return $this->resolvedIdentity; - } - - $identity = $this->getStorage()->read(); - - if (is_int($identity) || is_scalar($identity)) { - $identity = $this->getMapper()->findById($identity); - } - - if ($identity) { - $this->resolvedIdentity = $identity; - } else { - $this->resolvedIdentity = null; - } - - return $this->resolvedIdentity; - } - - /** - * Writes $contents to storage - * - * @param mixed $contents - * @throws \Zend\Authentication\Exception\InvalidArgumentException If writing $contents to storage is impossible - * @return void - */ - public function write($contents) - { - $this->resolvedIdentity = null; - $this->getStorage()->write($contents); - } - - /** - * Clears contents from storage - * - * @throws \Zend\Authentication\Exception\InvalidArgumentException If clearing contents from storage is impossible - * @return void - */ - public function clear() - { - $this->resolvedIdentity = null; - $this->getStorage()->clear(); - } - - /** - * getStorage - * - * @return Storage\StorageInterface - */ - public function getStorage() - { - if (null === $this->storage) { - $this->setStorage(new Storage\Session); - } - return $this->storage; - } - - /** - * setStorage - * - * @param Storage\StorageInterface $storage - * @access public - * @return Db - */ - public function setStorage(Storage\StorageInterface $storage) - { - $this->storage = $storage; - return $this; - } - - /** - * getMapper - * - * @return UserMapper - */ - public function getMapper() - { - if (null === $this->mapper) { - $this->mapper = $this->getServiceManager()->get('zfcuser_user_mapper'); - } - return $this->mapper; - } - - /** - * setMapper - * - * @param UserMapper $mapper - * @return Db - */ - public function setMapper(UserMapper $mapper) - { - $this->mapper = $mapper; - return $this; - } - - /** - * Retrieve service manager instance - * - * @return ServiceManager - */ - public function getServiceManager() - { - return $this->serviceManager; - } - - /** - * Set service manager instance - * - * @param ServiceManager $locator - * @return void - */ - public function setServiceManager(ServiceManager $serviceManager) - { - $this->serviceManager = $serviceManager; - } -} diff --git a/src/ZfcUser/Authentication/Storage/Mapper.php b/src/ZfcUser/Authentication/Storage/Mapper.php new file mode 100644 index 00000000..e91138e1 --- /dev/null +++ b/src/ZfcUser/Authentication/Storage/Mapper.php @@ -0,0 +1,104 @@ +mapper = $mapper; + $this->storage = $storage; + } + + /** + * Returns true if and only if storage is empty + * + * @throws \Zend\Authentication\Exception\InvalidArgumentException If it is impossible to determine whether + * storage is empty or not + * @return boolean + */ + public function isEmpty() + { + if ($this->storage->isEmpty()) { + return true; + } + $identity = $this->read(); + if ($identity === null) { + $this->clear(); + return true; + } + + return false; + } + + /** + * Returns the contents of storage + * + * Behavior is undefined when storage is empty. + * + * @throws \Zend\Authentication\Exception\InvalidArgumentException If reading contents from storage is impossible + * @return mixed + */ + public function read() + { + if (null !== $this->resolvedIdentity) { + return $this->resolvedIdentity; + } + + $identity = $this->storage->read(); + + if (is_int($identity) || is_scalar($identity)) { + $identity = $this->mapper->findById($identity); + } + + $this->resolvedIdentity = $identity instanceof UserEntity + ? $identity + : null; + + return $this->resolvedIdentity; + } + + /** + * Writes $contents to storage + * + * @param mixed $contents + * @throws \Zend\Authentication\Exception\InvalidArgumentException If writing $contents to storage is impossible + * @return void + */ + public function write($contents) + { + $this->resolvedIdentity = null; + $this->storage->write($contents); + } + + /** + * Clears contents from storage + * + * @throws \Zend\Authentication\Exception\InvalidArgumentException If clearing contents from storage is impossible + * @return void + */ + public function clear() + { + $this->resolvedIdentity = null; + $this->storage->clear(); + } +} diff --git a/src/ZfcUser/Factory/AuthenticationServiceFactory.php b/src/ZfcUser/Factory/AuthenticationServiceFactory.php index a38afcf5..a50d046a 100644 --- a/src/ZfcUser/Factory/AuthenticationServiceFactory.php +++ b/src/ZfcUser/Factory/AuthenticationServiceFactory.php @@ -15,7 +15,7 @@ class AuthenticationServiceFactory implements FactoryInterface public function createService(ServiceLocatorInterface $serviceLocator) { /* @var $authStorage Storage\StorageInterface */ - $authStorage = $serviceLocator->get('ZfcUser\Authentication\Storage\Db'); + $authStorage = $serviceLocator->get('zfcuser_authentication_storage'); /* @var $authAdapter Adapter\AdapterInterface */ $authAdapter = $serviceLocator->get('ZfcUser\Authentication\Adapter\AdapterChain'); From 6845307feb05962bc1c8b411f7639b4a79ed8727 Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Thu, 15 Jan 2015 23:57:17 -0330 Subject: [PATCH 03/17] Rewrite the Mapper-based Authentication Adapter - Externalize the password hashing and verification (CredentialProcessor) - Generalize Mapper adapter to work with any mapper find method - Provide factories for producing MapperUsername and MapperEmail adapters - Update dist configuration with new adapter name --- Module.php | 1 - config/module.config.php | 5 +- config/zfcuser.global.php.dist | 2 +- src/ZfcUser/Authentication/Adapter/Db.php | 257 ------------------ src/ZfcUser/Authentication/Adapter/Mapper.php | 80 ++++++ .../Adapter/MapperEmailFactory.php | 23 ++ .../Adapter/MapperUsernameFactory.php | 23 ++ .../CredentialProcessor/BcryptFactory.php | 21 ++ .../Authentication/Storage/MapperFactory.php | 22 ++ 9 files changed, 174 insertions(+), 260 deletions(-) delete mode 100644 src/ZfcUser/Authentication/Adapter/Db.php create mode 100644 src/ZfcUser/Authentication/Adapter/Mapper.php create mode 100644 src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php create mode 100644 src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php create mode 100644 src/ZfcUser/Factory/Authentication/CredentialProcessor/BcryptFactory.php create mode 100644 src/ZfcUser/Factory/Authentication/Storage/MapperFactory.php diff --git a/Module.php b/Module.php index 4e0114b0..a4ea73ef 100644 --- a/Module.php +++ b/Module.php @@ -63,7 +63,6 @@ public function getServiceConfig() { return array( 'invokables' => array( - 'ZfcUser\Authentication\Adapter\Db' => 'ZfcUser\Authentication\Adapter\Db', 'ZfcUser\Form\Login' => 'ZfcUser\Form\Login', 'zfcuser_user_service' => 'ZfcUser\Service\User', ), diff --git a/config/module.config.php b/config/module.config.php index 79bc4516..9cfbade0 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -39,7 +39,6 @@ ), 'service_manager' => array( 'invokables' => array( - 'ZfcUser\Authentication\Adapter\Db' => 'ZfcUser\Authentication\Adapter\Db', 'ZfcUser\Form\Login' => 'ZfcUser\Form\Login', 'zfcuser_user_service' => 'ZfcUser\Service\User', 'zfcuser_authentication_storage_backend_session' => 'Zend\Authentication\Storage\Session', @@ -48,6 +47,9 @@ 'zfcuser_module_options' => 'ZfcUser\Factory\ModuleOptionsFactory', 'zfcuser_auth_service' => 'ZfcUser\Factory\AuthenticationServiceFactory', 'ZfcUser\Authentication\Adapter\AdapterChain' => 'ZfcUser\Authentication\Adapter\AdapterChainServiceFactory', + 'ZfcUser\Authentication\Adapter\MapperUsername' => 'ZfcUser\Factory\Authentication\Adapter\MapperUsernameFactory', + 'ZfcUser\Authentication\Adapter\MapperEmail' => 'ZfcUser\Factory\Authentication\Adapter\MapperEmailFactory', + 'zfcuser_authentication_credentialprocessor_bcrypt' => 'ZfcUser\Factory\Authentication\CredentialProcessor\BcryptFactory', 'ZfcUser\Authentication\Storage\Mapper' => 'ZfcUser\Factory\Authentication\Storage\MapperFactory', 'zfcuser_login_form' => 'ZfcUser\Factory\Form\LoginFormFactory', 'zfcuser_register_form' => 'ZfcUser\Factory\Form\RegisterFormFactory', @@ -59,6 +61,7 @@ 'aliases' => array( 'zfcuser_register_form_hydrator' => 'zfcuser_user_hydrator', 'zfcuser_zend_db_adapter' => 'Zend\Db\Adapter\Adapter', + 'zfcuser_authentication_credentialprocessor' => 'zfcuser_authentication_credentialprocessor_bcrypt', 'zfcuser_authentication_storage' => 'ZfcUser\Authentication\Storage\Mapper', 'zfcuser_authentication_storage_backend' => 'zfcuser_authentication_storage_backend_session', ), diff --git a/config/zfcuser.global.php.dist b/config/zfcuser.global.php.dist index f0f007c9..44ba551f 100644 --- a/config/zfcuser.global.php.dist +++ b/config/zfcuser.global.php.dist @@ -50,7 +50,7 @@ $settings = array( * Default value: array containing 'ZfcUser\Authentication\Adapter\Db' with priority 100 * Accepted values: array containing services that implement 'ZfcUser\Authentication\Adapter\ChainableAdapter' */ - 'auth_adapters' => array( 100 => 'ZfcUser\Authentication\Adapter\Db' ), + 'auth_adapters' => array( 100 => 'ZfcUser\Authentication\Adapter\MapperEmail' ), /** * Enable Display Name diff --git a/src/ZfcUser/Authentication/Adapter/Db.php b/src/ZfcUser/Authentication/Adapter/Db.php deleted file mode 100644 index 3b59202a..00000000 --- a/src/ZfcUser/Authentication/Adapter/Db.php +++ /dev/null @@ -1,257 +0,0 @@ -getStorage()->clear(); - } - - public function authenticate(AuthenticationEvent $event) - { - if ($this->isSatisfied()) { - $storage = $this->getStorage()->read(); - $event->setIdentity($storage['identity']) - ->setCode(AuthenticationResult::SUCCESS) - ->setMessages(array('Authentication successful.')); - return; - } - - $identity = $event->getRequest()->getPost()->get('identity'); - $credential = $event->getRequest()->getPost()->get('credential'); - $credential = $this->preProcessCredential($credential); - $userObject = null; - - // Cycle through the configured identity sources and test each - $fields = $this->getOptions()->getAuthIdentityFields(); - while (!is_object($userObject) && count($fields) > 0) { - $mode = array_shift($fields); - switch ($mode) { - case 'username': - $userObject = $this->getMapper()->findByUsername($identity); - break; - case 'email': - $userObject = $this->getMapper()->findByEmail($identity); - break; - } - } - - if (!$userObject) { - $event->setCode(AuthenticationResult::FAILURE_IDENTITY_NOT_FOUND) - ->setMessages(array('A record with the supplied identity could not be found.')); - $this->setSatisfied(false); - return false; - } - - if ($this->getOptions()->getEnableUserState()) { - // Don't allow user to login if state is not in allowed list - if (!in_array($userObject->getState(), $this->getOptions()->getAllowedLoginStates())) { - $event->setCode(AuthenticationResult::FAILURE_UNCATEGORIZED) - ->setMessages(array('A record with the supplied identity is not active.')); - $this->setSatisfied(false); - return false; - } - } - - $cryptoService = $this->getHydrator()->getCryptoService(); - if (!$cryptoService->verify($credential, $userObject->getPassword())) { - // Password does not match - $event->setCode(AuthenticationResult::FAILURE_CREDENTIAL_INVALID) - ->setMessages(array('Supplied credential is invalid.')); - $this->setSatisfied(false); - return false; - } elseif ($cryptoService instanceof Bcrypt) { - // Update user's password hash if the cost parameter has changed - $this->updateUserPasswordHash($userObject, $credential, $cryptoService); - } - - // regen the id - SessionContainer::getDefaultManager()->regenerateId(); - - // Success! - $event->setIdentity($userObject->getId()); - - $this->setSatisfied(true); - $storage = $this->getStorage()->read(); - $storage['identity'] = $event->getIdentity(); - $this->getStorage()->write($storage); - $event->setCode(AuthenticationResult::SUCCESS) - ->setMessages(array('Authentication successful.')); - } - - protected function updateUserPasswordHash(UserEntity $user, $password, Bcrypt $bcrypt) - { - $hash = explode('$', $user->getPassword()); - if ($hash[2] === $bcrypt->getCost()) { - return; - } - $user = $this->getHydrator()->hydrate(compact('password'), $user); - $this->getMapper()->update($user); - } - - public function preprocessCredential($credential) - { - if (is_callable($this->credentialPreprocessor)) { - return call_user_func($this->credentialPreprocessor, $credential); - } - return $credential; - } - - /** - * getMapper - * - * @return UserMapper - */ - public function getMapper() - { - if (!$this->mapper instanceof UserMapper) { - $this->setMapper($this->serviceManager->get('zfcuser_user_mapper')); - } - return $this->mapper; - } - - /** - * setMapper - * - * @param UserMapper $mapper - * @return Db - */ - public function setMapper(UserMapper $mapper) - { - $this->mapper = $mapper; - return $this; - } - - /** - * Lazy-loads a hydrator from the service manager - * - * @return Hydrator - */ - public function getHydrator() - { - if (!$this->hydrator instanceof Hydrator) { - $this->setHydrator($this->serviceManager->get('zfcuser_user_hydrator')); - } - return $this->hydrator; - } - - /** - * Set the hydrator - * - * @param Hydrator $hydrator - */ - public function setHydrator(Hydrator $hydrator) - { - $this->hydrator = $hydrator; - } - - /** - * Get credentialPreprocessor. - * - * @return callable - */ - public function getCredentialPreprocessor() - { - return $this->credentialPreprocessor; - } - - /** - * Set credentialPreprocessor. - * - * @param callable $credentialPreprocessor the value to be set - * @throws InvalidArgumentException when argument is not callable - */ - public function setCredentialPreprocessor($credentialPreprocessor) - { - if (!is_callable($credentialPreprocessor)) { - $message = sprintf( - "Credential Preprocessor must be callable, [%s] given", - gettype($credentialPreprocessor) - ); - throw new InvalidArgumentException($message); - } - $this->credentialPreprocessor = $credentialPreprocessor; - } - - /** - * Retrieve service manager instance - * - * @return ServiceManager - */ - public function getServiceManager() - { - return $this->serviceManager; - } - - /** - * Set service manager instance - * - * @param ServiceManager $locator - * @return void - */ - public function setServiceManager(ServiceManager $serviceManager) - { - $this->serviceManager = $serviceManager; - } - - /** - * @param AuthenticationOptions $options - */ - public function setOptions(AuthenticationOptions $options) - { - $this->options = $options; - } - - /** - * @return AuthenticationOptions - */ - public function getOptions() - { - if (!$this->options instanceof AuthenticationOptions) { - $this->setOptions($this->serviceManager->get('zfcuser_module_options')); - } - return $this->options; - } -} diff --git a/src/ZfcUser/Authentication/Adapter/Mapper.php b/src/ZfcUser/Authentication/Adapter/Mapper.php new file mode 100644 index 00000000..8240ba76 --- /dev/null +++ b/src/ZfcUser/Authentication/Adapter/Mapper.php @@ -0,0 +1,80 @@ +mapper = $mapper; + $this->mapperMethod = $mapperMethod; + $this->credentialProcessor = $validator; + } + + /** + * Called when user id logged out + */ + public function logout() + { + $this->getStorage()->clear(); + } + + public function authenticate(AuthenticationEvent $event) + { + if ($this->isSatisfied()) { + $storage = $this->getStorage()->read(); + $event->setIdentity($storage['identity']) + ->setCode(AuthenticationResult::SUCCESS) + ->setMessages(array('Authentication successful.')); + return; + } + + $userObject = call_user_func(array($this->mapper, $this->mapperMethod), $event->getIdentity()); + + if (!$userObject instanceof UserEntity) { + $event->setCode(AuthenticationResult::FAILURE_IDENTITY_NOT_FOUND) + ->setMessages(array('A record with the supplied identity could not be found.')); + $this->setSatisfied(false); + return false; + } + + if (!$this->credentialProcessor->verify($event->getCredential(), $userObject->getPassword())) { + // Password does not match + $event->setCode(AuthenticationResult::FAILURE_CREDENTIAL_INVALID) + ->setMessages(array('Supplied credential is invalid.')); + $this->setSatisfied(false); + return false; + } + + // Success! + $event->setIdentity($userObject->getId()); + + $this->setSatisfied(true); + $storage = $this->getStorage()->read(); + $storage['identity'] = $event->getIdentity(); + $this->getStorage()->write($storage); + $event->setCode(AuthenticationResult::SUCCESS) + ->setMessages(array('Authentication successful.')); + } +} diff --git a/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php b/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php new file mode 100644 index 00000000..d68cbd34 --- /dev/null +++ b/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php @@ -0,0 +1,23 @@ +get('zfcuser_module_options'); + + return new Mapper( + $serviceLocator->get('zfcuser_user_mapper'), + 'findByEmail', + $serviceLocator->get('zfcuser_authentication_credentialprocessor') + ); + } +} diff --git a/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php b/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php new file mode 100644 index 00000000..479fe4d5 --- /dev/null +++ b/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php @@ -0,0 +1,23 @@ +get('zfcuser_module_options'); + + return new Mapper( + $serviceLocator->get('zfcuser_user_mapper'), + 'findByUsername', + $serviceLocator->get('zfcuser_authentication_credentialprocessor') + ); + } +} diff --git a/src/ZfcUser/Factory/Authentication/CredentialProcessor/BcryptFactory.php b/src/ZfcUser/Factory/Authentication/CredentialProcessor/BcryptFactory.php new file mode 100644 index 00000000..7b9340e0 --- /dev/null +++ b/src/ZfcUser/Factory/Authentication/CredentialProcessor/BcryptFactory.php @@ -0,0 +1,21 @@ +get('zfcuser_module_options'); + + return new Bcrypt(array( + 'cost' => $options->getPasswordCost() + )); + } +} diff --git a/src/ZfcUser/Factory/Authentication/Storage/MapperFactory.php b/src/ZfcUser/Factory/Authentication/Storage/MapperFactory.php new file mode 100644 index 00000000..15c7064c --- /dev/null +++ b/src/ZfcUser/Factory/Authentication/Storage/MapperFactory.php @@ -0,0 +1,22 @@ +get('zfcuser_module_options'); + + return new Mapper( + $serviceLocator->get('zfcuser_user_mapper'), + $serviceLocator->get('zfcuser_authentication_storage_backend') + ); + } +} From 64d37c3497f44ccb77b382111fbe1b28ca3b7ebb Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Fri, 16 Jan 2015 00:01:56 -0330 Subject: [PATCH 04/17] In AdapterChainEvent, clear credential if identity is cleared --- src/ZfcUser/Authentication/Adapter/AdapterChainEvent.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ZfcUser/Authentication/Adapter/AdapterChainEvent.php b/src/ZfcUser/Authentication/Adapter/AdapterChainEvent.php index b2f29145..9a5dd392 100644 --- a/src/ZfcUser/Authentication/Adapter/AdapterChainEvent.php +++ b/src/ZfcUser/Authentication/Adapter/AdapterChainEvent.php @@ -27,6 +27,7 @@ public function setIdentity($identity = null) { if (null === $identity) { // Setting the identity to null resets the code and messages. + $this->setCredential(); $this->setCode(); $this->setMessages(); } @@ -39,7 +40,7 @@ public function getCredential() return $this->getParam('credential'); } - public function setCredential($credential) + public function setCredential($credential = null) { $this->setParam('credential', $credential); return $this; From 96d520059ef5bca522bab3e49b889f94e3456b15 Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Fri, 16 Jan 2015 00:18:31 -0330 Subject: [PATCH 05/17] Allow setting Mapper auth adapter storage from constructor --- src/ZfcUser/Authentication/Adapter/Mapper.php | 6 +++++- .../Factory/Authentication/Adapter/MapperEmailFactory.php | 3 ++- .../Authentication/Adapter/MapperUsernameFactory.php | 3 ++- .../Authentication/Adapter/{DbTest.php => MapperTest.php} | 0 .../Authentication/Storage/{DbTest.php => MapperTest.php} | 0 5 files changed, 9 insertions(+), 3 deletions(-) rename tests/ZfcUserTest/Authentication/Adapter/{DbTest.php => MapperTest.php} (100%) rename tests/ZfcUserTest/Authentication/Storage/{DbTest.php => MapperTest.php} (100%) diff --git a/src/ZfcUser/Authentication/Adapter/Mapper.php b/src/ZfcUser/Authentication/Adapter/Mapper.php index 8240ba76..120e7c54 100644 --- a/src/ZfcUser/Authentication/Adapter/Mapper.php +++ b/src/ZfcUser/Authentication/Adapter/Mapper.php @@ -7,6 +7,7 @@ use ZfcUser\Entity\UserInterface as UserEntity; use ZfcUser\Mapper\UserInterface as UserMapper; use Zend\Crypt\Password\PasswordInterface; +use Zend\Authentication\Storage\StorageInterface; class Mapper extends AbstractAdapter { @@ -25,11 +26,14 @@ class Mapper extends AbstractAdapter */ protected $credentialProcessor; - public function __construct(UserMapper $mapper, $mapperMethod, PasswordInterface $validator) + public function __construct(UserMapper $mapper, $mapperMethod, PasswordInterface $validator, StorageInterface $storage = null) { $this->mapper = $mapper; $this->mapperMethod = $mapperMethod; $this->credentialProcessor = $validator; + if (!is_null($storage)) { + $this->setStorage($storage); + } } /** diff --git a/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php b/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php index d68cbd34..323216bb 100644 --- a/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php +++ b/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php @@ -17,7 +17,8 @@ public function createService(ServiceLocatorInterface $serviceLocator) return new Mapper( $serviceLocator->get('zfcuser_user_mapper'), 'findByEmail', - $serviceLocator->get('zfcuser_authentication_credentialprocessor') + $serviceLocator->get('zfcuser_authentication_credentialprocessor'), + $serviceLocator->get('zfcuser_authentication_storage') ); } } diff --git a/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php b/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php index 479fe4d5..62b0b947 100644 --- a/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php +++ b/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php @@ -17,7 +17,8 @@ public function createService(ServiceLocatorInterface $serviceLocator) return new Mapper( $serviceLocator->get('zfcuser_user_mapper'), 'findByUsername', - $serviceLocator->get('zfcuser_authentication_credentialprocessor') + $serviceLocator->get('zfcuser_authentication_credentialprocessor'), + $serviceLocator->get('zfcuser_authentication_storage') ); } } diff --git a/tests/ZfcUserTest/Authentication/Adapter/DbTest.php b/tests/ZfcUserTest/Authentication/Adapter/MapperTest.php similarity index 100% rename from tests/ZfcUserTest/Authentication/Adapter/DbTest.php rename to tests/ZfcUserTest/Authentication/Adapter/MapperTest.php diff --git a/tests/ZfcUserTest/Authentication/Storage/DbTest.php b/tests/ZfcUserTest/Authentication/Storage/MapperTest.php similarity index 100% rename from tests/ZfcUserTest/Authentication/Storage/DbTest.php rename to tests/ZfcUserTest/Authentication/Storage/MapperTest.php From 1b47a8289f7e9fd62fa6d10259861ad4bdc2d44f Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Fri, 16 Jan 2015 23:32:05 -0330 Subject: [PATCH 06/17] Rewrite ZfcUser\Authentication\Adapter\AdapterChain - Now just a priority list of Zend\Authentication\Adapter\AbstractAdapter instances - Eliminated Storage from collaborator list (AuthenticationService handles this) - Eliminated some obsoleted classes (AbstractAdapter, AdapterChainEvent, ChainableAdapter, OptionsNotFoundException) --- Module.php | 1 - config/module.config.php | 2 +- .../Adapter/AbstractAdapter.php | 70 -------- .../Authentication/Adapter/AdapterChain.php | 149 ++++-------------- .../Adapter/AdapterChainEvent.php | 92 ----------- .../Adapter/AdapterChainServiceFactory.php | 74 --------- .../Adapter/ChainableAdapter.php | 8 - .../Exception/OptionsNotFoundException.php | 10 -- src/ZfcUser/Authentication/Adapter/Mapper.php | 64 +++----- src/ZfcUser/Controller/UserController.php | 21 +-- .../Adapter/AdapterChainFactory.php | 26 +++ .../Adapter/MapperEmailFactory.php | 3 +- .../Adapter/MapperUsernameFactory.php | 3 +- 13 files changed, 83 insertions(+), 440 deletions(-) delete mode 100644 src/ZfcUser/Authentication/Adapter/AbstractAdapter.php delete mode 100644 src/ZfcUser/Authentication/Adapter/AdapterChainEvent.php delete mode 100644 src/ZfcUser/Authentication/Adapter/AdapterChainServiceFactory.php delete mode 100644 src/ZfcUser/Authentication/Adapter/ChainableAdapter.php delete mode 100644 src/ZfcUser/Authentication/Adapter/Exception/OptionsNotFoundException.php create mode 100644 src/ZfcUser/Factory/Authentication/Adapter/AdapterChainFactory.php diff --git a/Module.php b/Module.php index a4ea73ef..6a6bef79 100644 --- a/Module.php +++ b/Module.php @@ -69,7 +69,6 @@ public function getServiceConfig() 'factories' => array( 'zfcuser_module_options' => 'ZfcUser\Factory\ModuleOptionsFactory', 'zfcuser_auth_service' => 'ZfcUser\Factory\AuthenticationServiceFactory', - 'ZfcUser\Authentication\Adapter\AdapterChain' => 'ZfcUser\Authentication\Adapter\AdapterChainServiceFactory', 'zfcuser_login_form' => 'ZfcUser\Factory\Form\LoginFormFactory', 'zfcuser_register_form' => 'ZfcUser\Factory\Form\RegisterFormFactory', 'zfcuser_user_mapper' => 'ZfcUser\Factory\UserMapperFactory', diff --git a/config/module.config.php b/config/module.config.php index 9cfbade0..9adac840 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -46,7 +46,7 @@ 'factories' => array( 'zfcuser_module_options' => 'ZfcUser\Factory\ModuleOptionsFactory', 'zfcuser_auth_service' => 'ZfcUser\Factory\AuthenticationServiceFactory', - 'ZfcUser\Authentication\Adapter\AdapterChain' => 'ZfcUser\Authentication\Adapter\AdapterChainServiceFactory', + 'ZfcUser\Authentication\Adapter\AdapterChain' => 'ZfcUser\Factory\Authentication\Adapter\AdapterChainFactory', 'ZfcUser\Authentication\Adapter\MapperUsername' => 'ZfcUser\Factory\Authentication\Adapter\MapperUsernameFactory', 'ZfcUser\Authentication\Adapter\MapperEmail' => 'ZfcUser\Factory\Authentication\Adapter\MapperEmailFactory', 'zfcuser_authentication_credentialprocessor_bcrypt' => 'ZfcUser\Factory\Authentication\CredentialProcessor\BcryptFactory', diff --git a/src/ZfcUser/Authentication/Adapter/AbstractAdapter.php b/src/ZfcUser/Authentication/Adapter/AbstractAdapter.php deleted file mode 100644 index 56924cc4..00000000 --- a/src/ZfcUser/Authentication/Adapter/AbstractAdapter.php +++ /dev/null @@ -1,70 +0,0 @@ -storage) { - $this->setStorage(new SessionStorage(get_class($this))); - } - - return $this->storage; - } - - /** - * Sets the persistent storage handler - * - * @param StorageInterface $storage - * @return AbstractAdapter Provides a fluent interface - */ - public function setStorage(StorageInterface $storage) - { - $this->storage = $storage; - return $this; - } - - /** - * Check if this adapter is satisfied or not - * - * @return bool - */ - public function isSatisfied() - { - $storage = $this->getStorage()->read(); - return (isset($storage['is_satisfied']) && true === $storage['is_satisfied']); - } - - /** - * Set if this adapter is satisfied or not - * - * @param bool $bool - * @return AbstractAdapter - */ - public function setSatisfied($bool = true) - { - $storage = $this->getStorage(); - $data = $storage->read() ?: array(); - - $data['is_satisfied'] = (bool) $bool; - $storage->write($data); - - return $this; - } -} diff --git a/src/ZfcUser/Authentication/Adapter/AdapterChain.php b/src/ZfcUser/Authentication/Adapter/AdapterChain.php index 60af5792..9485ab9a 100644 --- a/src/ZfcUser/Authentication/Adapter/AdapterChain.php +++ b/src/ZfcUser/Authentication/Adapter/AdapterChain.php @@ -2,140 +2,49 @@ namespace ZfcUser\Authentication\Adapter; -use Zend\Authentication\Adapter\AdapterInterface; -use Zend\Authentication\Result as AuthenticationResult; -use Zend\EventManager\Event; -use Zend\Stdlib\RequestInterface as Request; -use Zend\Stdlib\ResponseInterface as Response; -use ZfcBase\EventManager\EventProvider; -use ZfcUser\Exception; +use Zend\Authentication\Adapter\AbstractAdapter; +use Zend\Stdlib\PriorityList; +use Zend\Authentication\Result; -class AdapterChain extends EventProvider implements AdapterInterface +class AdapterChain extends AbstractAdapter { /** - * @var AdapterChainEvent + * @var PriorityList */ - protected $event; - - /** - * Returns the authentication result - * - * @return AuthenticationResult - */ - public function authenticate() + protected $adapters; + + public function __construct() { - $e = $this->getEvent(); - - $result = new AuthenticationResult( - $e->getCode(), - $e->getIdentity(), - $e->getMessages() - ); - - $this->resetAdapters(); - - return $result; - } - - /** - * prepareForAuthentication - * - * @param Request $request - * @return Response|bool - * @throws Exception\AuthenticationEventException - */ - public function prepareForAuthentication($identity, $credential) - { - $e = $this->getEvent(); - $e->setIdentity($identity); - $e->setCredential($credential); - - $this->getEventManager()->trigger('authenticate.pre', $e); - - $result = $this->getEventManager()->trigger('authenticate', $e, function ($test) { - return ($test instanceof Response); - }); - - if ($result->stopped()) { - if ($result->last() instanceof Response) { - return $result->last(); - } - - throw new Exception\AuthenticationEventException( - sprintf( - 'Auth event was stopped without a response. Got "%s" instead', - is_object($result->last()) ? get_class($result->last()) : gettype($result->last()) - ) - ); - } - - if ($e->getIdentity()) { - $this->getEventManager()->trigger('authenticate.success', $e); - return true; - } - - $this->getEventManager()->trigger('authenticate.fail', $e); - return false; + $this->adapters = new PriorityList(); } - /** - * resetAdapters - * - * @return AdapterChain - */ - public function resetAdapters() + public function attach($name, AbstractAdapter $adapter, $priority = 1) { - $listeners = $this->getEventManager()->getListeners('authenticate'); - foreach ($listeners as $listener) { - $listener = $listener->getCallback(); - if (is_array($listener) && $listener[0] instanceof ChainableAdapter) { - $listener[0]->getStorage()->clear(); - } - } + $this->adapters->insert($name, $adapter, $priority); return $this; } - + /** - * logoutAdapters - * - * @return AdapterChain - */ - public function logoutAdapters() - { - //Adapters might need to perform additional cleanup after logout - $this->getEventManager()->trigger('logout', $this->getEvent()); - } - - /** - * Get the auth event - * - * @return AdapterChainEvent - */ - public function getEvent() - { - if (null === $this->event) { - $this->setEvent(new AdapterChainEvent); - $this->event->setTarget($this); - } - return $this->event; - } - - /** - * Set an event to use during dispatch - * - * By default, will re-cast to AdapterChainEvent if another event type is provided. + * Returns the authentication result * - * @param Event $e - * @return AdapterChain + * @return AuthenticationResult */ - public function setEvent(Event $e) + public function authenticate() { - if (!$e instanceof AdapterChainEvent) { - $eventParams = $e->getParams(); - $e = new AdapterChainEvent(); - $e->setParams($eventParams); + foreach ( $this->adapters as $adapter ) { + $adapter->setIdentity($this->getIdentity()); + $adapter->setCredential($this->getCredential()); + + $result = $adapter->authenticate(); + if ( $result->isValid() ) { + return $result; + } } - $this->event = $e; - return $this; + + //@TODO throw an exception if no result? (no adapters tried) + + return $result instanceof Result + ? $result + : new Result(Result::FAILURE_UNCATEGORIZED, null); } } diff --git a/src/ZfcUser/Authentication/Adapter/AdapterChainEvent.php b/src/ZfcUser/Authentication/Adapter/AdapterChainEvent.php deleted file mode 100644 index 9a5dd392..00000000 --- a/src/ZfcUser/Authentication/Adapter/AdapterChainEvent.php +++ /dev/null @@ -1,92 +0,0 @@ -getParam('identity'); - } - - /** - * setIdentity - * - * @param mixed $identity - * @return AdapterChainEvent - */ - public function setIdentity($identity = null) - { - if (null === $identity) { - // Setting the identity to null resets the code and messages. - $this->setCredential(); - $this->setCode(); - $this->setMessages(); - } - $this->setParam('identity', $identity); - return $this; - } - - public function getCredential() - { - return $this->getParam('credential'); - } - - public function setCredential($credential = null) - { - $this->setParam('credential', $credential); - return $this; - } - - /** - * getCode - * - * @return int - */ - public function getCode() - { - return $this->getParam('code'); - } - - /** - * setCode - * - * @param int $code - * @return AdapterChainEvent - */ - public function setCode($code = null) - { - $this->setParam('code', $code); - return $this; - } - - /** - * getMessages - * - * @return array - */ - public function getMessages() - { - return $this->getParam('messages') ?: array(); - } - - /** - * setMessages - * - * @param array $messages - * @return AdapterChainEvent - */ - public function setMessages($messages = array()) - { - $this->setParam('messages', $messages); - return $this; - } -} diff --git a/src/ZfcUser/Authentication/Adapter/AdapterChainServiceFactory.php b/src/ZfcUser/Authentication/Adapter/AdapterChainServiceFactory.php deleted file mode 100644 index cc29a558..00000000 --- a/src/ZfcUser/Authentication/Adapter/AdapterChainServiceFactory.php +++ /dev/null @@ -1,74 +0,0 @@ -getOptions($serviceLocator); - - //iterate and attach multiple adapters and events if offered - foreach ($options->getAuthAdapters() as $priority => $adapterName) { - $adapter = $serviceLocator->get($adapterName); - - if (is_callable(array($adapter, 'authenticate'))) { - $chain->getEventManager()->attach('authenticate', array($adapter, 'authenticate'), $priority); - } - - if (is_callable(array($adapter, 'logout'))) { - $chain->getEventManager()->attach('logout', array($adapter, 'logout'), $priority); - } - } - - return $chain; - } - - - /** - * set options - * - * @param ModuleOptions $options - * @return AdapterChainServiceFactory - */ - public function setOptions(ModuleOptions $options) - { - $this->options = $options; - return $this; - } - - /** - * get options - * - * @param ServiceLocatorInterface $serviceLocator (optional) Service Locator - * @return ModuleOptions $options - * @throws OptionsNotFoundException If options tried to retrieve without being set but no SL was provided - */ - public function getOptions(ServiceLocatorInterface $serviceLocator = null) - { - if (!$this->options) { - if (!$serviceLocator) { - throw new OptionsNotFoundException( - 'Options were tried to retrieve but not set ' . - 'and no service locator was provided' - ); - } - - $this->setOptions($serviceLocator->get('zfcuser_module_options')); - } - - return $this->options; - } -} diff --git a/src/ZfcUser/Authentication/Adapter/ChainableAdapter.php b/src/ZfcUser/Authentication/Adapter/ChainableAdapter.php deleted file mode 100644 index aa8a383f..00000000 --- a/src/ZfcUser/Authentication/Adapter/ChainableAdapter.php +++ /dev/null @@ -1,8 +0,0 @@ -mapper = $mapper; $this->mapperMethod = $mapperMethod; $this->credentialProcessor = $validator; - if (!is_null($storage)) { - $this->setStorage($storage); - } } - /** - * Called when user id logged out - */ - public function logout() + public function authenticate() { - $this->getStorage()->clear(); - } - - public function authenticate(AuthenticationEvent $event) - { - if ($this->isSatisfied()) { - $storage = $this->getStorage()->read(); - $event->setIdentity($storage['identity']) - ->setCode(AuthenticationResult::SUCCESS) - ->setMessages(array('Authentication successful.')); - return; - } - - $userObject = call_user_func(array($this->mapper, $this->mapperMethod), $event->getIdentity()); + $userObject = call_user_func(array($this->mapper, $this->mapperMethod), $this->getIdentity()); if (!$userObject instanceof UserEntity) { - $event->setCode(AuthenticationResult::FAILURE_IDENTITY_NOT_FOUND) - ->setMessages(array('A record with the supplied identity could not be found.')); - $this->setSatisfied(false); - return false; + return new Result( + Result::FAILURE_IDENTITY_NOT_FOUND, + null, + array('A record with the supplied identity could not be found.') + ); } - if (!$this->credentialProcessor->verify($event->getCredential(), $userObject->getPassword())) { + if (!$this->credentialProcessor->verify($this->getCredential(), $userObject->getPassword())) { // Password does not match - $event->setCode(AuthenticationResult::FAILURE_CREDENTIAL_INVALID) - ->setMessages(array('Supplied credential is invalid.')); - $this->setSatisfied(false); - return false; + return new Result( + Result::FAILURE_CREDENTIAL_INVALID, + null, + array('Supplied credential is invalid.') + ); } - // Success! - $event->setIdentity($userObject->getId()); - - $this->setSatisfied(true); - $storage = $this->getStorage()->read(); - $storage['identity'] = $event->getIdentity(); - $this->getStorage()->write($storage); - $event->setCode(AuthenticationResult::SUCCESS) - ->setMessages(array('Authentication successful.')); + return new Result( + Result::SUCCESS, + $userObject, + array('Authentication successful.') + ); } } diff --git a/src/ZfcUser/Controller/UserController.php b/src/ZfcUser/Controller/UserController.php index d745c08c..3cd655a1 100644 --- a/src/ZfcUser/Controller/UserController.php +++ b/src/ZfcUser/Controller/UserController.php @@ -124,8 +124,6 @@ public function loginAction() return $this->redirect()->toUrl($this->url()->fromRoute(static::ROUTE_LOGIN).($redirect ? '?redirect='. rawurlencode($redirect) : '')); } - // clear adapters - $this->zfcUserAuthentication()->getAuthAdapter()->resetAdapters(); $this->zfcUserAuthentication()->getAuthService()->clearIdentity(); return $this->forward()->dispatch(static::CONTROLLER_NAME, array('action' => 'authenticate')); @@ -136,8 +134,6 @@ public function loginAction() */ public function logoutAction() { - $this->zfcUserAuthentication()->getAuthAdapter()->resetAdapters(); - $this->zfcUserAuthentication()->getAuthAdapter()->logoutAdapters(); $this->zfcUserAuthentication()->getAuthService()->clearIdentity(); $redirect = $this->params()->fromPost('redirect', $this->params()->fromQuery('redirect', false)); @@ -158,24 +154,15 @@ public function authenticateAction() return $this->redirect()->toRoute($this->options->getLoginRedirectRoute()); } - $adapter = $this->zfcUserAuthentication()->getAuthAdapter(); $redirect = $this->params()->fromPost('redirect', $this->params()->fromQuery('redirect', false)); - - $result = $adapter->prepareForAuthentication( - $this->params()->fromPost('identity'), - $this->params()->fromPost('credential') - ); - - // Return early if an adapter returned a response - if ($result instanceof Response) { - return $result; - } + + $adapter = $this->zfcUserAuthentication()->getAuthAdapter(); + $adapter->setIdentity($this->params()->fromPost('identity')); + $adapter->setCredential($this->params()->fromPost('credential')); $auth = $this->zfcUserAuthentication()->getAuthService()->authenticate($adapter); - if (!$auth->isValid()) { $this->flashMessenger()->setNamespace($this->loginNamespace)->addMessage($this->failedLoginMessage); - $adapter->resetAdapters(); return $this->redirect()->toUrl( $this->url()->fromRoute(static::ROUTE_LOGIN) . ($redirect ? '?redirect='. rawurlencode($redirect) : '') diff --git a/src/ZfcUser/Factory/Authentication/Adapter/AdapterChainFactory.php b/src/ZfcUser/Factory/Authentication/Adapter/AdapterChainFactory.php new file mode 100644 index 00000000..5ab0e28e --- /dev/null +++ b/src/ZfcUser/Factory/Authentication/Adapter/AdapterChainFactory.php @@ -0,0 +1,26 @@ +get('zfcuser_module_options'); + + $chain = new AdapterChain(); + foreach ($options->getAuthAdapters() as $priority => $adapterName) { + $chain->attach($adapterName, $serviceLocator->get($adapterName), $priority); + } + + return $chain; + } +} diff --git a/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php b/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php index 323216bb..d68cbd34 100644 --- a/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php +++ b/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php @@ -17,8 +17,7 @@ public function createService(ServiceLocatorInterface $serviceLocator) return new Mapper( $serviceLocator->get('zfcuser_user_mapper'), 'findByEmail', - $serviceLocator->get('zfcuser_authentication_credentialprocessor'), - $serviceLocator->get('zfcuser_authentication_storage') + $serviceLocator->get('zfcuser_authentication_credentialprocessor') ); } } diff --git a/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php b/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php index 62b0b947..479fe4d5 100644 --- a/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php +++ b/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php @@ -17,8 +17,7 @@ public function createService(ServiceLocatorInterface $serviceLocator) return new Mapper( $serviceLocator->get('zfcuser_user_mapper'), 'findByUsername', - $serviceLocator->get('zfcuser_authentication_credentialprocessor'), - $serviceLocator->get('zfcuser_authentication_storage') + $serviceLocator->get('zfcuser_authentication_credentialprocessor') ); } } From 4c6d1bda8ce8e2f19f5182289840e2002e8c14ae Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Sat, 17 Jan 2015 14:14:13 -0330 Subject: [PATCH 07/17] Ensure that adapters are processed FIFO (LIFO is default for PriorityList) --- .../Authentication/Adapter/AdapterChain.php | 1 + .../Adapter/AbstractAdapterTest.php | 63 -------- .../Adapter/AdapterChainEventTest.php | 76 ---------- .../TestAsset/AbstractAdapterExtension.php | 13 -- .../Adapter/AdapterChainFactoryTest.php} | 0 .../Adapter/MapperEmailFactoryTest.php | 134 ++++++++++++++++++ .../Adapter/MapperUsernameFactoryTest.php | 134 ++++++++++++++++++ .../CredentialProcessor/BcryptFactoryTest.php | 134 ++++++++++++++++++ .../Storage/MapperFactoryTest.php | 134 ++++++++++++++++++ 9 files changed, 537 insertions(+), 152 deletions(-) delete mode 100644 tests/ZfcUserTest/Authentication/Adapter/AbstractAdapterTest.php delete mode 100644 tests/ZfcUserTest/Authentication/Adapter/AdapterChainEventTest.php delete mode 100644 tests/ZfcUserTest/Authentication/Adapter/TestAsset/AbstractAdapterExtension.php rename tests/ZfcUserTest/{Authentication/Adapter/AdapterChainServiceFactoryTest.php => Factory/Authentication/Adapter/AdapterChainFactoryTest.php} (100%) create mode 100644 tests/ZfcUserTest/Factory/Authentication/Adapter/MapperEmailFactoryTest.php create mode 100644 tests/ZfcUserTest/Factory/Authentication/Adapter/MapperUsernameFactoryTest.php create mode 100644 tests/ZfcUserTest/Factory/Authentication/CredentialProcessor/BcryptFactoryTest.php create mode 100644 tests/ZfcUserTest/Factory/Authentication/Storage/MapperFactoryTest.php diff --git a/src/ZfcUser/Authentication/Adapter/AdapterChain.php b/src/ZfcUser/Authentication/Adapter/AdapterChain.php index 9485ab9a..4da0782a 100644 --- a/src/ZfcUser/Authentication/Adapter/AdapterChain.php +++ b/src/ZfcUser/Authentication/Adapter/AdapterChain.php @@ -16,6 +16,7 @@ class AdapterChain extends AbstractAdapter public function __construct() { $this->adapters = new PriorityList(); + $this->adapters->isLIFO(false); } public function attach($name, AbstractAdapter $adapter, $priority = 1) diff --git a/tests/ZfcUserTest/Authentication/Adapter/AbstractAdapterTest.php b/tests/ZfcUserTest/Authentication/Adapter/AbstractAdapterTest.php deleted file mode 100644 index fbc27959..00000000 --- a/tests/ZfcUserTest/Authentication/Adapter/AbstractAdapterTest.php +++ /dev/null @@ -1,63 +0,0 @@ -adapter = $adapter; - } - - /** - * @covers ZfcUser\Authentication\Adapter\AbstractAdapter::getStorage - */ - public function testGetStorageWithoutStorageSet() - { - $this->assertInstanceOf('Zend\Authentication\Storage\Session', $this->adapter->getStorage()); - } - - /** - * @covers ZfcUser\Authentication\Adapter\AbstractAdapter::getStorage - * @covers ZfcUser\Authentication\Adapter\AbstractAdapter::setStorage - */ - public function testSetGetStorage() - { - $storage = new \Zend\Authentication\Storage\Session('ZfcUser'); - $storage->write('zfcUser'); - $this->adapter->setStorage($storage); - - $this->assertInstanceOf('Zend\Authentication\Storage\Session', $this->adapter->getStorage()); - $this->assertSame('zfcUser', $this->adapter->getStorage()->read()); - } - - /** - * @covers ZfcUser\Authentication\Adapter\AbstractAdapter::isSatisfied - */ - public function testIsSatisfied() - { - $this->assertFalse($this->adapter->isSatisfied()); - } - - public function testSetSatisfied() - { - $result = $this->adapter->setSatisfied(); - $this->assertInstanceOf('ZfcUser\Authentication\Adapter\AbstractAdapter', $result); - $this->assertTrue($this->adapter->isSatisfied()); - - $result = $this->adapter->setSatisfied(false); - $this->assertInstanceOf('ZfcUser\Authentication\Adapter\AbstractAdapter', $result); - $this->assertFalse($this->adapter->isSatisfied()); - } -} diff --git a/tests/ZfcUserTest/Authentication/Adapter/AdapterChainEventTest.php b/tests/ZfcUserTest/Authentication/Adapter/AdapterChainEventTest.php deleted file mode 100644 index 95153032..00000000 --- a/tests/ZfcUserTest/Authentication/Adapter/AdapterChainEventTest.php +++ /dev/null @@ -1,76 +0,0 @@ -event = new AdapterChainEvent(); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainEvent::getCode - * @covers \ZfcUser\Authentication\Adapter\AdapterChainEvent::setCode - * @covers \ZfcUser\Authentication\Adapter\AdapterChainEvent::getMessages - * @covers \ZfcUser\Authentication\Adapter\AdapterChainEvent::setMessages - */ - public function testCodeAndMessages() - { - $testCode = 103; - $testMessages = array('Message recieved loud and clear.'); - - $this->event->setCode($testCode); - $this->assertEquals($testCode, $this->event->getCode(), "Asserting code values match."); - - $this->event->setMessages($testMessages); - $this->assertEquals($testMessages, $this->event->getMessages(), "Asserting messages values match."); - } - - /** - * @depends testCodeAndMessages - * @covers \ZfcUser\Authentication\Adapter\AdapterChainEvent::getIdentity - * @covers \ZfcUser\Authentication\Adapter\AdapterChainEvent::setIdentity - */ - public function testIdentity() - { - $testCode = 123; - $testMessages = array('The message.'); - $testIdentity = 'the_user'; - - $this->event->setCode($testCode); - $this->event->setMessages($testMessages); - - $this->event->setIdentity($testIdentity); - - $this->assertEquals($testCode, $this->event->getCode(), "Asserting the code persisted."); - $this->assertEquals($testMessages, $this->event->getMessages(), "Asserting the messages persisted."); - $this->assertEquals($testIdentity, $this->event->getIdentity(), "Asserting the identity matches"); - - $this->event->setIdentity(); - - $this->assertNull($this->event->getCode(), "Asserting the code has been cleared."); - $this->assertEquals(array(), $this->event->getMessages(), "Asserting the messages have been cleared."); - $this->assertNull($this->event->getIdentity(), "Asserting the identity has been cleared"); - } - - public function testRequest() - { - $request = $this->getMock('Zend\Stdlib\RequestInterface'); - $this->event->setRequest($request); - - $this->assertInstanceOf('Zend\Stdlib\RequestInterface', $this->event->getRequest()); - } -} diff --git a/tests/ZfcUserTest/Authentication/Adapter/TestAsset/AbstractAdapterExtension.php b/tests/ZfcUserTest/Authentication/Adapter/TestAsset/AbstractAdapterExtension.php deleted file mode 100644 index 30497650..00000000 --- a/tests/ZfcUserTest/Authentication/Adapter/TestAsset/AbstractAdapterExtension.php +++ /dev/null @@ -1,13 +0,0 @@ -serviceLocatorArray[$index]; + } + + /** + * Prepare the object to be tested. + */ + protected function setUp() + { + $this->serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); + + $this->options = $this->getMockBuilder('ZfcUser\Options\ModuleOptions') + ->disableOriginalConstructor() + ->getMock(); + + $this->serviceLocatorArray = array ( + 'zfcuser_module_options'=>$this->options + ); + + $this->serviceLocator->expects($this->any()) + ->method('get') + ->will($this->returnCallback(array($this,'helperServiceLocator'))); + + $this->eventManager = $this->getMock('Zend\EventManager\EventManager'); + + $this->factory = new AdapterChainServiceFactory(); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::createService + */ + public function testCreateService() + { + $adapter = array( + 'adapter1'=> $this->getMock( + 'ZfcUser\Authentication\Adapter\AbstractAdapter', + array('authenticate', 'logout') + ), + 'adapter2'=> $this->getMock( + 'ZfcUser\Authentication\Adapter\AbstractAdapter', + array('authenticate', 'logout') + ) + ); + $adapterNames = array(100=>'adapter1', 200=>'adapter2'); + + $this->serviceLocatorArray = array_merge($this->serviceLocatorArray, $adapter); + + $this->options->expects($this->once()) + ->method('getAuthAdapters') + ->will($this->returnValue($adapterNames)); + + $adapterChain = $this->factory->createService($this->serviceLocator); + + $this->assertInstanceOf('ZfcUser\Authentication\Adapter\AdapterChain', $adapterChain); + $this->assertEquals(array('authenticate', 'logout'), $adapterChain->getEventManager()->getEvents()); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::setOptions + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions + */ + public function testGetOptionWithSetter() + { + $this->factory->setOptions($this->options); + + $options = $this->factory->getOptions(); + + $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); + $this->assertSame($this->options, $options); + + + $options2 = clone $this->options; + $this->factory->setOptions($options2); + $options = $this->factory->getOptions(); + + $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); + $this->assertNotSame($this->options, $options); + $this->assertSame($options2, $options); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions + */ + public function testGetOptionWithLocator() + { + $options = $this->factory->getOptions($this->serviceLocator); + + $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); + $this->assertSame($this->options, $options); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions + * @expectedException \ZfcUser\Authentication\Adapter\Exception\OptionsNotFoundException + */ + public function testGetOptionFailing() + { + $options = $this->factory->getOptions(); + } +} diff --git a/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperUsernameFactoryTest.php b/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperUsernameFactoryTest.php new file mode 100644 index 00000000..c92fcd00 --- /dev/null +++ b/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperUsernameFactoryTest.php @@ -0,0 +1,134 @@ +serviceLocatorArray[$index]; + } + + /** + * Prepare the object to be tested. + */ + protected function setUp() + { + $this->serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); + + $this->options = $this->getMockBuilder('ZfcUser\Options\ModuleOptions') + ->disableOriginalConstructor() + ->getMock(); + + $this->serviceLocatorArray = array ( + 'zfcuser_module_options'=>$this->options + ); + + $this->serviceLocator->expects($this->any()) + ->method('get') + ->will($this->returnCallback(array($this,'helperServiceLocator'))); + + $this->eventManager = $this->getMock('Zend\EventManager\EventManager'); + + $this->factory = new AdapterChainServiceFactory(); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::createService + */ + public function testCreateService() + { + $adapter = array( + 'adapter1'=> $this->getMock( + 'ZfcUser\Authentication\Adapter\AbstractAdapter', + array('authenticate', 'logout') + ), + 'adapter2'=> $this->getMock( + 'ZfcUser\Authentication\Adapter\AbstractAdapter', + array('authenticate', 'logout') + ) + ); + $adapterNames = array(100=>'adapter1', 200=>'adapter2'); + + $this->serviceLocatorArray = array_merge($this->serviceLocatorArray, $adapter); + + $this->options->expects($this->once()) + ->method('getAuthAdapters') + ->will($this->returnValue($adapterNames)); + + $adapterChain = $this->factory->createService($this->serviceLocator); + + $this->assertInstanceOf('ZfcUser\Authentication\Adapter\AdapterChain', $adapterChain); + $this->assertEquals(array('authenticate', 'logout'), $adapterChain->getEventManager()->getEvents()); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::setOptions + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions + */ + public function testGetOptionWithSetter() + { + $this->factory->setOptions($this->options); + + $options = $this->factory->getOptions(); + + $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); + $this->assertSame($this->options, $options); + + + $options2 = clone $this->options; + $this->factory->setOptions($options2); + $options = $this->factory->getOptions(); + + $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); + $this->assertNotSame($this->options, $options); + $this->assertSame($options2, $options); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions + */ + public function testGetOptionWithLocator() + { + $options = $this->factory->getOptions($this->serviceLocator); + + $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); + $this->assertSame($this->options, $options); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions + * @expectedException \ZfcUser\Authentication\Adapter\Exception\OptionsNotFoundException + */ + public function testGetOptionFailing() + { + $options = $this->factory->getOptions(); + } +} diff --git a/tests/ZfcUserTest/Factory/Authentication/CredentialProcessor/BcryptFactoryTest.php b/tests/ZfcUserTest/Factory/Authentication/CredentialProcessor/BcryptFactoryTest.php new file mode 100644 index 00000000..c92fcd00 --- /dev/null +++ b/tests/ZfcUserTest/Factory/Authentication/CredentialProcessor/BcryptFactoryTest.php @@ -0,0 +1,134 @@ +serviceLocatorArray[$index]; + } + + /** + * Prepare the object to be tested. + */ + protected function setUp() + { + $this->serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); + + $this->options = $this->getMockBuilder('ZfcUser\Options\ModuleOptions') + ->disableOriginalConstructor() + ->getMock(); + + $this->serviceLocatorArray = array ( + 'zfcuser_module_options'=>$this->options + ); + + $this->serviceLocator->expects($this->any()) + ->method('get') + ->will($this->returnCallback(array($this,'helperServiceLocator'))); + + $this->eventManager = $this->getMock('Zend\EventManager\EventManager'); + + $this->factory = new AdapterChainServiceFactory(); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::createService + */ + public function testCreateService() + { + $adapter = array( + 'adapter1'=> $this->getMock( + 'ZfcUser\Authentication\Adapter\AbstractAdapter', + array('authenticate', 'logout') + ), + 'adapter2'=> $this->getMock( + 'ZfcUser\Authentication\Adapter\AbstractAdapter', + array('authenticate', 'logout') + ) + ); + $adapterNames = array(100=>'adapter1', 200=>'adapter2'); + + $this->serviceLocatorArray = array_merge($this->serviceLocatorArray, $adapter); + + $this->options->expects($this->once()) + ->method('getAuthAdapters') + ->will($this->returnValue($adapterNames)); + + $adapterChain = $this->factory->createService($this->serviceLocator); + + $this->assertInstanceOf('ZfcUser\Authentication\Adapter\AdapterChain', $adapterChain); + $this->assertEquals(array('authenticate', 'logout'), $adapterChain->getEventManager()->getEvents()); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::setOptions + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions + */ + public function testGetOptionWithSetter() + { + $this->factory->setOptions($this->options); + + $options = $this->factory->getOptions(); + + $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); + $this->assertSame($this->options, $options); + + + $options2 = clone $this->options; + $this->factory->setOptions($options2); + $options = $this->factory->getOptions(); + + $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); + $this->assertNotSame($this->options, $options); + $this->assertSame($options2, $options); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions + */ + public function testGetOptionWithLocator() + { + $options = $this->factory->getOptions($this->serviceLocator); + + $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); + $this->assertSame($this->options, $options); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions + * @expectedException \ZfcUser\Authentication\Adapter\Exception\OptionsNotFoundException + */ + public function testGetOptionFailing() + { + $options = $this->factory->getOptions(); + } +} diff --git a/tests/ZfcUserTest/Factory/Authentication/Storage/MapperFactoryTest.php b/tests/ZfcUserTest/Factory/Authentication/Storage/MapperFactoryTest.php new file mode 100644 index 00000000..c92fcd00 --- /dev/null +++ b/tests/ZfcUserTest/Factory/Authentication/Storage/MapperFactoryTest.php @@ -0,0 +1,134 @@ +serviceLocatorArray[$index]; + } + + /** + * Prepare the object to be tested. + */ + protected function setUp() + { + $this->serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); + + $this->options = $this->getMockBuilder('ZfcUser\Options\ModuleOptions') + ->disableOriginalConstructor() + ->getMock(); + + $this->serviceLocatorArray = array ( + 'zfcuser_module_options'=>$this->options + ); + + $this->serviceLocator->expects($this->any()) + ->method('get') + ->will($this->returnCallback(array($this,'helperServiceLocator'))); + + $this->eventManager = $this->getMock('Zend\EventManager\EventManager'); + + $this->factory = new AdapterChainServiceFactory(); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::createService + */ + public function testCreateService() + { + $adapter = array( + 'adapter1'=> $this->getMock( + 'ZfcUser\Authentication\Adapter\AbstractAdapter', + array('authenticate', 'logout') + ), + 'adapter2'=> $this->getMock( + 'ZfcUser\Authentication\Adapter\AbstractAdapter', + array('authenticate', 'logout') + ) + ); + $adapterNames = array(100=>'adapter1', 200=>'adapter2'); + + $this->serviceLocatorArray = array_merge($this->serviceLocatorArray, $adapter); + + $this->options->expects($this->once()) + ->method('getAuthAdapters') + ->will($this->returnValue($adapterNames)); + + $adapterChain = $this->factory->createService($this->serviceLocator); + + $this->assertInstanceOf('ZfcUser\Authentication\Adapter\AdapterChain', $adapterChain); + $this->assertEquals(array('authenticate', 'logout'), $adapterChain->getEventManager()->getEvents()); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::setOptions + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions + */ + public function testGetOptionWithSetter() + { + $this->factory->setOptions($this->options); + + $options = $this->factory->getOptions(); + + $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); + $this->assertSame($this->options, $options); + + + $options2 = clone $this->options; + $this->factory->setOptions($options2); + $options = $this->factory->getOptions(); + + $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); + $this->assertNotSame($this->options, $options); + $this->assertSame($options2, $options); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions + */ + public function testGetOptionWithLocator() + { + $options = $this->factory->getOptions($this->serviceLocator); + + $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); + $this->assertSame($this->options, $options); + } + + /** + * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions + * @expectedException \ZfcUser\Authentication\Adapter\Exception\OptionsNotFoundException + */ + public function testGetOptionFailing() + { + $options = $this->factory->getOptions(); + } +} From 6342b5bf96eca2cccb5b319e71c7c7564be3228c Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Sat, 17 Jan 2015 14:14:34 -0330 Subject: [PATCH 08/17] Prevent returning results that are not instances of Result in AdapterChain::authenticate --- src/ZfcUser/Authentication/Adapter/AdapterChain.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZfcUser/Authentication/Adapter/AdapterChain.php b/src/ZfcUser/Authentication/Adapter/AdapterChain.php index 4da0782a..a775bb28 100644 --- a/src/ZfcUser/Authentication/Adapter/AdapterChain.php +++ b/src/ZfcUser/Authentication/Adapter/AdapterChain.php @@ -44,7 +44,7 @@ public function authenticate() //@TODO throw an exception if no result? (no adapters tried) - return $result instanceof Result + return ( isset($result) && $result instanceof Result ) ? $result : new Result(Result::FAILURE_UNCATEGORIZED, null); } From 1e2365edd79bafac892f022a88624f8cb4bdc98f Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Sat, 17 Jan 2015 14:15:33 -0330 Subject: [PATCH 09/17] Remove unused references to ModuleOptions in some factories --- .../Factory/Authentication/Adapter/AdapterChainFactory.php | 5 ----- .../Factory/Authentication/Adapter/MapperEmailFactory.php | 2 -- .../Factory/Authentication/Adapter/MapperUsernameFactory.php | 2 -- src/ZfcUser/Factory/Authentication/Storage/MapperFactory.php | 2 -- 4 files changed, 11 deletions(-) diff --git a/src/ZfcUser/Factory/Authentication/Adapter/AdapterChainFactory.php b/src/ZfcUser/Factory/Authentication/Adapter/AdapterChainFactory.php index 5ab0e28e..3fc13769 100644 --- a/src/ZfcUser/Factory/Authentication/Adapter/AdapterChainFactory.php +++ b/src/ZfcUser/Factory/Authentication/Adapter/AdapterChainFactory.php @@ -7,11 +7,6 @@ class AdapterChainFactory implements FactoryInterface { - /** - * @var ModuleOptions - */ - protected $options; - public function createService(ServiceLocatorInterface $serviceLocator) { $options = $serviceLocator->get('zfcuser_module_options'); diff --git a/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php b/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php index d68cbd34..f431892f 100644 --- a/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php +++ b/src/ZfcUser/Factory/Authentication/Adapter/MapperEmailFactory.php @@ -12,8 +12,6 @@ class MapperEmailFactory implements FactoryInterface */ public function createService(ServiceLocatorInterface $serviceLocator) { - $options = $serviceLocator->get('zfcuser_module_options'); - return new Mapper( $serviceLocator->get('zfcuser_user_mapper'), 'findByEmail', diff --git a/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php b/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php index 479fe4d5..acb01473 100644 --- a/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php +++ b/src/ZfcUser/Factory/Authentication/Adapter/MapperUsernameFactory.php @@ -12,8 +12,6 @@ class MapperUsernameFactory implements FactoryInterface */ public function createService(ServiceLocatorInterface $serviceLocator) { - $options = $serviceLocator->get('zfcuser_module_options'); - return new Mapper( $serviceLocator->get('zfcuser_user_mapper'), 'findByUsername', diff --git a/src/ZfcUser/Factory/Authentication/Storage/MapperFactory.php b/src/ZfcUser/Factory/Authentication/Storage/MapperFactory.php index 15c7064c..1e278450 100644 --- a/src/ZfcUser/Factory/Authentication/Storage/MapperFactory.php +++ b/src/ZfcUser/Factory/Authentication/Storage/MapperFactory.php @@ -12,8 +12,6 @@ class MapperFactory implements FactoryInterface */ public function createService(ServiceLocatorInterface $serviceLocator) { - $options = $serviceLocator->get('zfcuser_module_options'); - return new Mapper( $serviceLocator->get('zfcuser_user_mapper'), $serviceLocator->get('zfcuser_authentication_storage_backend') From 0440720e7424ea90b1d60dc97e57ebea25a93816 Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Sat, 17 Jan 2015 14:15:53 -0330 Subject: [PATCH 10/17] Update ModuleOptions to reflect new default auth adapter name --- src/ZfcUser/Options/ModuleOptions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZfcUser/Options/ModuleOptions.php b/src/ZfcUser/Options/ModuleOptions.php index 5643ddf9..78ec1f3b 100644 --- a/src/ZfcUser/Options/ModuleOptions.php +++ b/src/ZfcUser/Options/ModuleOptions.php @@ -59,7 +59,7 @@ class ModuleOptions extends AbstractOptions implements UserControllerOptionsInte /** * @var array */ - protected $authAdapters = array( 100 => 'ZfcUser\Authentication\Adapter\Db' ); + protected $authAdapters = array( 100 => 'ZfcUser\Authentication\Adapter\Mapper' ); /** * @var array From e47a62de42c53b46a2b1ca3224c9765427bc18ca Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Sat, 17 Jan 2015 14:16:15 -0330 Subject: [PATCH 11/17] Fix the tests --- .../Adapter/AdapterChainTest.php | 312 ++-------- .../Authentication/Adapter/MapperTest.php | 558 ++---------------- .../Authentication/Storage/MapperTest.php | 181 +++--- .../Controller/UserControllerTest.php | 170 +++--- .../Adapter/AdapterChainFactoryTest.php | 130 +--- .../Adapter/MapperEmailFactoryTest.php | 142 +---- .../Adapter/MapperUsernameFactoryTest.php | 142 +---- .../CredentialProcessor/BcryptFactoryTest.php | 139 +---- .../Storage/MapperFactoryTest.php | 142 +---- .../AuthenticationServiceFactoryTest.php | 10 +- .../ZfcUserTest/Options/ModuleOptionsTest.php | 2 +- 11 files changed, 353 insertions(+), 1575 deletions(-) diff --git a/tests/ZfcUserTest/Authentication/Adapter/AdapterChainTest.php b/tests/ZfcUserTest/Authentication/Adapter/AdapterChainTest.php index 6e564744..7873e50b 100644 --- a/tests/ZfcUserTest/Authentication/Adapter/AdapterChainTest.php +++ b/tests/ZfcUserTest/Authentication/Adapter/AdapterChainTest.php @@ -2,9 +2,8 @@ namespace ZfcUserTest\Authentication\Adapter; -use Zend\EventManager\EventManagerInterface; use ZfcUser\Authentication\Adapter\AdapterChain; -use ZfcUser\Authentication\Adapter\AdapterChainEvent; +use Zend\Authentication\Result; class AdapterChainTest extends \PHPUnit_Framework_TestCase { @@ -15,297 +14,76 @@ class AdapterChainTest extends \PHPUnit_Framework_TestCase */ protected $adapterChain; - /** - * Mock event manager. - * - * @var EventManagerInterface - */ - protected $eventManager; - - /** - * For tests where an event is required. - * - * @var \Zend\EventManager\EventInterface - */ - protected $event; - - /** - * Used when testing prepareForAuthentication. - * - * @var \Zend\Stdlib\RequestInterface - */ - protected $request; - /** * Prepare the objects to be tested. + * @covers ZfcUser\Authentication\Adapter\AdapterChain::__construct */ protected function setUp() { - $this->event = null; - $this->request = null; - $this->adapterChain = new AdapterChain(); - - $this->eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); - $this->adapterChain->setEventManager($this->eventManager); + $this->adapterChain->setIdentity('identity'); + $this->adapterChain->setCredential('credential'); } /** * @covers ZfcUser\Authentication\Adapter\AdapterChain::authenticate */ - public function testAuthenticate() + public function testAuthenticateWithNoAdaptersReturnsUncategorizedFailure() { - $event = $this->getMock('ZfcUser\Authentication\Adapter\AdapterChainEvent'); - $event->expects($this->once()) - ->method('getCode') - ->will($this->returnValue(123)); - $event->expects($this->once()) - ->method('getIdentity') - ->will($this->returnValue('identity')); - $event->expects($this->once()) - ->method('getMessages') - ->will($this->returnValue(array())); - - $this->eventManager->expects($this->once()) - ->method('getListeners') - ->with($this->equalTo('authenticate')) - ->will($this->returnValue(array())); - - $this->adapterChain->setEvent($event); $result = $this->adapterChain->authenticate(); $this->assertInstanceOf('Zend\Authentication\Result', $result); - $this->assertEquals($result->getIdentity(), 'identity'); + $this->assertEquals(Result::FAILURE_UNCATEGORIZED, $result->getCode()); + $this->assertEquals($result->getIdentity(), null); $this->assertEquals($result->getMessages(), array()); } /** - * @covers ZfcUser\Authentication\Adapter\AdapterChain::resetAdapters - */ - public function testResetAdapters() - { - $listeners = array(); - - for ($i=1; $i<=3; $i++) { - $storage = $this->getMock('ZfcUser\Authentication\Storage\Db'); - $storage->expects($this->once()) - ->method('clear'); - - $adapter = $this->getMock('ZfcUser\Authentication\Adapter\AbstractAdapter'); - $adapter->expects($this->once()) - ->method('getStorage') - ->will($this->returnValue($storage)); - - $callback = $this->getMockBuilder('Zend\Stdlib\CallbackHandler')->disableOriginalConstructor()->getMock(); - $callback->expects($this->once()) - ->method('getCallback') - ->will($this->returnValue(array($adapter))); - - $listeners[] = $callback; - } - - $this->eventManager->expects($this->once()) - ->method('getListeners') - ->with($this->equalTo('authenticate')) - ->will($this->returnValue($listeners)); - - $result = $this->adapterChain->resetAdapters(); - - $this->assertInstanceOf('ZfcUser\Authentication\Adapter\AdapterChain', $result); - } - - /** - * Get through the first part of SetUpPrepareForAuthentication - */ - protected function setUpPrepareForAuthentication() - { - $this->request = $this->getMock('Zend\Stdlib\RequestInterface'); - $this->event = $this->getMock('ZfcUser\Authentication\Adapter\AdapterChainEvent'); - - $this->event->expects($this->once())->method('setRequest')->with($this->request); - - $this->eventManager->expects($this->at(0))->method('trigger')->with('authenticate.pre'); - - /** - * @var $response Zend\EventManager\ResponseCollection - */ - $responses = $this->getMock('Zend\EventManager\ResponseCollection'); - - $this->eventManager->expects($this->at(1)) - ->method('trigger') - ->with('authenticate', $this->event) - ->will($this->returnCallback(function ($event, $target, $callback) use ($responses) { - if (call_user_func($callback, $responses->last())) { - $responses->setStopped(true); - } - return $responses; - })); - - $this->adapterChain->setEvent($this->event); - - return $responses; - } - - /** - * Provider for testPrepareForAuthentication() - * - * @return array - */ - public function identityProvider() - { - return array( - array(true, true), - array(false, false), - ); - } - - /** - * Tests prepareForAuthentication when falls through events. - * - * @param mixed $identity - * @param bool $expected - * - * @dataProvider identityProvider - * @covers ZfcUser\Authentication\Adapter\AdapterChain::prepareForAuthentication - */ - public function testPrepareForAuthentication($identity, $expected) - { - $result = $this->setUpPrepareForAuthentication(); - - $result->expects($this->once())->method('stopped')->will($this->returnValue(false)); - - $this->event->expects($this->once())->method('getIdentity')->will($this->returnValue($identity)); - - $this->assertEquals( - $expected, - $this->adapterChain->prepareForAuthentication($this->request), - 'Asserting prepareForAuthentication() returns true' - ); - } - - /** - * Test prepareForAuthentication() when the returned collection contains stopped. - * - * @covers ZfcUser\Authentication\Adapter\AdapterChain::prepareForAuthentication - */ - public function testPrepareForAuthenticationWithStoppedEvent() - { - $result = $this->setUpPrepareForAuthentication(); - - $result->expects($this->once())->method('stopped')->will($this->returnValue(true)); - - $lastResponse = $this->getMock('Zend\Stdlib\ResponseInterface'); - $result->expects($this->atLeastOnce())->method('last')->will($this->returnValue($lastResponse)); - - $this->assertEquals( - $lastResponse, - $this->adapterChain->prepareForAuthentication($this->request), - 'Asserting the Response returned from the event is returned' - ); - } - - /** - * Test prepareForAuthentication() when the returned collection contains stopped. - * - * @covers ZfcUser\Authentication\Adapter\AdapterChain::prepareForAuthentication - * @expectedException ZfcUser\Exception\AuthenticationEventException - */ - public function testPrepareForAuthenticationWithBadEventResult() - { - $result = $this->setUpPrepareForAuthentication(); - - $result->expects($this->once())->method('stopped')->will($this->returnValue(true)); - - $lastResponse = 'random-value'; - $result->expects($this->atLeastOnce())->method('last')->will($this->returnValue($lastResponse)); - - $this->adapterChain->prepareForAuthentication($this->request); - } - - /** - * Test getEvent() when no event has previously been set. - * - * @covers ZfcUser\Authentication\Adapter\AdapterChain::getEvent - */ - public function testGetEventWithNoEventSet() - { - $event = $this->adapterChain->getEvent(); - - $this->assertInstanceOf( - 'ZfcUser\Authentication\Adapter\AdapterChainEvent', - $event, - 'Asserting the adapter in an instance of ZfcUser\Authentication\Adapter\AdapterChainEvent' - ); - $this->assertEquals( - $this->adapterChain, - $event->getTarget(), - 'Asserting the Event target is the AdapterChain' - ); - } - - /** - * Test getEvent() when an event has previously been set. - * - * @covers ZfcUser\Authentication\Adapter\AdapterChain::setEvent - * @covers ZfcUser\Authentication\Adapter\AdapterChain::getEvent - */ - public function testGetEventWithEventSet() - { - $event = new \ZfcUser\Authentication\Adapter\AdapterChainEvent(); - - $this->adapterChain->setEvent($event); - - $this->assertEquals( - $event, - $this->adapterChain->getEvent(), - 'Asserting the event fetched is the same as the event set' - ); - } - - /** - * Tests the mechanism for casting one event type to AdapterChainEvent - * - * @covers ZfcUser\Authentication\Adapter\AdapterChain::setEvent + * @covers ZfcUser\Authentication\Adapter\AdapterChain::authenticate + * @covers ZfcUser\Authentication\Adapter\AdapterChain::attach */ - public function testSetEventWithDifferentEventType() + public function testAuthenticateWithZeroAdapterMatchesReturnsLastAdapterResult() { - $testParams = array('testParam' => 'testValue'); - - $event = new \Zend\EventManager\Event; - $event->setParams($testParams); - - $this->adapterChain->setEvent($event); - $returnEvent = $this->adapterChain->getEvent(); - - $this->assertInstanceOf( - 'ZfcUser\Authentication\Adapter\AdapterChainEvent', - $returnEvent, - 'Asserting the adapter in an instance of ZfcUser\Authentication\Adapter\AdapterChainEvent' - ); + $result1 = new Result(Result::FAILURE_IDENTITY_NOT_FOUND, null); + $adapter1 = $this->getMockForAbstractClass('Zend\Authentication\Adapter\AbstractAdapter'); + $adapter1->expects($this->once())->method('authenticate')->will($this->returnValue($result1)); + $this->adapterChain->attach('adapter1', $adapter1); + + $result2 = new Result(Result::FAILURE_IDENTITY_NOT_FOUND, null); + $adapter2 = $this->getMockForAbstractClass('Zend\Authentication\Adapter\AbstractAdapter'); + $adapter2->expects($this->once())->method('authenticate')->will($this->returnValue($result2)); + $this->adapterChain->attach('adapter2', $adapter2); + + $result = $this->adapterChain->authenticate(); - $this->assertEquals( - $testParams, - $returnEvent->getParams(), - 'Asserting event parameters match' - ); + $this->assertSame($result2, $result); + $this->assertEquals(Result::FAILURE_IDENTITY_NOT_FOUND, $result->getCode()); + $this->assertEquals($result->getIdentity(), null); + $this->assertEquals($result->getMessages(), array()); } - + /** - * Test the logoutAdapters method. - * - * @depends testGetEventWithEventSet - * @covers ZfcUser\Authentication\Adapter\AdapterChain::logoutAdapters + * Also enforces FIFO behavior of AdapterChain (If LIFO, adapter2 would execute first) + * + * @covers ZfcUser\Authentication\Adapter\AdapterChain::authenticate + * @covers ZfcUser\Authentication\Adapter\AdapterChain::attach */ - public function testLogoutAdapters() + public function testAuthenticateWithAdapterMatchReturnsSuccessfulAdapterResult() { - $event = new AdapterChainEvent(); - - $this->eventManager - ->expects($this->once()) - ->method('trigger') - ->with('logout', $event); + $result1 = new Result(Result::SUCCESS, $this->adapterChain->getIdentity()); + $adapter1 = $this->getMockForAbstractClass('Zend\Authentication\Adapter\AbstractAdapter'); + $adapter1->expects($this->once())->method('authenticate')->will($this->returnValue($result1)); + $this->adapterChain->attach('adapter1', $adapter1); + + $adapter2 = $this->getMockForAbstractClass('Zend\Authentication\Adapter\AbstractAdapter'); + $adapter2->expects($this->never())->method('authenticate'); + $this->adapterChain->attach('adapter2', $adapter2); + + $result = $this->adapterChain->authenticate(); - $this->adapterChain->setEvent($event); - $this->adapterChain->logoutAdapters(); + $this->assertSame($result1, $result); + $this->assertEquals(Result::SUCCESS, $result->getCode()); + $this->assertEquals($result->getIdentity(), $this->adapterChain->getIdentity()); + $this->assertEquals($result->getMessages(), array()); } } diff --git a/tests/ZfcUserTest/Authentication/Adapter/MapperTest.php b/tests/ZfcUserTest/Authentication/Adapter/MapperTest.php index 5d8b3e69..63d89b98 100644 --- a/tests/ZfcUserTest/Authentication/Adapter/MapperTest.php +++ b/tests/ZfcUserTest/Authentication/Adapter/MapperTest.php @@ -4,9 +4,10 @@ use PHPUnit_Framework_MockObject_MockObject as MockObject; use PHPUnit_Framework_TestCase as TestCase; -use ZfcUser\Authentication\Adapter\Db; +use ZfcUser\Authentication\Adapter\Mapper; +use Zend\Authentication\Result; -class DbTest extends TestCase +class MapperTest extends TestCase { const PASSWORD_COST_04 = '04'; const PASSWORD_COST_10 = '10'; @@ -16,28 +17,7 @@ class DbTest extends TestCase * * @var Db */ - protected $db; - - /** - * Mock of AuthEvent. - * - * @var MockObject - */ - protected $authEvent; - - /** - * Mock of Storage. - * - * @var MockObject - */ - protected $storage; - - /** - * Mock of Options. - * - * @var MockObject - */ - protected $options; + protected $adapter; /** * Mock of Mapper. @@ -49,12 +29,7 @@ class DbTest extends TestCase /** * @var MockObject */ - protected $hydrator; - - /** - * @var MockObject - */ - protected $bcrypt; + protected $processor; /** * Mock of User. @@ -63,502 +38,71 @@ class DbTest extends TestCase */ protected $user; - /** - * Mock of ServiceManager. - * - * @var MockObject - */ - protected $services; - protected function setUp() { - $this->options = $this->getMock('ZfcUser\Options\ModuleOptions'); $this->mapper = $this->getMockForAbstractClass( 'ZfcUser\Mapper\UserInterface' ); $this->user = $this->getMockForAbstractClass( 'ZfcUser\Entity\UserInterface' ); - $this->storage = $this->getMockForAbstractClass( - 'Zend\Authentication\Storage\StorageInterface' - ); - $this->authEvent = $this->getMock( - 'ZfcUser\Authentication\Adapter\AdapterChainEvent' - ); - - $this->bcrypt = $this->getMock('Zend\Crypt\Password\Bcrypt'); - $this->hydrator = $this->getMockForAbstractClass( - 'ZfcUser\Mapper\HydratorInterface' - ); - $this->hydrator->expects($this->any()) - ->method('getCryptoService') - ->will($this->returnValue($this->bcrypt)); - - $this->services = $this->getMock('Zend\ServiceManager\ServiceManager'); - $this->services->expects($this->any()) - ->method('get') - ->will($this->returnValueMap(array( - array('zfcuser_module_options', true, $this->options), - array('zfcuser_user_mapper', true, $this->mapper), - array('zfcuser_user_hydrator', true, $this->hydrator), - ))); - - $this->db = new Db; - $this->db->setServiceManager($this->services); - $this->db->setStorage($this->storage); - - $sessionManager = $this->getMock('Zend\Session\SessionManager'); - \Zend\Session\AbstractContainer::setDefaultManager($sessionManager); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::logout - */ - public function testLogout() - { - $this->storage->expects($this->once())->method('clear'); - $this->db->logout($this->authEvent); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::Authenticate - */ - public function testAuthenticateWhenSatisfies() - { - $this->authEvent->expects($this->once()) - ->method('setIdentity') - ->with('ZfcUser') - ->will($this->returnValue($this->authEvent)); - $this->authEvent->expects($this->once()) - ->method('setCode') - ->with(\Zend\Authentication\Result::SUCCESS) - ->will($this->returnValue($this->authEvent)); - $this->authEvent->expects($this->once()) - ->method('setMessages') - ->with(array('Authentication successful.')) - ->will($this->returnValue($this->authEvent)); - - $this->storage->expects($this->at(0)) - ->method('read') - ->will($this->returnValue(array('is_satisfied' => true))); - $this->storage->expects($this->at(1)) - ->method('read') - ->will($this->returnValue(array('identity' => 'ZfcUser'))); - - $result = $this->db->authenticate($this->authEvent); - $this->assertNull($result); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::Authenticate - */ - public function testAuthenticateNoUserObject() - { - $this->setAuthenticationCredentials(); - - $this->options->expects($this->once()) - ->method('getAuthIdentityFields') - ->will($this->returnValue(array())); - - $this->authEvent->expects($this->once()) - ->method('setCode') - ->with(\Zend\Authentication\Result::FAILURE_IDENTITY_NOT_FOUND) - ->will($this->returnValue($this->authEvent)); - $this->authEvent->expects($this->once(1)) - ->method('setMessages') - ->with(array('A record with the supplied identity could not be found.')) - ->will($this->returnValue($this->authEvent)); + $this->processor = $this->getMock('Zend\Crypt\Password\PasswordInterface'); - $result = $this->db->authenticate($this->authEvent); - - $this->assertFalse($result); - $this->assertFalse($this->db->isSatisfied()); + $this->adapter = new Mapper($this->mapper, 'findByUsername', $this->processor); + $this->adapter->setIdentity('identity'); + $this->adapter->setCredential('credential'); } - /** - * @covers ZfcUser\Authentication\Adapter\Db::Authenticate - */ - public function testAuthenticationUserStateEnabledUserButUserStateNotInArray() + public function testAuthenticateWhenNoUserEntityFound() { - $this->setAuthenticationCredentials(); - $this->setAuthenticationUser(); - - $this->options->expects($this->once()) - ->method('getEnableUserState') - ->will($this->returnValue(true)); - $this->options->expects($this->once()) - ->method('getAllowedLoginStates') - ->will($this->returnValue(array(2, 3))); - - $this->authEvent->expects($this->once()) - ->method('setCode') - ->with(\Zend\Authentication\Result::FAILURE_UNCATEGORIZED) - ->will($this->returnValue($this->authEvent)); - $this->authEvent->expects($this->once()) - ->method('setMessages') - ->with(array('A record with the supplied identity is not active.')) - ->will($this->returnValue($this->authEvent)); - - $this->user->expects($this->once()) - ->method('getState') - ->will($this->returnValue(1)); - - $result = $this->db->authenticate($this->authEvent); - - $this->assertFalse($result); - $this->assertFalse($this->db->isSatisfied()); + $this->mapper->expects($this->once()) + ->method('findByUsername') + ->with('identity') + ->will($this->returnValue(null)); + + $result = $this->adapter->authenticate(); + $this->assertInstanceOf('Zend\Authentication\Result', $result); + $this->assertEquals(Result::FAILURE_IDENTITY_NOT_FOUND, $result->getCode()); + $this->assertCount(1, $result->getMessages()); } - /** - * @covers ZfcUser\Authentication\Adapter\Db::Authenticate - */ - public function testAuthenticateWithWrongPassword() + public function testAuthenticateWhenUserEntityFoundButPasswordIncorrect() { - $this->setAuthenticationCredentials(); - $this->setAuthenticationUser(); - - $this->options->expects($this->once()) - ->method('getEnableUserState') - ->will($this->returnValue(false)); - - $this->bcrypt->expects($this->once()) - ->method('verify') - ->will($this->returnValue(false)); - - $this->authEvent->expects($this->once()) - ->method('setCode') - ->with(\Zend\Authentication\Result::FAILURE_CREDENTIAL_INVALID) - ->will($this->returnValue($this->authEvent)); - $this->authEvent->expects($this->once(1)) - ->method('setMessages') - ->with(array('Supplied credential is invalid.')); - - $result = $this->db->authenticate($this->authEvent); - - $this->assertFalse($result); - $this->assertFalse($this->db->isSatisfied()); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::Authenticate - */ - public function testAuthenticationAuthenticatesWithEmail() - { - $this->setAuthenticationCredentials('zfc-user@zf-commons.io'); - $this->setAuthenticationEmail(); - - $this->options->expects($this->once()) - ->method('getEnableUserState') - ->will($this->returnValue(false)); - - $this->bcrypt->expects($this->once()) - ->method('verify') - ->will($this->returnValue(true)); - $this->bcrypt->expects($this->any()) - ->method('getCost') - ->will($this->returnValue(static::PASSWORD_COST_04)); - - $this->user->expects($this->exactly(2)) - ->method('getPassword') - ->will($this->returnValue('$2a$04$5kq1mnYWbww8X.rIj7eOVOHXtvGw/peefjIcm0lDGxRTEjm9LnOae')); $this->user->expects($this->once()) - ->method('getId') - ->will($this->returnValue(1)); - - $this->storage->expects($this->any()) - ->method('getNameSpace') - ->will($this->returnValue('test')); - - $this->authEvent->expects($this->once()) - ->method('setIdentity') - ->with(1) - ->will($this->returnValue($this->authEvent)); - $this->authEvent->expects($this->once()) - ->method('setCode') - ->with(\Zend\Authentication\Result::SUCCESS) - ->will($this->returnValue($this->authEvent)); - $this->authEvent->expects($this->once()) - ->method('setMessages') - ->with(array('Authentication successful.')) - ->will($this->returnValue($this->authEvent)); - - $result = $this->db->authenticate($this->authEvent); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::Authenticate - */ - public function testAuthenticationAuthenticates() - { - $this->setAuthenticationCredentials(); - $this->setAuthenticationUser(); - - $this->options->expects($this->once()) - ->method('getEnableUserState') - ->will($this->returnValue(true)); - - $this->options->expects($this->once()) - ->method('getAllowedLoginStates') - ->will($this->returnValue(array(1, 2, 3))); - - $this->bcrypt->expects($this->once()) - ->method('verify') - ->will($this->returnValue(true)); - $this->bcrypt->expects($this->any()) - ->method('getCost') - ->will($this->returnValue(static::PASSWORD_COST_04)); - - $this->user->expects($this->exactly(2)) ->method('getPassword') - ->will($this->returnValue('$2a$04$5kq1mnYWbww8X.rIj7eOVOHXtvGw/peefjIcm0lDGxRTEjm9LnOae')); - $this->user->expects($this->once()) - ->method('getId') - ->will($this->returnValue(1)); - $this->user->expects($this->once()) - ->method('getState') - ->will($this->returnValue(1)); - - $this->storage->expects($this->any()) - ->method('getNameSpace') - ->will($this->returnValue('test')); - - $this->authEvent->expects($this->once()) - ->method('setIdentity') - ->with(1) - ->will($this->returnValue($this->authEvent)); - $this->authEvent->expects($this->once()) - ->method('setCode') - ->with(\Zend\Authentication\Result::SUCCESS) - ->will($this->returnValue($this->authEvent)); - $this->authEvent->expects($this->once()) - ->method('setMessages') - ->with(array('Authentication successful.')) - ->will($this->returnValue($this->authEvent)); - - $result = $this->db->authenticate($this->authEvent); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::updateUserPasswordHash - */ - public function testUpdateUserPasswordHashWithSameCost() - { - $this->user->expects($this->once()) - ->method('getPassword') - ->will($this->returnValue('$2a$10$x05G2P803MrB3jaORBXBn.QHtiYzGQOBjQ7unpEIge.Mrz6c3KiVm')); - - $this->bcrypt->expects($this->once()) - ->method('getCost') - ->will($this->returnValue(static::PASSWORD_COST_10)); - - $this->hydrator->expects($this->never())->method('hydrate'); - $this->mapper->expects($this->never())->method('update'); - - $method = new \ReflectionMethod( - 'ZfcUser\Authentication\Adapter\Db', - 'updateUserPasswordHash' - ); - $method->setAccessible(true); - $method->invoke($this->db, $this->user, 'ZfcUser', $this->bcrypt); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::updateUserPasswordHash - */ - public function testUpdateUserPasswordHashWithoutSameCost() - { - $this->user->expects($this->once()) - ->method('getPassword') - ->will($this->returnValue('$2a$10$x05G2P803MrB3jaORBXBn.QHtiYzGQOBjQ7unpEIge.Mrz6c3KiVm')); - - $this->bcrypt->expects($this->once()) - ->method('getCost') - ->will($this->returnValue(static::PASSWORD_COST_04)); - - $this->hydrator->expects($this->once()) - ->method('hydrate') - ->with(array('password' => 'ZfcUserNew'), $this->user) - ->will($this->returnValue($this->user)); - - $this->mapper->expects($this->once()) - ->method('update') - ->with($this->user); - - $method = new \ReflectionMethod( - 'ZfcUser\Authentication\Adapter\Db', - 'updateUserPasswordHash' - ); - $method->setAccessible(true); - $method->invoke($this->db, $this->user, 'ZfcUserNew', $this->bcrypt); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::getCredentialPreprocessor - * @covers ZfcUser\Authentication\Adapter\Db::setCredentialPreprocessor - */ - public function testSetValidPreprocessCredential() - { - $callable = function () { - // no-op - }; - $this->db->setCredentialPreprocessor($callable); - $this->assertSame($callable, $this->db->getCredentialPreprocessor()); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::setCredentialPreprocessor - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Credential Preprocessor must be callable, [boolean] given - */ - public function testSetInvalidPreprocessCredential() - { - $this->db->setCredentialPreprocessor(false); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::preprocessCredential - * @covers ZfcUser\Authentication\Adapter\Db::setCredentialPreprocessor - */ - public function testPreprocessCredentialWithCallable() - { - $expected = 'processed'; - $this->db->setCredentialPreprocessor(function ($credential) use ($expected) { - return $expected; - }); - $this->assertSame($expected, $this->db->preprocessCredential('ZfcUser')); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::preprocessCredential - */ - public function testPreprocessCredentialWithoutCallable() - { - $this->assertSame('zfcUser', $this->db->preprocessCredential('zfcUser')); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::getServiceManager - * @covers ZfcUser\Authentication\Adapter\Db::setServiceManager - */ - public function testGetServiceManager() - { - $this->assertSame($this->services, $this->db->getServiceManager()); - } - - /** - * @depends testGetServiceManager - * @covers ZfcUser\Authentication\Adapter\Db::getOptions - */ - public function testLazyLoadOptions() - { - $this->assertEquals($this->options, $this->db->getOptions()); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::setOptions - * @covers ZfcUser\Authentication\Adapter\Db::getOptions - */ - public function testSetOptions() - { - $options = new \ZfcUser\Options\ModuleOptions; - $options->setLoginRedirectRoute('zfcUser'); - - $this->db->setOptions($options); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $this->db->getOptions()); - $this->assertSame('zfcUser', $this->db->getOptions()->getLoginRedirectRoute()); - } - - /** - * @depends testGetServiceManager - * @covers ZfcUser\Authentication\Adapter\Db::getMapper - */ - public function testLazyLoadMapper() - { - $this->assertEquals($this->mapper, $this->db->getMapper()); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::setMapper - * @covers ZfcUser\Authentication\Adapter\Db::getMapper - */ - public function testSetMapper() - { - $mapper = new \ZfcUser\Mapper\User; - $mapper->setTableName('zfcUser'); - - $this->db->setMapper($mapper); - - $this->assertInstanceOf('ZfcUser\Mapper\User', $this->db->getMapper()); - $this->assertSame('zfcUser', $this->db->getMapper()->getTableName()); - } - - /** - * @depends testGetServiceManager - * @covers ZfcUser\Authentication\Adapter\Db::getHydrator - */ - public function testLazyLoadHydrator() - { - $this->assertEquals($this->hydrator, $this->db->getHydrator()); - } - - /** - * @covers ZfcUser\Authentication\Adapter\Db::setHydrator - * @covers ZfcUser\Authentication\Adapter\Db::getHydrator - */ - public function testSetHydrator() - { - $this->db->setHydrator($this->hydrator); - $this->assertSame($this->hydrator, $this->db->getHydrator()); - } - - protected function setAuthenticationEmail() - { + ->will($this->returnValue('notthecredential')); $this->mapper->expects($this->once()) - ->method('findByEmail') - ->with('zfc-user@zf-commons.io') - ->will($this->returnValue($this->user)); - - $this->options->expects($this->once()) - ->method('getAuthIdentityFields') - ->will($this->returnValue(array('email'))); - } - - protected function setAuthenticationUser() + ->method('findByUsername') + ->with('identity') + ->will($this->returnValue($this->user)); + $this->processor->expects($this->once()) + ->method('verify') + ->with('credential', 'notthecredential') + ->will($this->returnValue(false)); + + $result = $this->adapter->authenticate(); + $this->assertInstanceOf('Zend\Authentication\Result', $result); + $this->assertEquals(Result::FAILURE_CREDENTIAL_INVALID, $result->getCode()); + $this->assertCount(1, $result->getMessages()); + } + + public function testAuthenticateSuccessful() { + $this->user->expects($this->once()) + ->method('getPassword') + ->will($this->returnValue('credential')); $this->mapper->expects($this->once()) - ->method('findByUsername') - ->with('ZfcUser') - ->will($this->returnValue($this->user)); - - $this->options->expects($this->once()) - ->method('getAuthIdentityFields') - ->will($this->returnValue(array('username'))); - } - - protected function setAuthenticationCredentials($identity = 'ZfcUser', $credential = 'ZfcUserPassword') - { - $this->storage->expects($this->at(0)) - ->method('read') - ->will($this->returnValue(array('is_satisfied' => false))); - - $post = $this->getMock('Zend\Stdlib\Parameters'); - $post->expects($this->at(0)) - ->method('get') - ->with('identity') - ->will($this->returnValue($identity)); - $post->expects($this->at(1)) - ->method('get') - ->with('credential') - ->will($this->returnValue($credential)); - - $request = $this->getMock('Zend\Http\Request'); - $request->expects($this->exactly(2)) - ->method('getPost') - ->will($this->returnValue($post)); - - $this->authEvent->expects($this->exactly(2)) - ->method('getRequest') - ->will($this->returnValue($request)); + ->method('findByUsername') + ->with('identity') + ->will($this->returnValue($this->user)); + $this->processor->expects($this->once()) + ->method('verify') + ->with('credential', 'credential') + ->will($this->returnValue(true)); + + $result = $this->adapter->authenticate(); + $this->assertInstanceOf('Zend\Authentication\Result', $result); + $this->assertEquals(Result::SUCCESS, $result->getCode()); + $this->assertCount(1, $result->getMessages()); } } diff --git a/tests/ZfcUserTest/Authentication/Storage/MapperTest.php b/tests/ZfcUserTest/Authentication/Storage/MapperTest.php index f7a0ae84..5d7eed6e 100644 --- a/tests/ZfcUserTest/Authentication/Storage/MapperTest.php +++ b/tests/ZfcUserTest/Authentication/Storage/MapperTest.php @@ -2,16 +2,16 @@ namespace ZfcUserTest\Authentication\Storage; -use ZfcUser\Authentication\Storage\Db; +use ZfcUser\Authentication\Storage\Mapper; -class DbTest extends \PHPUnit_Framework_TestCase +class MapperTest extends \PHPUnit_Framework_TestCase { /** * The object to be tested. * * @var Db */ - protected $db; + protected $adapter; /** * Mock of Storage. @@ -27,17 +27,19 @@ class DbTest extends \PHPUnit_Framework_TestCase */ protected $mapper; + /** + * @covers ZfcUser\Authentication\Storage\Mapper::__construct + */ public function setUp() { - $db = new Db; - $this->db = $db; - - $this->storage = $this->getMock('Zend\Authentication\Storage\Session'); - $this->mapper = $this->getMock('ZfcUser\Mapper\User'); + $this->storage = $this->getMock('Zend\Authentication\Storage\StorageInterface'); + $this->mapper = $this->getMock('ZfcUser\Mapper\UserInterface'); + + $this->adapter = new Mapper($this->mapper, $this->storage); } /** - * @covers ZfcUser\Authentication\Storage\Db::isEmpty + * @covers ZfcUser\Authentication\Storage\Mapper::isEmpty */ public function testIsEmpty() { @@ -45,26 +47,68 @@ public function testIsEmpty() ->method('isEmpty') ->will($this->returnValue(true)); - $this->db->setStorage($this->storage); + $this->assertTrue($this->adapter->isEmpty()); + } - $this->assertTrue($this->db->isEmpty()); + /** + * @covers ZfcUser\Authentication\Storage\Mapper::isEmpty + */ + public function testIsEmptyWhenNotEmpty() + { + $this->adapter->write('identity'); + + $this->storage->expects($this->once()) + ->method('isEmpty') + ->will($this->returnValue(false)); + + $this->storage->expects($this->once()) + ->method('read') + ->will($this->returnValue('identity')); + + $this->mapper->expects($this->once()) + ->method('findById') + ->will($this->returnValue($this->getMock('ZfcUser\Entity\UserInterface'))); + + $this->assertFalse($this->adapter->isEmpty()); } + + /** + * @covers ZfcUser\Authentication\Storage\Mapper::isEmpty + */ + public function testIsEmptyWhenStorageIsEmptyButAdapterHasNoIdentity() + { + $this->adapter->write('identity'); + + $this->storage->expects($this->once()) + ->method('isEmpty') + ->will($this->returnValue(false)); + + $this->storage->expects($this->once()) + ->method('read') + ->will($this->returnValue('identity')); + + $this->mapper->expects($this->once()) + ->method('findById') + ->will($this->returnValue(null)); + $this->assertTrue($this->adapter->isEmpty()); + } + /** - * @covers ZfcUser\Authentication\Storage\Db::read + * @covers ZfcUser\Authentication\Storage\Mapper::read */ public function testReadWithResolvedEntitySet() { - $reflectionClass = new \ReflectionClass('ZfcUser\Authentication\Storage\Db'); + $reflectionClass = new \ReflectionClass('ZfcUser\Authentication\Storage\Mapper'); $reflectionProperty = $reflectionClass->getProperty('resolvedIdentity'); $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($this->db, 'zfcUser'); + $reflectionProperty->setValue($this->adapter, 'zfcUser'); - $this->assertSame('zfcUser', $this->db->read()); + $this->assertSame('zfcUser', $this->adapter->read()); } /** - * @covers ZfcUser\Authentication\Storage\Db::read + * @covers ZfcUser\Authentication\Storage\Mapper::read */ public function testReadWithoutResolvedEntitySetIdentityIntUserFound() { @@ -72,8 +116,6 @@ public function testReadWithoutResolvedEntitySetIdentityIntUserFound() ->method('read') ->will($this->returnValue(1)); - $this->db->setStorage($this->storage); - $user = $this->getMock('ZfcUser\Entity\User'); $user->setUsername('zfcUser'); @@ -82,15 +124,13 @@ public function testReadWithoutResolvedEntitySetIdentityIntUserFound() ->with(1) ->will($this->returnValue($user)); - $this->db->setMapper($this->mapper); - - $result = $this->db->read(); + $result = $this->adapter->read(); $this->assertSame($user, $result); } /** - * @covers ZfcUser\Authentication\Storage\Db::read + * @covers ZfcUser\Authentication\Storage\Mapper::read */ public function testReadWithoutResolvedEntitySetIdentityIntUserNotFound() { @@ -98,22 +138,18 @@ public function testReadWithoutResolvedEntitySetIdentityIntUserNotFound() ->method('read') ->will($this->returnValue(1)); - $this->db->setStorage($this->storage); - $this->mapper->expects($this->once()) ->method('findById') ->with(1) ->will($this->returnValue(false)); - $this->db->setMapper($this->mapper); - - $result = $this->db->read(); + $result = $this->adapter->read(); $this->assertNull($result); } /** - * @covers ZfcUser\Authentication\Storage\Db::read + * @covers ZfcUser\Authentication\Storage\Mapper::read */ public function testReadWithoutResolvedEntitySetIdentityObject() { @@ -124,19 +160,17 @@ public function testReadWithoutResolvedEntitySetIdentityObject() ->method('read') ->will($this->returnValue($user)); - $this->db->setStorage($this->storage); - - $result = $this->db->read(); + $result = $this->adapter->read(); $this->assertSame($user, $result); } /** - * @covers ZfcUser\Authentication\Storage\Db::write + * @covers ZfcUser\Authentication\Storage\Mapper::write */ public function testWrite() { - $reflectionClass = new \ReflectionClass('ZfcUser\Authentication\Storage\Db'); + $reflectionClass = new \ReflectionClass('ZfcUser\Authentication\Storage\Mapper'); $reflectionProperty = $reflectionClass->getProperty('resolvedIdentity'); $reflectionProperty->setAccessible(true); @@ -144,95 +178,26 @@ public function testWrite() ->method('write') ->with('zfcUser'); - $this->db->setStorage($this->storage); + $this->adapter->write('zfcUser'); - $this->db->write('zfcUser'); - - $this->assertNull($reflectionProperty->getValue($this->db)); + $this->assertNull($reflectionProperty->getValue($this->adapter)); } /** - * @covers ZfcUser\Authentication\Storage\Db::clear + * @covers ZfcUser\Authentication\Storage\Mapper::clear */ public function testClear() { - $reflectionClass = new \ReflectionClass('ZfcUser\Authentication\Storage\Db'); + $reflectionClass = new \ReflectionClass('ZfcUser\Authentication\Storage\Mapper'); $reflectionProperty = $reflectionClass->getProperty('resolvedIdentity'); $reflectionProperty->setAccessible(true); $this->storage->expects($this->once()) ->method('clear'); - $this->db->setStorage($this->storage); - - $this->db->clear(); - - $this->assertNull($reflectionProperty->getValue($this->db)); - } - - /** - * @covers ZfcUser\Authentication\Storage\Db::getMapper - */ - public function testGetMapperWithNoMapperSet() - { - $sm = $this->getMock('Zend\ServiceManager\ServiceManager'); - $sm->expects($this->once()) - ->method('get') - ->with('zfcuser_user_mapper') - ->will($this->returnValue($this->mapper)); - - $this->db->setServiceManager($sm); - - $this->assertInstanceOf('ZfcUser\Mapper\UserInterface', $this->db->getMapper()); - } - - /** - * @covers ZfcUser\Authentication\Storage\Db::setMapper - * @covers ZfcUser\Authentication\Storage\Db::getMapper - */ - public function testSetGetMapper() - { - $mapper = new \ZfcUser\Mapper\User; - $mapper->setTableName('zfcUser'); - - $this->db->setMapper($mapper); - - $this->assertInstanceOf('ZfcUser\Mapper\User', $this->db->getMapper()); - $this->assertSame('zfcUser', $this->db->getMapper()->getTableName()); - } + $this->adapter->clear(); - /** - * @covers ZfcUser\Authentication\Storage\Db::setServiceManager - * @covers ZfcUser\Authentication\Storage\Db::getServiceManager - */ - public function testSetGetServicemanager() - { - $sm = $this->getMock('Zend\ServiceManager\ServiceManager'); - - $this->db->setServiceManager($sm); - - $this->assertInstanceOf('Zend\ServiceManager\ServiceLocatorInterface', $this->db->getServiceManager()); - $this->assertSame($sm, $this->db->getServiceManager()); + $this->assertNull($reflectionProperty->getValue($this->adapter)); } - /** - * @covers ZfcUser\Authentication\Storage\Db::getStorage - * @covers ZfcUser\Authentication\Storage\Db::setStorage - */ - public function testGetStorageWithoutStorageSet() - { - $this->assertInstanceOf('Zend\Authentication\Storage\Session', $this->db->getStorage()); - } - - /** - * @covers ZfcUser\Authentication\Storage\Db::getStorage - * @covers ZfcUser\Authentication\Storage\Db::setStorage - */ - public function testSetGetStorage() - { - $storage = new \Zend\Authentication\Storage\Session('ZfcUserStorage'); - $this->db->setStorage($storage); - - $this->assertInstanceOf('Zend\Authentication\Storage\Session', $this->db->getStorage()); - } } diff --git a/tests/ZfcUserTest/Controller/UserControllerTest.php b/tests/ZfcUserTest/Controller/UserControllerTest.php index aca42945..6e92c9cf 100644 --- a/tests/ZfcUserTest/Controller/UserControllerTest.php +++ b/tests/ZfcUserTest/Controller/UserControllerTest.php @@ -207,8 +207,6 @@ public function testLoginActionValidFormRedirectFalse($isValid, $wantRedirect) if ($isValid) { $adapter = $this->getMock('ZfcUser\Authentication\Adapter\AdapterChain'); - $adapter->expects($this->once()) - ->method('resetAdapters'); $service = $this->getMock('Zend\Authentication\AuthenticationService'); $service->expects($this->once()) @@ -349,11 +347,7 @@ public function testLogoutAction($withRedirect, $post, $query) $controller = $this->controller; $adapter = $this->getMock('ZfcUser\Authentication\Adapter\AdapterChain'); - $adapter->expects($this->once()) - ->method('resetAdapters'); - $adapter->expects($this->once()) - ->method('logoutAdapters'); $service = $this->getMock('Zend\Authentication\AuthenticationService'); $service->expects($this->once()) @@ -418,14 +412,14 @@ public function testLogoutAction($withRedirect, $post, $query) public function testLoginRedirectFailsWithUrl() { - + $this->markTestIncomplete(); } /** * @dataProvider providerTestAuthenticateAction * @depend testActionControllHasIdentity */ - public function testAuthenticateAction($wantRedirect, $post, $query, $prepareResult = false, $authValid = false) + public function testAuthenticateAction($wantRedirect, $post, $query, $authValid = false) { $controller = $this->controller; $response = new Response(); @@ -435,12 +429,12 @@ public function testAuthenticateAction($wantRedirect, $post, $query, $prepareRes $params->expects($this->any()) ->method('__invoke') ->will($this->returnSelf()); - $params->expects($this->once()) + $params->expects($this->any()) ->method('fromPost') ->will($this->returnCallback(function ($key, $default) use ($post) { return $post ?: $default; })); - $params->expects($this->once()) + $params->expects($this->any()) ->method('fromQuery') ->will($this->returnCallback(function ($key, $default) use ($query) { return $query ?: $default; @@ -454,9 +448,11 @@ public function testAuthenticateAction($wantRedirect, $post, $query, $prepareRes $adapter = $this->getMock('ZfcUser\Authentication\Adapter\AdapterChain'); $adapter->expects($this->once()) - ->method('prepareForAuthentication') - ->with($request) - ->will($this->returnValue($prepareResult)); + ->method('setIdentity') + ->will($this->returnSelf()); + $adapter->expects($this->once()) + ->method('setCredential') + ->will($this->returnSelf()); $service = $this->getMock('Zend\Authentication\AuthenticationService'); @@ -467,80 +463,72 @@ public function testAuthenticateAction($wantRedirect, $post, $query, $prepareRes 'getAuthService'=>$service )); - if (is_bool($prepareResult)) { - - $authResult = $this->getMockBuilder('Zend\Authentication\Result') - ->disableOriginalConstructor() - ->getMock(); - $authResult->expects($this->once()) - ->method('isValid') - ->will($this->returnValue($authValid)); - - $service->expects($this->once()) - ->method('authenticate') - ->with($adapter) - ->will($this->returnValue($authResult)); - - $redirect = $this->getMock('Zend\Mvc\Controller\Plugin\Redirect'); - $this->pluginManagerPlugins['redirect'] = $redirect; - - if (!$authValid) { - $flashMessenger = $this->getMock( - 'Zend\Mvc\Controller\Plugin\FlashMessenger' - ); - $this->pluginManagerPlugins['flashMessenger']= $flashMessenger; + $authResult = $this->getMockBuilder('Zend\Authentication\Result') + ->disableOriginalConstructor() + ->getMock(); + $authResult->expects($this->once()) + ->method('isValid') + ->will($this->returnValue($authValid)); - $flashMessenger->expects($this->once()) - ->method('setNamespace') - ->with('zfcuser-login-form') - ->will($this->returnSelf()); + $service->expects($this->once()) + ->method('authenticate') + ->with($adapter) + ->will($this->returnValue($authResult)); - $flashMessenger->expects($this->once()) - ->method('addMessage'); + $redirect = $this->getMock('Zend\Mvc\Controller\Plugin\Redirect'); + $this->pluginManagerPlugins['redirect'] = $redirect; - $adapter->expects($this->once()) - ->method('resetAdapters'); + if (!$authValid) { + $flashMessenger = $this->getMock( + 'Zend\Mvc\Controller\Plugin\FlashMessenger' + ); + $this->pluginManagerPlugins['flashMessenger']= $flashMessenger; - $redirectQuery = ($post ?: $query ?: false); - $redirectQuery = $redirectQuery ? '?redirect=' . rawurlencode($redirectQuery) : ''; + $flashMessenger->expects($this->once()) + ->method('setNamespace') + ->with('zfcuser-login-form') + ->will($this->returnSelf()); - $redirect->expects($this->once()) - ->method('toUrl') - ->with('user/login' . $redirectQuery) - ->will($this->returnValue($response)); + $flashMessenger->expects($this->once()) + ->method('addMessage'); - $url = $this->getMock('Zend\Mvc\Controller\Plugin\Url'); - $url->expects($this->once()) - ->method('fromRoute') - ->with($controller::ROUTE_LOGIN) - ->will($this->returnValue('user/login')); - $this->pluginManagerPlugins['url'] = $url; + $redirectQuery = ($post ?: $query ?: false); + $redirectQuery = $redirectQuery ? '?redirect=' . rawurlencode($redirectQuery) : ''; - } elseif ($wantRedirect && $hasRedirect) { - $redirect->expects($this->once()) - ->method('toRoute') - ->with(($post ?: $query ?: false)) - ->will($this->returnValue($response)); - } else { + $redirect->expects($this->once()) + ->method('toUrl') + ->with('user/login' . $redirectQuery) + ->will($this->returnValue($response)); - $redirect->expects($this->once()) - ->method('toRoute') - ->with('zfcuser') - ->will($this->returnValue($response)); + $url = $this->getMock('Zend\Mvc\Controller\Plugin\Url'); + $url->expects($this->once()) + ->method('fromRoute') + ->with($controller::ROUTE_LOGIN) + ->will($this->returnValue('user/login')); + $this->pluginManagerPlugins['url'] = $url; - $this->options->expects($this->once()) - ->method('getLoginRedirectRoute') - ->will($this->returnValue('zfcuser')); - } + } elseif ($wantRedirect && $hasRedirect) { + $redirect->expects($this->once()) + ->method('toRoute') + ->with(($post ?: $query ?: false)) + ->will($this->returnValue($response)); + } else { - $this->options->expects($this->any()) - ->method('getUseRedirectParameterIfPresent') - ->will($this->returnValue((bool) $wantRedirect)); + $redirect->expects($this->once()) + ->method('toRoute') + ->with('zfcuser') + ->will($this->returnValue($response)); + $this->options->expects($this->once()) + ->method('getLoginRedirectRoute') + ->will($this->returnValue('zfcuser')); } - $result = $controller->authenticateAction(); + $this->options->expects($this->any()) + ->method('getUseRedirectParameterIfPresent') + ->will($this->returnValue((bool) $wantRedirect)); + $result = $controller->authenticateAction(); } @@ -751,24 +739,24 @@ public function providerTestAuthenticateAction () { // $redirect, $post, $query, $prepareResult = false, $authValid = false return array( - array(false, null, null, new Response(), false), - array(false, null, null, false, false), - array(false, null, null, false, true), - array(false, 'localhost/test1', null, false, false), - array(false, 'localhost/test1', null, false, true), - array(false, 'localhost/test1', 'localhost/test2', false, false), - array(false, 'localhost/test1', 'localhost/test2', false, true), - array(false, null, 'localhost/test2', false, false), - array(false, null, 'localhost/test2', false, true), - - array(true, null, null, false, false), - array(true, null, null, false, true), - array(true, 'localhost/test1', null, false, false), - array(true, 'localhost/test1', null, false, true), - array(true, 'localhost/test1', 'localhost/test2', false, false), - array(true, 'localhost/test1', 'localhost/test2', false, true), - array(true, null, 'localhost/test2', false, false), - array(true, null, 'localhost/test2', false, true), + array(false, null, null, false), + array(false, null, null, false), + array(false, null, null, true), + array(false, 'localhost/test1', null, false), + array(false, 'localhost/test1', null, true), + array(false, 'localhost/test1', 'localhost/test2', false), + array(false, 'localhost/test1', 'localhost/test2', true), + array(false, null, 'localhost/test2', false), + array(false, null, 'localhost/test2', true), + + array(true, null, null, false), + array(true, null, null, true), + array(true, 'localhost/test1', null, false), + array(true, 'localhost/test1', null, true), + array(true, 'localhost/test1', 'localhost/test2', false), + array(true, 'localhost/test1', 'localhost/test2', true), + array(true, null, 'localhost/test2', false), + array(true, null, 'localhost/test2', true), ); } diff --git a/tests/ZfcUserTest/Factory/Authentication/Adapter/AdapterChainFactoryTest.php b/tests/ZfcUserTest/Factory/Authentication/Adapter/AdapterChainFactoryTest.php index c92fcd00..9e1cfe69 100644 --- a/tests/ZfcUserTest/Factory/Authentication/Adapter/AdapterChainFactoryTest.php +++ b/tests/ZfcUserTest/Factory/Authentication/Adapter/AdapterChainFactoryTest.php @@ -1,15 +1,15 @@ serviceLocatorArray[$index]; - } - - /** - * Prepare the object to be tested. - */ - protected function setUp() + public function testCreateService() { $this->serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); - + $this->options = $this->getMockBuilder('ZfcUser\Options\ModuleOptions') - ->disableOriginalConstructor() - ->getMock(); + ->disableOriginalConstructor() + ->getMock(); - $this->serviceLocatorArray = array ( - 'zfcuser_module_options'=>$this->options + $adapters = array( + 9999 => 'adapter1', + 20 => 'adapter2', ); - - $this->serviceLocator->expects($this->any()) - ->method('get') - ->will($this->returnCallback(array($this,'helperServiceLocator'))); - - $this->eventManager = $this->getMock('Zend\EventManager\EventManager'); - - $this->factory = new AdapterChainServiceFactory(); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::createService - */ - public function testCreateService() - { - $adapter = array( - 'adapter1'=> $this->getMock( - 'ZfcUser\Authentication\Adapter\AbstractAdapter', - array('authenticate', 'logout') - ), - 'adapter2'=> $this->getMock( - 'ZfcUser\Authentication\Adapter\AbstractAdapter', - array('authenticate', 'logout') - ) + $adapter1 = $this->getMock('Zend\Authentication\Adapter\AbstractAdapter'); + $adapter2 = $this->getMock('Zend\Authentication\Adapter\AbstractAdapter'); + + $this->options->expects($this->atLeastOnce()) + ->method('getAuthAdapters') + ->will($this->returnValue($adapters)); + + $locatorMap = array( + array('zfcuser_module_options', $this->options), + array('adapter1', $adapter1), + array('adapter2', $adapter2), ); - $adapterNames = array(100=>'adapter1', 200=>'adapter2'); - - $this->serviceLocatorArray = array_merge($this->serviceLocatorArray, $adapter); - - $this->options->expects($this->once()) - ->method('getAuthAdapters') - ->will($this->returnValue($adapterNames)); + + $this->serviceLocator->expects($this->atLeastOnce()) + ->method('get') + ->will($this->returnValueMap($locatorMap)); + $this->factory = new AdapterChainFactory(); + $adapterChain = $this->factory->createService($this->serviceLocator); - $this->assertInstanceOf('ZfcUser\Authentication\Adapter\AdapterChain', $adapterChain); - $this->assertEquals(array('authenticate', 'logout'), $adapterChain->getEventManager()->getEvents()); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::setOptions - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - */ - public function testGetOptionWithSetter() - { - $this->factory->setOptions($this->options); - - $options = $this->factory->getOptions(); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertSame($this->options, $options); - - - $options2 = clone $this->options; - $this->factory->setOptions($options2); - $options = $this->factory->getOptions(); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertNotSame($this->options, $options); - $this->assertSame($options2, $options); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - */ - public function testGetOptionWithLocator() - { - $options = $this->factory->getOptions($this->serviceLocator); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertSame($this->options, $options); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - * @expectedException \ZfcUser\Authentication\Adapter\Exception\OptionsNotFoundException - */ - public function testGetOptionFailing() - { - $options = $this->factory->getOptions(); } } diff --git a/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperEmailFactoryTest.php b/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperEmailFactoryTest.php index c92fcd00..b055cac6 100644 --- a/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperEmailFactoryTest.php +++ b/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperEmailFactoryTest.php @@ -1,134 +1,28 @@ serviceLocatorArray[$index]; - } - - /** - * Prepare the object to be tested. - */ - protected function setUp() - { - $this->serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); - - $this->options = $this->getMockBuilder('ZfcUser\Options\ModuleOptions') - ->disableOriginalConstructor() - ->getMock(); - - $this->serviceLocatorArray = array ( - 'zfcuser_module_options'=>$this->options - ); - - $this->serviceLocator->expects($this->any()) - ->method('get') - ->will($this->returnCallback(array($this,'helperServiceLocator'))); - - $this->eventManager = $this->getMock('Zend\EventManager\EventManager'); - - $this->factory = new AdapterChainServiceFactory(); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::createService - */ public function testCreateService() { - $adapter = array( - 'adapter1'=> $this->getMock( - 'ZfcUser\Authentication\Adapter\AbstractAdapter', - array('authenticate', 'logout') - ), - 'adapter2'=> $this->getMock( - 'ZfcUser\Authentication\Adapter\AbstractAdapter', - array('authenticate', 'logout') - ) + $serviceLocator = new ServiceManager(); + + $serviceLocator->setService( + 'zfcuser_user_mapper', + $this->getMock('ZfcUser\Mapper\UserInterface') ); - $adapterNames = array(100=>'adapter1', 200=>'adapter2'); - - $this->serviceLocatorArray = array_merge($this->serviceLocatorArray, $adapter); - - $this->options->expects($this->once()) - ->method('getAuthAdapters') - ->will($this->returnValue($adapterNames)); - - $adapterChain = $this->factory->createService($this->serviceLocator); - - $this->assertInstanceOf('ZfcUser\Authentication\Adapter\AdapterChain', $adapterChain); - $this->assertEquals(array('authenticate', 'logout'), $adapterChain->getEventManager()->getEvents()); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::setOptions - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - */ - public function testGetOptionWithSetter() - { - $this->factory->setOptions($this->options); - - $options = $this->factory->getOptions(); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertSame($this->options, $options); - - - $options2 = clone $this->options; - $this->factory->setOptions($options2); - $options = $this->factory->getOptions(); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertNotSame($this->options, $options); - $this->assertSame($options2, $options); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - */ - public function testGetOptionWithLocator() - { - $options = $this->factory->getOptions($this->serviceLocator); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertSame($this->options, $options); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - * @expectedException \ZfcUser\Authentication\Adapter\Exception\OptionsNotFoundException - */ - public function testGetOptionFailing() - { - $options = $this->factory->getOptions(); + + $serviceLocator->setService( + 'zfcuser_authentication_credentialprocessor', + $this->getMock('Zend\Crypt\Password\PasswordInterface') + ); + + $factory = new MapperEmailFactory(); + $mapper = $factory->createService($serviceLocator); + $this->assertInstanceOf('ZfcUser\Authentication\Adapter\Mapper', $mapper); } } diff --git a/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperUsernameFactoryTest.php b/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperUsernameFactoryTest.php index c92fcd00..29337efd 100644 --- a/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperUsernameFactoryTest.php +++ b/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperUsernameFactoryTest.php @@ -1,134 +1,28 @@ serviceLocatorArray[$index]; - } - - /** - * Prepare the object to be tested. - */ - protected function setUp() - { - $this->serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); - - $this->options = $this->getMockBuilder('ZfcUser\Options\ModuleOptions') - ->disableOriginalConstructor() - ->getMock(); - - $this->serviceLocatorArray = array ( - 'zfcuser_module_options'=>$this->options - ); - - $this->serviceLocator->expects($this->any()) - ->method('get') - ->will($this->returnCallback(array($this,'helperServiceLocator'))); - - $this->eventManager = $this->getMock('Zend\EventManager\EventManager'); - - $this->factory = new AdapterChainServiceFactory(); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::createService - */ public function testCreateService() { - $adapter = array( - 'adapter1'=> $this->getMock( - 'ZfcUser\Authentication\Adapter\AbstractAdapter', - array('authenticate', 'logout') - ), - 'adapter2'=> $this->getMock( - 'ZfcUser\Authentication\Adapter\AbstractAdapter', - array('authenticate', 'logout') - ) + $serviceLocator = new ServiceManager(); + + $serviceLocator->setService( + 'zfcuser_user_mapper', + $this->getMock('ZfcUser\Mapper\UserInterface') ); - $adapterNames = array(100=>'adapter1', 200=>'adapter2'); - - $this->serviceLocatorArray = array_merge($this->serviceLocatorArray, $adapter); - - $this->options->expects($this->once()) - ->method('getAuthAdapters') - ->will($this->returnValue($adapterNames)); - - $adapterChain = $this->factory->createService($this->serviceLocator); - - $this->assertInstanceOf('ZfcUser\Authentication\Adapter\AdapterChain', $adapterChain); - $this->assertEquals(array('authenticate', 'logout'), $adapterChain->getEventManager()->getEvents()); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::setOptions - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - */ - public function testGetOptionWithSetter() - { - $this->factory->setOptions($this->options); - - $options = $this->factory->getOptions(); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertSame($this->options, $options); - - - $options2 = clone $this->options; - $this->factory->setOptions($options2); - $options = $this->factory->getOptions(); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertNotSame($this->options, $options); - $this->assertSame($options2, $options); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - */ - public function testGetOptionWithLocator() - { - $options = $this->factory->getOptions($this->serviceLocator); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertSame($this->options, $options); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - * @expectedException \ZfcUser\Authentication\Adapter\Exception\OptionsNotFoundException - */ - public function testGetOptionFailing() - { - $options = $this->factory->getOptions(); + + $serviceLocator->setService( + 'zfcuser_authentication_credentialprocessor', + $this->getMock('Zend\Crypt\Password\PasswordInterface') + ); + + $factory = new MapperUsernameFactory(); + $mapper = $factory->createService($serviceLocator); + $this->assertInstanceOf('ZfcUser\Authentication\Adapter\Mapper', $mapper); } } diff --git a/tests/ZfcUserTest/Factory/Authentication/CredentialProcessor/BcryptFactoryTest.php b/tests/ZfcUserTest/Factory/Authentication/CredentialProcessor/BcryptFactoryTest.php index c92fcd00..426b1352 100644 --- a/tests/ZfcUserTest/Factory/Authentication/CredentialProcessor/BcryptFactoryTest.php +++ b/tests/ZfcUserTest/Factory/Authentication/CredentialProcessor/BcryptFactoryTest.php @@ -1,134 +1,23 @@ serviceLocatorArray[$index]; - } - - /** - * Prepare the object to be tested. - */ - protected function setUp() - { - $this->serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); - - $this->options = $this->getMockBuilder('ZfcUser\Options\ModuleOptions') - ->disableOriginalConstructor() - ->getMock(); - - $this->serviceLocatorArray = array ( - 'zfcuser_module_options'=>$this->options - ); - - $this->serviceLocator->expects($this->any()) - ->method('get') - ->will($this->returnCallback(array($this,'helperServiceLocator'))); - - $this->eventManager = $this->getMock('Zend\EventManager\EventManager'); - - $this->factory = new AdapterChainServiceFactory(); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::createService - */ public function testCreateService() { - $adapter = array( - 'adapter1'=> $this->getMock( - 'ZfcUser\Authentication\Adapter\AbstractAdapter', - array('authenticate', 'logout') - ), - 'adapter2'=> $this->getMock( - 'ZfcUser\Authentication\Adapter\AbstractAdapter', - array('authenticate', 'logout') - ) - ); - $adapterNames = array(100=>'adapter1', 200=>'adapter2'); - - $this->serviceLocatorArray = array_merge($this->serviceLocatorArray, $adapter); - - $this->options->expects($this->once()) - ->method('getAuthAdapters') - ->will($this->returnValue($adapterNames)); - - $adapterChain = $this->factory->createService($this->serviceLocator); - - $this->assertInstanceOf('ZfcUser\Authentication\Adapter\AdapterChain', $adapterChain); - $this->assertEquals(array('authenticate', 'logout'), $adapterChain->getEventManager()->getEvents()); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::setOptions - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - */ - public function testGetOptionWithSetter() - { - $this->factory->setOptions($this->options); - - $options = $this->factory->getOptions(); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertSame($this->options, $options); - - - $options2 = clone $this->options; - $this->factory->setOptions($options2); - $options = $this->factory->getOptions(); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertNotSame($this->options, $options); - $this->assertSame($options2, $options); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - */ - public function testGetOptionWithLocator() - { - $options = $this->factory->getOptions($this->serviceLocator); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertSame($this->options, $options); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - * @expectedException \ZfcUser\Authentication\Adapter\Exception\OptionsNotFoundException - */ - public function testGetOptionFailing() - { - $options = $this->factory->getOptions(); + $options = $this->getMock('ZfcUser\Options\ModuleOptions'); + $options->expects($this->once())->method('getPasswordCost')->will($this->returnValue(5)); + + $serviceLocator = new ServiceManager(); + $serviceLocator->setService('zfcuser_module_options', $options); + + $factory = new BcryptFactory(); + $processor = $factory->createService($serviceLocator); + $this->assertInstanceOf('Zend\Crypt\Password\Bcrypt', $processor); + $this->assertEquals(5, $processor->getCost()); } } diff --git a/tests/ZfcUserTest/Factory/Authentication/Storage/MapperFactoryTest.php b/tests/ZfcUserTest/Factory/Authentication/Storage/MapperFactoryTest.php index c92fcd00..24c6fc60 100644 --- a/tests/ZfcUserTest/Factory/Authentication/Storage/MapperFactoryTest.php +++ b/tests/ZfcUserTest/Factory/Authentication/Storage/MapperFactoryTest.php @@ -1,134 +1,28 @@ serviceLocatorArray[$index]; - } - - /** - * Prepare the object to be tested. - */ - protected function setUp() - { - $this->serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); - - $this->options = $this->getMockBuilder('ZfcUser\Options\ModuleOptions') - ->disableOriginalConstructor() - ->getMock(); - - $this->serviceLocatorArray = array ( - 'zfcuser_module_options'=>$this->options - ); - - $this->serviceLocator->expects($this->any()) - ->method('get') - ->will($this->returnCallback(array($this,'helperServiceLocator'))); - - $this->eventManager = $this->getMock('Zend\EventManager\EventManager'); - - $this->factory = new AdapterChainServiceFactory(); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::createService - */ public function testCreateService() { - $adapter = array( - 'adapter1'=> $this->getMock( - 'ZfcUser\Authentication\Adapter\AbstractAdapter', - array('authenticate', 'logout') - ), - 'adapter2'=> $this->getMock( - 'ZfcUser\Authentication\Adapter\AbstractAdapter', - array('authenticate', 'logout') - ) + $serviceLocator = new ServiceManager(); + + $serviceLocator->setService( + 'zfcuser_user_mapper', + $this->getMock('ZfcUser\Mapper\UserInterface') ); - $adapterNames = array(100=>'adapter1', 200=>'adapter2'); - - $this->serviceLocatorArray = array_merge($this->serviceLocatorArray, $adapter); - - $this->options->expects($this->once()) - ->method('getAuthAdapters') - ->will($this->returnValue($adapterNames)); - - $adapterChain = $this->factory->createService($this->serviceLocator); - - $this->assertInstanceOf('ZfcUser\Authentication\Adapter\AdapterChain', $adapterChain); - $this->assertEquals(array('authenticate', 'logout'), $adapterChain->getEventManager()->getEvents()); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::setOptions - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - */ - public function testGetOptionWithSetter() - { - $this->factory->setOptions($this->options); - - $options = $this->factory->getOptions(); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertSame($this->options, $options); - - - $options2 = clone $this->options; - $this->factory->setOptions($options2); - $options = $this->factory->getOptions(); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertNotSame($this->options, $options); - $this->assertSame($options2, $options); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - */ - public function testGetOptionWithLocator() - { - $options = $this->factory->getOptions($this->serviceLocator); - - $this->assertInstanceOf('ZfcUser\Options\ModuleOptions', $options); - $this->assertSame($this->options, $options); - } - - /** - * @covers \ZfcUser\Authentication\Adapter\AdapterChainServiceFactory::getOptions - * @expectedException \ZfcUser\Authentication\Adapter\Exception\OptionsNotFoundException - */ - public function testGetOptionFailing() - { - $options = $this->factory->getOptions(); + + $serviceLocator->setService( + 'zfcuser_authentication_storage_backend', + $this->getMock('Zend\Authentication\Storage\StorageInterface') + ); + + $factory = new MapperFactory(); + $mapper = $factory->createService($serviceLocator); + $this->assertInstanceOf('ZfcUser\Authentication\Storage\Mapper', $mapper); } } diff --git a/tests/ZfcUserTest/Factory/AuthenticationServiceFactoryTest.php b/tests/ZfcUserTest/Factory/AuthenticationServiceFactoryTest.php index 792cc5c0..89178c98 100644 --- a/tests/ZfcUserTest/Factory/AuthenticationServiceFactoryTest.php +++ b/tests/ZfcUserTest/Factory/AuthenticationServiceFactoryTest.php @@ -8,9 +8,15 @@ class AuthenticationServiceFactoryTest extends \PHPUnit_Framework_TestCase { public function testFactory() { + $mapper = $this->getMockBuilder('ZfcUser\Authentication\Storage\Mapper') + ->disableOriginalConstructor() + ->getMock(); + + $adapter = $this->getMock('ZfcUser\Authentication\Adapter\AdapterChain'); + $serviceManager = new ServiceManager; - $serviceManager->setService('ZfcUser\Authentication\Storage\Db', $this->getMock('ZfcUser\Authentication\Storage\Db')); - $serviceManager->setService('ZfcUser\Authentication\Adapter\AdapterChain', $this->getMock('ZfcUser\Authentication\Adapter\AdapterChain')); + $serviceManager->setService('zfcuser_authentication_storage', $mapper); + $serviceManager->setService('ZfcUser\Authentication\Adapter\AdapterChain', $adapter); $factory = new AuthenticationServiceFactory; diff --git a/tests/ZfcUserTest/Options/ModuleOptionsTest.php b/tests/ZfcUserTest/Options/ModuleOptionsTest.php index 86e913c5..cb56055b 100644 --- a/tests/ZfcUserTest/Options/ModuleOptionsTest.php +++ b/tests/ZfcUserTest/Options/ModuleOptionsTest.php @@ -220,7 +220,7 @@ public function testSetGetAllowedLoginStates() */ public function testGetAuthAdapters() { - $this->assertEquals(array(100 => 'ZfcUser\Authentication\Adapter\Db'), $this->options->getAuthAdapters()); + $this->assertEquals(array(100 => 'ZfcUser\Authentication\Adapter\Mapper'), $this->options->getAuthAdapters()); } /** From 084311fec4c528ce3e2d5ad3637cae719f5b2bf7 Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Sat, 17 Jan 2015 14:21:36 -0330 Subject: [PATCH 12/17] CS fixes --- src/ZfcUser/Authentication/Adapter/AdapterChain.php | 8 ++++---- tests/ZfcUserTest/Authentication/Adapter/MapperTest.php | 3 --- tests/ZfcUserTest/Authentication/Storage/MapperTest.php | 1 - .../Authentication/Adapter/MapperEmailFactoryTest.php | 2 +- .../Authentication/Adapter/MapperUsernameFactoryTest.php | 2 +- .../CredentialProcessor/BcryptFactoryTest.php | 6 +++--- .../Factory/Authentication/Storage/MapperFactoryTest.php | 2 +- 7 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/ZfcUser/Authentication/Adapter/AdapterChain.php b/src/ZfcUser/Authentication/Adapter/AdapterChain.php index a775bb28..0c4db3df 100644 --- a/src/ZfcUser/Authentication/Adapter/AdapterChain.php +++ b/src/ZfcUser/Authentication/Adapter/AdapterChain.php @@ -13,7 +13,7 @@ class AdapterChain extends AbstractAdapter */ protected $adapters; - public function __construct() + public function __construct() { $this->adapters = new PriorityList(); $this->adapters->isLIFO(false); @@ -32,19 +32,19 @@ public function attach($name, AbstractAdapter $adapter, $priority = 1) */ public function authenticate() { - foreach ( $this->adapters as $adapter ) { + foreach ($this->adapters as $adapter) { $adapter->setIdentity($this->getIdentity()); $adapter->setCredential($this->getCredential()); $result = $adapter->authenticate(); - if ( $result->isValid() ) { + if ($result->isValid()) { return $result; } } //@TODO throw an exception if no result? (no adapters tried) - return ( isset($result) && $result instanceof Result ) + return (isset($result) && $result instanceof Result) ? $result : new Result(Result::FAILURE_UNCATEGORIZED, null); } diff --git a/tests/ZfcUserTest/Authentication/Adapter/MapperTest.php b/tests/ZfcUserTest/Authentication/Adapter/MapperTest.php index 63d89b98..d21184af 100644 --- a/tests/ZfcUserTest/Authentication/Adapter/MapperTest.php +++ b/tests/ZfcUserTest/Authentication/Adapter/MapperTest.php @@ -9,9 +9,6 @@ class MapperTest extends TestCase { - const PASSWORD_COST_04 = '04'; - const PASSWORD_COST_10 = '10'; - /** * The object to be tested. * diff --git a/tests/ZfcUserTest/Authentication/Storage/MapperTest.php b/tests/ZfcUserTest/Authentication/Storage/MapperTest.php index 5d7eed6e..78ba52b7 100644 --- a/tests/ZfcUserTest/Authentication/Storage/MapperTest.php +++ b/tests/ZfcUserTest/Authentication/Storage/MapperTest.php @@ -199,5 +199,4 @@ public function testClear() $this->assertNull($reflectionProperty->getValue($this->adapter)); } - } diff --git a/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperEmailFactoryTest.php b/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperEmailFactoryTest.php index b055cac6..851adbdb 100644 --- a/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperEmailFactoryTest.php +++ b/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperEmailFactoryTest.php @@ -21,7 +21,7 @@ public function testCreateService() $this->getMock('Zend\Crypt\Password\PasswordInterface') ); - $factory = new MapperEmailFactory(); + $factory = new MapperEmailFactory(); $mapper = $factory->createService($serviceLocator); $this->assertInstanceOf('ZfcUser\Authentication\Adapter\Mapper', $mapper); } diff --git a/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperUsernameFactoryTest.php b/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperUsernameFactoryTest.php index 29337efd..3b557810 100644 --- a/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperUsernameFactoryTest.php +++ b/tests/ZfcUserTest/Factory/Authentication/Adapter/MapperUsernameFactoryTest.php @@ -21,7 +21,7 @@ public function testCreateService() $this->getMock('Zend\Crypt\Password\PasswordInterface') ); - $factory = new MapperUsernameFactory(); + $factory = new MapperUsernameFactory(); $mapper = $factory->createService($serviceLocator); $this->assertInstanceOf('ZfcUser\Authentication\Adapter\Mapper', $mapper); } diff --git a/tests/ZfcUserTest/Factory/Authentication/CredentialProcessor/BcryptFactoryTest.php b/tests/ZfcUserTest/Factory/Authentication/CredentialProcessor/BcryptFactoryTest.php index 426b1352..6049a8cc 100644 --- a/tests/ZfcUserTest/Factory/Authentication/CredentialProcessor/BcryptFactoryTest.php +++ b/tests/ZfcUserTest/Factory/Authentication/CredentialProcessor/BcryptFactoryTest.php @@ -12,12 +12,12 @@ public function testCreateService() $options = $this->getMock('ZfcUser\Options\ModuleOptions'); $options->expects($this->once())->method('getPasswordCost')->will($this->returnValue(5)); - $serviceLocator = new ServiceManager(); + $serviceLocator = new ServiceManager(); $serviceLocator->setService('zfcuser_module_options', $options); - $factory = new BcryptFactory(); + $factory = new BcryptFactory(); $processor = $factory->createService($serviceLocator); - $this->assertInstanceOf('Zend\Crypt\Password\Bcrypt', $processor); + $this->assertInstanceOf('Zend\Crypt\Password\Bcrypt', $processor); $this->assertEquals(5, $processor->getCost()); } } diff --git a/tests/ZfcUserTest/Factory/Authentication/Storage/MapperFactoryTest.php b/tests/ZfcUserTest/Factory/Authentication/Storage/MapperFactoryTest.php index 24c6fc60..eb30fef2 100644 --- a/tests/ZfcUserTest/Factory/Authentication/Storage/MapperFactoryTest.php +++ b/tests/ZfcUserTest/Factory/Authentication/Storage/MapperFactoryTest.php @@ -21,7 +21,7 @@ public function testCreateService() $this->getMock('Zend\Authentication\Storage\StorageInterface') ); - $factory = new MapperFactory(); + $factory = new MapperFactory(); $mapper = $factory->createService($serviceLocator); $this->assertInstanceOf('ZfcUser\Authentication\Storage\Mapper', $mapper); } From 4153c18ef4052f3caf917315af47948320682a12 Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Sat, 17 Jan 2015 22:41:56 -0330 Subject: [PATCH 13/17] Update AdapterChain to trigger relevant events --- .../Authentication/Adapter/AdapterChain.php | 84 ++++++++++++- .../Adapter/AdapterChainTest.php | 113 ++++++++++++++++-- 2 files changed, 182 insertions(+), 15 deletions(-) diff --git a/src/ZfcUser/Authentication/Adapter/AdapterChain.php b/src/ZfcUser/Authentication/Adapter/AdapterChain.php index 0c4db3df..ca0feed7 100644 --- a/src/ZfcUser/Authentication/Adapter/AdapterChain.php +++ b/src/ZfcUser/Authentication/Adapter/AdapterChain.php @@ -2,17 +2,29 @@ namespace ZfcUser\Authentication\Adapter; +use Zend\Authentication\Adapter\ValidatableAdapterInterface; use Zend\Authentication\Adapter\AbstractAdapter; use Zend\Stdlib\PriorityList; use Zend\Authentication\Result; +use ZfcBase\EventManager\EventProvider; -class AdapterChain extends AbstractAdapter +class AdapterChain extends EventProvider implements ValidatableAdapterInterface { /** * @var PriorityList */ protected $adapters; + /** + * @var mixed + */ + protected $credential; + + /** + * @var mixed + */ + protected $identity; + public function __construct() { $this->adapters = new PriorityList(); @@ -21,6 +33,9 @@ public function __construct() public function attach($name, AbstractAdapter $adapter, $priority = 1) { + $argv = compact('name', 'adapter', 'priority'); + $this->getEventManager()->trigger(__FUNCTION__, $this, $argv); + $this->adapters->insert($name, $adapter, $priority); return $this; } @@ -32,20 +47,81 @@ public function attach($name, AbstractAdapter $adapter, $priority = 1) */ public function authenticate() { + $response = $this->getEventManager()->trigger(__FUNCTION__ . '.pre', $this); + if ($response->stopped()) { + return $response->last(); + } + foreach ($this->adapters as $adapter) { $adapter->setIdentity($this->getIdentity()); $adapter->setCredential($this->getCredential()); $result = $adapter->authenticate(); if ($result->isValid()) { + $argv = compact('adapter', 'result'); + $this->getEventManager()->trigger(__FUNCTION__ . '.success', $this, $argv); return $result; } } //@TODO throw an exception if no result? (no adapters tried) - return (isset($result) && $result instanceof Result) - ? $result - : new Result(Result::FAILURE_UNCATEGORIZED, null); + if (!isset($result) || ! $result instanceof Result) { + $result = new Result(Result::FAILURE_UNCATEGORIZED, null); + } + + $argv = compact('result'); + $this->getEventManager()->trigger(__FUNCTION__ . '.failure', $this, $argv); + + return $result; + } + + + /** + * Returns the credential of the account being authenticated, or + * NULL if none is set. + * + * @return mixed + */ + public function getCredential() + { + return $this->credential; + } + + /** + * Sets the credential for binding + * + * @param mixed $credential + * @return AbstractAdapter + */ + public function setCredential($credential) + { + $this->credential = $credential; + + return $this; + } + + /** + * Returns the identity of the account being authenticated, or + * NULL if none is set. + * + * @return mixed + */ + public function getIdentity() + { + return $this->identity; + } + + /** + * Sets the identity for binding + * + * @param mixed $identity + * @return AbstractAdapter + */ + public function setIdentity($identity) + { + $this->identity = $identity; + + return $this; } } diff --git a/tests/ZfcUserTest/Authentication/Adapter/AdapterChainTest.php b/tests/ZfcUserTest/Authentication/Adapter/AdapterChainTest.php index 7873e50b..d6508cf1 100644 --- a/tests/ZfcUserTest/Authentication/Adapter/AdapterChainTest.php +++ b/tests/ZfcUserTest/Authentication/Adapter/AdapterChainTest.php @@ -16,7 +16,6 @@ class AdapterChainTest extends \PHPUnit_Framework_TestCase /** * Prepare the objects to be tested. - * @covers ZfcUser\Authentication\Adapter\AdapterChain::__construct */ protected function setUp() { @@ -25,9 +24,26 @@ protected function setUp() $this->adapterChain->setCredential('credential'); } - /** - * @covers ZfcUser\Authentication\Adapter\AdapterChain::authenticate - */ + public function testAttachTriggersEvent() + { + $adapter1 = $this->getMockForAbstractClass('Zend\Authentication\Adapter\AbstractAdapter'); + + $triggerCount = 0; + $this->adapterChain->getEventManager()->attach('attach', function ($e) use ($adapter1, &$triggerCount) { + $this->assertSame($this->adapterChain, $e->getTarget()); + $this->assertArrayHasKey('name', $e->getParams()); + $this->assertEquals('adapter1', $e->getParam('name')); + $this->assertArrayHasKey('adapter', $e->getParams()); + $this->assertSame($adapter1, $e->getParam('adapter')); + $this->assertArrayHasKey('priority', $e->getParams()); + $this->assertEquals(29, $e->getParam('priority')); + $triggerCount++; + }); + + $this->adapterChain->attach('adapter1', $adapter1, 29); + $this->assertEquals(1, $triggerCount); + } + public function testAuthenticateWithNoAdaptersReturnsUncategorizedFailure() { $result = $this->adapterChain->authenticate(); @@ -38,10 +54,6 @@ public function testAuthenticateWithNoAdaptersReturnsUncategorizedFailure() $this->assertEquals($result->getMessages(), array()); } - /** - * @covers ZfcUser\Authentication\Adapter\AdapterChain::authenticate - * @covers ZfcUser\Authentication\Adapter\AdapterChain::attach - */ public function testAuthenticateWithZeroAdapterMatchesReturnsLastAdapterResult() { $result1 = new Result(Result::FAILURE_IDENTITY_NOT_FOUND, null); @@ -62,11 +74,40 @@ public function testAuthenticateWithZeroAdapterMatchesReturnsLastAdapterResult() $this->assertEquals($result->getMessages(), array()); } + public function testAuthenticateTriggersEventsOnFailure() + { + $em = $this->adapterChain->getEventManager(); + + $triggerCount['pre'] = 0; + $em->attach('authenticate.pre', function ($e) use (&$triggerCount) { + $this->assertSame($this->adapterChain, $e->getTarget()); + $this->assertEmpty($e->getParams()); + $triggerCount['pre']++; + }); + + $triggerCount['success'] = 0; + $em->attach('authenticate.success', function ($e) use (&$triggerCount) { + $this->assertSame($this->adapterChain, $e->getTarget()); + $this->assertArrayHasKey('adapter', $e->getParams()); + $this->assertArrayHasKey('result', $e->getParams()); + $triggerCount['success']++; + }); + + $triggerCount['failure'] = 0; + $em->attach('authenticate.failure', function ($e) use (&$triggerCount) { + $this->assertSame($this->adapterChain, $e->getTarget()); + $this->assertArrayHasKey('result', $e->getParams()); + $triggerCount['failure']++; + }); + + $this->testAuthenticateWithZeroAdapterMatchesReturnsLastAdapterResult(); + $this->assertEquals(1, $triggerCount['pre']); + $this->assertEquals(0, $triggerCount['success']); + $this->assertEquals(1, $triggerCount['failure']); + } + /** * Also enforces FIFO behavior of AdapterChain (If LIFO, adapter2 would execute first) - * - * @covers ZfcUser\Authentication\Adapter\AdapterChain::authenticate - * @covers ZfcUser\Authentication\Adapter\AdapterChain::attach */ public function testAuthenticateWithAdapterMatchReturnsSuccessfulAdapterResult() { @@ -86,4 +127,54 @@ public function testAuthenticateWithAdapterMatchReturnsSuccessfulAdapterResult() $this->assertEquals($result->getIdentity(), $this->adapterChain->getIdentity()); $this->assertEquals($result->getMessages(), array()); } + + public function testAuthenticateTriggersEventsOnSuccess() + { + $em = $this->adapterChain->getEventManager(); + + $triggerCount['pre'] = 0; + $em->attach('authenticate.pre', function ($e) use (&$triggerCount) { + $this->assertSame($this->adapterChain, $e->getTarget()); + $this->assertEmpty($e->getParams()); + $triggerCount['pre']++; + }); + + $triggerCount['success'] = 0; + $em->attach('authenticate.success', function ($e) use (&$triggerCount) { + $this->assertSame($this->adapterChain, $e->getTarget()); + $this->assertArrayHasKey('adapter', $e->getParams()); + $this->assertArrayHasKey('result', $e->getParams()); + $triggerCount['success']++; + }); + + $triggerCount['failure'] = 0; + $em->attach('authenticate.failure', function ($e) use (&$triggerCount) { + $this->assertSame($this->adapterChain, $e->getTarget()); + $this->assertArrayHasKey('result', $e->getParams()); + $triggerCount['failure']++; + }); + + $this->testAuthenticateWithAdapterMatchReturnsSuccessfulAdapterResult(); + $this->assertEquals(1, $triggerCount['pre']); + $this->assertEquals(1, $triggerCount['success']); + $this->assertEquals(0, $triggerCount['failure']); + } + + public function testGetSetCredential() + { + $this->adapterChain->setCredential('foo'); + $this->assertEquals('foo', $this->adapterChain->getCredential()); + + $this->adapterChain->setCredential(null); + $this->assertNull($this->adapterChain->getCredential()); + } + + public function testGetSetIdentity() + { + $this->adapterChain->setIdentity('baz'); + $this->assertEquals('baz', $this->adapterChain->getIdentity()); + + $this->adapterChain->setIdentity(null); + $this->assertNull($this->adapterChain->getIdentity()); + } } From 038ac7ae344095bbc3ca667352e050c1f77c9f24 Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Sat, 17 Jan 2015 22:43:05 -0330 Subject: [PATCH 14/17] Add event listener which regenerates SID on authenticate if Session storage backend is in use --- config/module.config.php | 5 +++ .../Listener/RegenerateSessionIdentifier.php | 23 +++++++++++++ .../RegenerateSessionIdentifierFactory.php | 33 +++++++++++++++++++ .../RegenerateSessionIdentifierTest.php | 18 ++++++++++ tests/phpunit.xml | 1 + 5 files changed, 80 insertions(+) create mode 100644 src/ZfcUser/Authentication/Listener/RegenerateSessionIdentifier.php create mode 100644 src/ZfcUser/Factory/Authentication/Listener/RegenerateSessionIdentifierFactory.php create mode 100644 tests/ZfcUserTest/Authentication/Listener/RegenerateSessionIdentifierTest.php diff --git a/config/module.config.php b/config/module.config.php index 9adac840..aba08f59 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -58,6 +58,11 @@ 'zfcuser_user_mapper' => 'ZfcUser\Factory\UserMapperFactory', 'zfcuser_user_hydrator' => 'ZfcUser\Factory\Mapper\UserHydratorFactory', ), + 'delegators' => array( + 'zfcuser_authentication_storage_backend_session' => array( + 'ZfcUser\Factory\Authentication\Listener\RegenerateSessionIdentifierFactory' + ), + ), 'aliases' => array( 'zfcuser_register_form_hydrator' => 'zfcuser_user_hydrator', 'zfcuser_zend_db_adapter' => 'Zend\Db\Adapter\Adapter', diff --git a/src/ZfcUser/Authentication/Listener/RegenerateSessionIdentifier.php b/src/ZfcUser/Authentication/Listener/RegenerateSessionIdentifier.php new file mode 100644 index 00000000..43e98b8a --- /dev/null +++ b/src/ZfcUser/Authentication/Listener/RegenerateSessionIdentifier.php @@ -0,0 +1,23 @@ +session = $session; + } + + public function __invoke() + { + $this->session->regenerateId(); + } +} diff --git a/src/ZfcUser/Factory/Authentication/Listener/RegenerateSessionIdentifierFactory.php b/src/ZfcUser/Factory/Authentication/Listener/RegenerateSessionIdentifierFactory.php new file mode 100644 index 00000000..97957182 --- /dev/null +++ b/src/ZfcUser/Factory/Authentication/Listener/RegenerateSessionIdentifierFactory.php @@ -0,0 +1,33 @@ +get('SharedEventManager'); + + $manager = $serviceLocator->has('Zend\Session\ManagerInterface') + ? $serviceLocator->get('Zend\Session\ManagerInterface') + : Container::getDefaultManager(); + + // Attach listener to regenerate SID before authentication occurs + $sem->attach( + 'ZfcUser\Authentication\Adapter\AdapterChain', + 'authenticate.pre', + new RegenerateSessionIdentifier($manager) + ); + + return $sessionStorage; + } +} diff --git a/tests/ZfcUserTest/Authentication/Listener/RegenerateSessionIdentifierTest.php b/tests/ZfcUserTest/Authentication/Listener/RegenerateSessionIdentifierTest.php new file mode 100644 index 00000000..a9c99005 --- /dev/null +++ b/tests/ZfcUserTest/Authentication/Listener/RegenerateSessionIdentifierTest.php @@ -0,0 +1,18 @@ +getMock('Zend\Session\SessionManager'); + $manager->expects($this->once()) + ->method('regenerateId'); + + $listener = new RegenerateSessionIdentifier($manager); + $listener(); + } +} diff --git a/tests/phpunit.xml b/tests/phpunit.xml index b63f4e0c..17538289 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -34,5 +34,6 @@ + From 774efa76f4c98ffbeddd159156521f29b6d38c8e Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Sat, 17 Jan 2015 22:46:22 -0330 Subject: [PATCH 15/17] Remove HTML code coverage from phpunit.xml (enabled for debugging, slipped through) [skip ci] --- tests/phpunit.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/phpunit.xml b/tests/phpunit.xml index 17538289..b63f4e0c 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -34,6 +34,5 @@ - From fef538d5cdbe25a98387eb87441c565bed79045b Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Sat, 24 Jan 2015 19:59:51 -0330 Subject: [PATCH 16/17] Simplified AdapterChain by using EventManagerAwareTrait --- .../Authentication/Adapter/AdapterChain.php | 68 ++----------------- .../Adapter/AdapterChainTest.php | 18 ----- 2 files changed, 5 insertions(+), 81 deletions(-) diff --git a/src/ZfcUser/Authentication/Adapter/AdapterChain.php b/src/ZfcUser/Authentication/Adapter/AdapterChain.php index ca0feed7..df435ace 100644 --- a/src/ZfcUser/Authentication/Adapter/AdapterChain.php +++ b/src/ZfcUser/Authentication/Adapter/AdapterChain.php @@ -2,29 +2,20 @@ namespace ZfcUser\Authentication\Adapter; -use Zend\Authentication\Adapter\ValidatableAdapterInterface; use Zend\Authentication\Adapter\AbstractAdapter; use Zend\Stdlib\PriorityList; use Zend\Authentication\Result; -use ZfcBase\EventManager\EventProvider; +use Zend\EventManager\EventManagerAwareTrait; -class AdapterChain extends EventProvider implements ValidatableAdapterInterface +class AdapterChain extends AbstractAdapter { + use EventManagerAwareTrait; + /** * @var PriorityList */ protected $adapters; - - /** - * @var mixed - */ - protected $credential; - - /** - * @var mixed - */ - protected $identity; - + public function __construct() { $this->adapters = new PriorityList(); @@ -75,53 +66,4 @@ public function authenticate() return $result; } - - - /** - * Returns the credential of the account being authenticated, or - * NULL if none is set. - * - * @return mixed - */ - public function getCredential() - { - return $this->credential; - } - - /** - * Sets the credential for binding - * - * @param mixed $credential - * @return AbstractAdapter - */ - public function setCredential($credential) - { - $this->credential = $credential; - - return $this; - } - - /** - * Returns the identity of the account being authenticated, or - * NULL if none is set. - * - * @return mixed - */ - public function getIdentity() - { - return $this->identity; - } - - /** - * Sets the identity for binding - * - * @param mixed $identity - * @return AbstractAdapter - */ - public function setIdentity($identity) - { - $this->identity = $identity; - - return $this; - } } diff --git a/tests/ZfcUserTest/Authentication/Adapter/AdapterChainTest.php b/tests/ZfcUserTest/Authentication/Adapter/AdapterChainTest.php index d6508cf1..fb4601dd 100644 --- a/tests/ZfcUserTest/Authentication/Adapter/AdapterChainTest.php +++ b/tests/ZfcUserTest/Authentication/Adapter/AdapterChainTest.php @@ -159,22 +159,4 @@ public function testAuthenticateTriggersEventsOnSuccess() $this->assertEquals(1, $triggerCount['success']); $this->assertEquals(0, $triggerCount['failure']); } - - public function testGetSetCredential() - { - $this->adapterChain->setCredential('foo'); - $this->assertEquals('foo', $this->adapterChain->getCredential()); - - $this->adapterChain->setCredential(null); - $this->assertNull($this->adapterChain->getCredential()); - } - - public function testGetSetIdentity() - { - $this->adapterChain->setIdentity('baz'); - $this->assertEquals('baz', $this->adapterChain->getIdentity()); - - $this->adapterChain->setIdentity(null); - $this->assertNull($this->adapterChain->getIdentity()); - } } From 49b53c7a6a9ed00cfaca46cedbbe0f17aa1ac63c Mon Sep 17 00:00:00 2001 From: Adam Lundrigan Date: Sat, 24 Jan 2015 20:27:55 -0330 Subject: [PATCH 17/17] Update/Add docblocks were appropriate --- .../Authentication/Adapter/AdapterChain.php | 21 +++++++++++++++++-- src/ZfcUser/Authentication/Adapter/Mapper.php | 12 +++++++++++ .../Listener/RegenerateSessionIdentifier.php | 14 +++++++++++-- src/ZfcUser/Authentication/Storage/Mapper.php | 17 ++++++++++----- 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/ZfcUser/Authentication/Adapter/AdapterChain.php b/src/ZfcUser/Authentication/Adapter/AdapterChain.php index df435ace..e3a93e90 100644 --- a/src/ZfcUser/Authentication/Adapter/AdapterChain.php +++ b/src/ZfcUser/Authentication/Adapter/AdapterChain.php @@ -7,6 +7,12 @@ use Zend\Authentication\Result; use Zend\EventManager\EventManagerAwareTrait; +/** + * Chainable authentication adapter for Zend\Authentication + * + * Allows multiple authentication adapters to be tried in succession, + * breaking the chain on the first adapter to return a successful result + */ class AdapterChain extends AbstractAdapter { use EventManagerAwareTrait; @@ -22,6 +28,14 @@ public function __construct() $this->adapters->isLIFO(false); } + /** + * Attach an authentication adapter to the chain at the specified priority + * + * @param type $name + * @param AbstractAdapter $adapter + * @param type $priority + * @return \ZfcUser\Authentication\Adapter\AdapterChain + */ public function attach($name, AbstractAdapter $adapter, $priority = 1) { $argv = compact('name', 'adapter', 'priority'); @@ -32,9 +46,12 @@ public function attach($name, AbstractAdapter $adapter, $priority = 1) } /** - * Returns the authentication result + * Cycles through the attached adapters, short-circuiting when a + * successful authentication result is returned. Adapters are executed + * in descending priority order, with adapters at the same priority level + * executed in order of registration (FIFO) * - * @return AuthenticationResult + * @return Result */ public function authenticate() { diff --git a/src/ZfcUser/Authentication/Adapter/Mapper.php b/src/ZfcUser/Authentication/Adapter/Mapper.php index 9eea088d..67151643 100644 --- a/src/ZfcUser/Authentication/Adapter/Mapper.php +++ b/src/ZfcUser/Authentication/Adapter/Mapper.php @@ -8,6 +8,10 @@ use Zend\Crypt\Password\PasswordInterface; use Zend\Authentication\Result; +/** + * Authentication adatper which queries the standard ZfcUser mapper for + * an account matching the provided identity and verifies credential match + */ class Mapper extends AbstractAdapter { /** @@ -25,6 +29,11 @@ class Mapper extends AbstractAdapter */ protected $credentialProcessor; + /** + * @param UserMapper $mapper ZfcUser mapper instance + * @param type $mapperMethod Name of mapper method to pass identity into + * @param PasswordInterface $validator Credential validator instance + */ public function __construct(UserMapper $mapper, $mapperMethod, PasswordInterface $validator) { $this->mapper = $mapper; @@ -32,6 +41,9 @@ public function __construct(UserMapper $mapper, $mapperMethod, PasswordInterface $this->credentialProcessor = $validator; } + /** + * @return Result + */ public function authenticate() { $userObject = call_user_func(array($this->mapper, $this->mapperMethod), $this->getIdentity()); diff --git a/src/ZfcUser/Authentication/Listener/RegenerateSessionIdentifier.php b/src/ZfcUser/Authentication/Listener/RegenerateSessionIdentifier.php index 43e98b8a..50304188 100644 --- a/src/ZfcUser/Authentication/Listener/RegenerateSessionIdentifier.php +++ b/src/ZfcUser/Authentication/Listener/RegenerateSessionIdentifier.php @@ -3,19 +3,29 @@ use Zend\Session\SessionManager; +/** + * Listener which provides session fixation protection by regenerating + * the SID before an authentication request is handled + */ class RegenerateSessionIdentifier { /** - * * @var SessionManager */ protected $session; - + + /** + * @param SessionManager $session Session Manager instance + */ public function __construct(SessionManager $session) { $this->session = $session; } + /** + * Regenerate the SID of the session being managed by the + * provided Session Manager + */ public function __invoke() { $this->session->regenerateId(); diff --git a/src/ZfcUser/Authentication/Storage/Mapper.php b/src/ZfcUser/Authentication/Storage/Mapper.php index e91138e1..81d22a5d 100644 --- a/src/ZfcUser/Authentication/Storage/Mapper.php +++ b/src/ZfcUser/Authentication/Storage/Mapper.php @@ -6,6 +6,10 @@ use ZfcUser\Mapper\UserInterface as UserMapper; use ZfcUser\Entity\UserInterface as UserEntity; +/** + * Zend\Authentication Storage decorator which converts user identifier + * stored in the session container to a User entity on read + */ class Mapper implements StorageInterface { /** @@ -19,10 +23,14 @@ class Mapper implements StorageInterface protected $mapper; /** - * @var mixed + * @var UserEntity|null */ protected $resolvedIdentity; + /** + * @param UserMapper $mapper Mapper to load user entity from + * @param StorageInterface $storage Decorated storage object + */ public function __construct(UserMapper $mapper, StorageInterface $storage) { $this->mapper = $mapper; @@ -51,12 +59,11 @@ public function isEmpty() } /** - * Returns the contents of storage - * - * Behavior is undefined when storage is empty. + * Returns the contents of storage as a User entity or null if the + * identifier in storage does not map to an existing user account. * * @throws \Zend\Authentication\Exception\InvalidArgumentException If reading contents from storage is impossible - * @return mixed + * @return UserEntity|null */ public function read() {