Commit cc5ed43e authored by Bertrand Gauthier's avatar Bertrand Gauthier
Browse files

Tests unitaires et améliorations/refactorisations.

parent e257996a
......@@ -3,8 +3,6 @@
namespace UnicaenAuth\Authentication\Storage;
use Zend\Authentication\Storage\StorageInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\EventManagerAwareInterface;
use Zend\EventManager\EventManager;
......@@ -17,26 +15,19 @@ use Zend\EventManager\EventManager;
* - Ldap (annuaire LDAP)
* - Db (table des utilisateurs en base de données)
*
*
*
* @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
* @see ChainEvent
* @see \UnicaenAuth\Service\ChainAuthenticationStorageServiceFactory
* @see Ldap
* @see Db
*/
class Chain implements StorageInterface, ServiceLocatorAwareInterface, EventManagerAwareInterface
class Chain implements StorageInterface, EventManagerAwareInterface
{
/**
* @var StorageInterface
*/
protected $storage;
/**
* @var ServiceLocatorInterface
*/
protected $serviceLocator;
/**
* @var EventManagerInterface
*/
......@@ -47,6 +38,11 @@ class Chain implements StorageInterface, ServiceLocatorAwareInterface, EventMana
*/
protected $event;
/**
* @var array
*/
protected $resolvedIdentity;
/**
* Returns true if and only if storage is empty
*
......@@ -68,12 +64,23 @@ class Chain implements StorageInterface, ServiceLocatorAwareInterface, EventMana
*/
public function read()
{
if (null !== $this->resolvedIdentity) {
return $this->resolvedIdentity;
}
$e = $this->getEvent();
$this->getEventManager()->trigger('read', $e);
$identity = $e->getContents();
return $identity;
if ($identity) {
$this->resolvedIdentity = $identity;
}
else {
$this->resolvedIdentity = null;
}
return $this->resolvedIdentity;
}
/**
......@@ -131,28 +138,6 @@ class Chain implements StorageInterface, ServiceLocatorAwareInterface, EventMana
return $this;
}
/**
* Set service locator
*
* @param ServiceLocatorInterface $serviceLocator
* @return self
*/
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
return $this;
}
/**
* Get service locator
*
* @return ServiceLocatorInterface
*/
public function getServiceLocator()
{
return $this->serviceLocator;
}
/**
* Inject an EventManager instance
*
......
......@@ -25,7 +25,6 @@ class ChainServiceFactory implements FactoryInterface
);
$chain = new Chain();
$chain->setServiceLocator($serviceLocator);
foreach ($storages as $priority => $name) {
$storage = $serviceLocator->get($name);
......
......@@ -7,7 +7,9 @@ use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\ServiceManager\Exception\ServiceNotFoundException;
use Zend\Authentication\Exception\InvalidArgumentException;
use ZfcUser\Authentication\Storage\Db as DbStorage;
use Zend\Authentication\Storage\Session;
use Zend\Authentication\Storage\StorageInterface;
use ZfcUser\Mapper\UserInterface as UserMapper;
/**
* Db authentication storage.
......@@ -17,9 +19,14 @@ use ZfcUser\Authentication\Storage\Db as DbStorage;
class Db implements ChainableStorage, ServiceManagerAwareInterface
{
/**
* @var DbStorage
* @var StorageInterface
*/
protected $delegate;
protected $storage;
/**
* @var UserMapper
*/
protected $mapper;
/**
* @var mixed
......@@ -27,47 +34,60 @@ class Db implements ChainableStorage, ServiceManagerAwareInterface
protected $resolvedIdentity;
/**
* Writes $contents to storage
*
* @param mixed $contents
* @throws \Zend\Authentication\Exception\InvalidArgumentException If writing $contents to storage is impossible
* @return void
* @var ServiceManager
*/
public function write(ChainEvent $e)
{
$contents = $e->getParam('contents');
$this->resolvedIdentity = null;
$this->getDelegate()->write($contents);
}
protected $serviceManager;
/**
* Returns the contents of storage
*
* Behavior is undefined when storage is empty.
*
* @params ChainEvent $e
* @throws InvalidArgumentException If reading contents from storage is impossible
* @return \ZfcUser\Entity\UserInterface
* @return void
*/
public function read(ChainEvent $e)
{
if (!$this->resolvedIdentity) {
$identity = $this->findIdentity();
if ($identity) {
$this->resolvedIdentity = $identity;
}
else {
$this->resolvedIdentity = null;
}
}
$e->addContents('db', $identity);
$e->addContents('db', $this->resolvedIdentity);
}
return $identity;
/**
* Writes $contents to storage
*
* @params ChainEvent $e
* @throws \Zend\Authentication\Exception\InvalidArgumentException If writing $contents to storage is impossible
* @return void
*/
public function write(ChainEvent $e)
{
$contents = $e->getParam('contents');
$this->resolvedIdentity = null;
$this->getStorage()->write($contents);
}
/**
* Clears contents from storage
*
* @params ChainEvent $e
* @throws \Zend\Authentication\Exception\InvalidArgumentException If clearing contents from storage is impossible
* @return void
*/
public function clear(ChainEvent $e)
{
$this->resolvedIdentity = null;
$this->getDelegate()->getStorage()->clear();
$this->getStorage()->clear();
}
/**
......@@ -76,8 +96,16 @@ class Db implements ChainableStorage, ServiceManagerAwareInterface
*/
protected function findIdentity()
{
$id = $this->getStorage()->read();
// si on obtient autre chose qu'un scalaire, l'utilisateur a déjà été
// recherché/trouvé dans la base de données
if ($id && !is_scalar($id)) {
return $id;
}
/**
* 1ere tentative (mécanisme standard du module ZfcUser) :
* 1ere tentative :
*
* Recherche dans la base de données de l'utilisateur dont l'id correspond à ce qui
* est stoqué en session.
......@@ -85,8 +113,9 @@ class Db implements ChainableStorage, ServiceManagerAwareInterface
* NB: En cas de problème de connexion ou de service 'zfcuser_user_mapper' introuvable,
* cela signifie sans doute que l'application n'utilise pas de table des utilisateurs.
*/
if (is_int($id) || is_scalar($id)) {
try {
$identity = $this->getDelegate()->read();
$identity = $this->getMapper()->findById($id);
}
catch (PDOException $pdoe) {
$identity = null;
......@@ -94,10 +123,6 @@ class Db implements ChainableStorage, ServiceManagerAwareInterface
catch (ServiceNotFoundException $e) {
$identity = null;
}
// si on obtient autre chose qu'un scalaire, l'utilisateur a déjà été
// recherché/trouvé dans la base de données
if ($identity && !is_scalar($identity)) {
return $identity;
}
/**
......@@ -109,10 +134,9 @@ class Db implements ChainableStorage, ServiceManagerAwareInterface
* NB: En cas de problème de connexion ou de service 'zfcuser_user_mapper' introuvable,
* cela signifie sans doute que l'application n'utilise pas de table des utilisateurs.
*/
$username = $this->getDelegate()->getStorage()->read();
if (is_string($username)) {
if (is_string($id)) {
try {
$identity = $this->getDelegate()->getMapper()->findByUsername($username);
$identity = $this->getMapper()->findByUsername($id);
}
catch (PDOException $pdoe) {
$identity = null;
......@@ -122,14 +146,58 @@ class Db implements ChainableStorage, ServiceManagerAwareInterface
}
}
if ($identity) {
$this->resolvedIdentity = $identity;
return $identity;
}
else {
$this->resolvedIdentity = null;
/**
* getStorage
*
* @return StorageInterface
*/
public function getStorage()
{
if (null === $this->storage) {
$this->setStorage(new Session());
}
return $this->storage;
}
/**
* setStorage
*
* @param StorageInterface $storage
* @access public
* @return Db
*/
public function setStorage(StorageInterface $storage)
{
$this->storage = $storage;
return $this;
}
return $this->resolvedIdentity;
/**
* 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 = null)
{
$this->mapper = $mapper;
return $this;
}
/**
......@@ -146,21 +214,11 @@ class Db implements ChainableStorage, ServiceManagerAwareInterface
* Set service manager instance
*
* @param ServiceManager $locator
* @return void
* @return self
*/
public function setServiceManager(ServiceManager $serviceManager)
{
$this->serviceManager = $serviceManager;
}
/**
* @return DbStorage
*/
protected function getDelegate()
{
if (null === $this->delegate) {
$this->delegate = $this->getServiceManager()->get('ZfcUser\Authentication\Storage\Db');
}
return $this->delegate;
return $this;
}
}
\ No newline at end of file
......@@ -43,17 +43,6 @@ class Ldap implements ChainableStorage, ServiceManagerAwareInterface
*/
protected $serviceManager;
/**
* Returns true if and only if storage is empty
*
* @throws InvalidArgumentException If it is impossible to determine whether storage is empty
* @return boolean
*/
public function isEmpty()
{
return $this->getStorage()->isEmpty();
}
/**
* Returns the contents of storage
*
......@@ -84,8 +73,16 @@ class Ldap implements ChainableStorage, ServiceManagerAwareInterface
$identity = $this->getStorage()->read();
if (is_scalar($identity)) {
try {
$identity = $this->getMapper()->findOneByUsername($identity);
}
catch (\Zend\Ldap\Exception\LdapException $exc) {
$identity = null;
}
catch (\UnicaenApp\Exception $exc) {
$identity = null;
}
}
if ($identity) {
$this->resolvedIdentity = new People($identity);
......@@ -168,7 +165,7 @@ class Ldap implements ChainableStorage, ServiceManagerAwareInterface
* @param LdapPeopleMapper $mapper
* @return Ldap
*/
public function setMapper(LdapPeopleMapper $mapper)
public function setMapper(LdapPeopleMapper $mapper = null)
{
$this->mapper = $mapper;
return $this;
......@@ -188,7 +185,7 @@ class Ldap implements ChainableStorage, ServiceManagerAwareInterface
* Set service manager instance
*
* @param ServiceManager $locator
* @return void
* @return self
*/
public function setServiceManager(ServiceManager $serviceManager)
{
......@@ -199,7 +196,7 @@ class Ldap implements ChainableStorage, ServiceManagerAwareInterface
/**
* @param ModuleOptions $options
*/
public function setOptions(ModuleOptions $options)
public function setOptions(ModuleOptions $options = null)
{
$this->options = $options;
return $this;
......
<?php
namespace UnicaenAuth\Authentication\Storage;
use UnicaenAuth\Entity\Ldap\PeopleAdapter;
use UnicaenAuth\Options\ModuleOptions;
use Zend\Authentication\Exception\InvalidArgumentException;
use Zend\Authentication\Storage;
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use ZfcUser\Entity\UserInterface;
/**
* Ldap/Db mixin authentification storage.
*
* @see Ldap
* @see Db
* @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
*/
class LdapDb implements Storage\StorageInterface, ServiceManagerAwareInterface
{
/**
* @var ServiceManager
*/
protected $serviceManager;
/**
* @var Ldap
*/
protected $ldapStorage;
/**
* @var Db
*/
protected $dbStorage;
/**
* @var ModuleOptions
*/
protected $options;
/**
* Returns true if and only if storage is empty
*
* @throws InvalidArgumentException If it is impossible to determine whether storage is empty
* @return boolean
*/
public function isEmpty()
{
if ($this->getLdapStorage()->isEmpty() && $this->getDbStorage()->isEmpty()) {
return true;
}
return false;
}
/**
* Returns the contents of storage
*
* Behavior is undefined when storage is empty.
*
* @throws InvalidArgumentException If reading contents from storage is impossible
* @return UserInterface
*/
public function read()
{
$identity = null;
$userId = null;
if (($dbIdentity = $this->getDbStorage()->read())) {
$userId = $dbIdentity->getId();
$identity = $dbIdentity;
}
$userExistsInDb = (bool) $dbIdentity;
$userExistsInLdap = $dbIdentity && $dbIdentity->getPassword() === 'ldap';
// NB: si le mot de passe est 'ldap', alors l'utilisateur a été créé à partir de l'annuaire LDAP
if (!$userExistsInDb || $userExistsInLdap) {
// on s'attend à ce que les données en session soient l'entité LDAP correspondant à l'utilisateur connecté
$ldapIdentity = $this->getLdapStorage()->read();
if ($ldapIdentity) {
$identity = new PeopleAdapter($ldapIdentity->getData(), $userId);
}
}
return $identity;
}
/**
* Writes $contents to storage
*
* @param mixed $contents
* @throws InvalidArgumentException If writing $contents to storage is impossible
* @return void
*/
public function write($contents)
{
$this->getLdapStorage()->write($contents);
$this->getDbStorage()->write($contents);
}
/**
* Clears contents from storage
*
* @throws InvalidArgumentException If clearing contents from storage is impossible
* @return void
*/
public function clear()
{
$this->getLdapStorage()->clear();
$this->getDbStorage()->clear();
}
/**
* Retrieve service manager instance
*
* @return ServiceManager
*/
public function getServiceManager()
{
return $this->serviceManager;
}
/**
* Set service manager
*
* @param ServiceManager $serviceManager
* @return LdapDb
*/
public function setServiceManager(ServiceManager $serviceManager)
{
$this->serviceManager = $serviceManager;
return $this;
}
/**
* get db Storage
*
* @return Db
*/
public function getDbStorage()
{
return $this->dbStorage;
}
/**
* set db Storage
*
* @param Db $storage
* @access public
* @return LdapDb
*/
public function setDbStorage(Db $storage)
{
$this->dbStorage = $storage;
return $this;
}
/**
* get ldap Storage
*
* @return Ldap
*/
public function getLdapStorage()
{
return $this->ldapStorage;
}
/**
* set ldap Storage
*
* @param Ldap $storage
* @access public
* @return LdapDb
*/
public function setLdapStorage(Ldap $storage)
{
$this->ldapStorage = $storage;
return $this;
}
/**
* @param ModuleOptions $options
* @return LdapDb
*/
public function setOptions(ModuleOptions $options)
{
$this->options = $options;
return $this;
}
/**
* @return ModuleOptions
*/
public function getOptions()
{
if (null === $this->options) {
$this->setOptions($this->getServiceManager()->get('unicaen-auth_module_options'));
}
return $this->options;
}
}
\ No newline at end of file
......@@ -2,7 +2,6 @@
namespace UnicaenAuth\Entity\Ldap;