Commit e2e24dba authored by David Surville's avatar David Surville
Browse files

Merge branch 'zf-3.x' into develop

parents 613dbe9f 5ca0247c
Pipeline #5370 failed with stage
in 9 seconds
......@@ -9,7 +9,7 @@ use Zend\EventManager\EventInterface;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Zend\ModuleManager\Feature\ServiceProviderInterface;
use Zend\ServiceManager\Exception\ServiceNotFoundException;
use Zend\ModuleManager\ModuleManager;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\View\Helper\Navigation;
use ZfcUser\Form\Login;
......@@ -69,14 +69,12 @@ class Module implements AutoloaderProviderInterface, ConfigProviderInterface, Se
/* @var $services \Zend\ServiceManager\ServiceManager */
$services = $application->getServiceManager();
if ($services->has('BjyAuthorize\Service\Authorize')) {
// transmission des ACL aux aides de vue de navigation
try {
$authorizeService = $services->get('BjyAuthorize\Service\Authorize');
/* @var $authorizeService \BjyAuthorize\Service\Authorize */
Navigation::setDefaultAcl($authorizeService->getAcl());
Navigation::setDefaultRole($authorizeService->getIdentity());
} catch (ServiceNotFoundException $snfe) {
// pas de module BjyAuthorize : pas d'ACL
}
/* @var $options ModuleOptions */
......
......@@ -9,6 +9,7 @@ use UnicaenAuth\Controller\UtilisateurControllerFactory;
use UnicaenAuth\Form\Droits\RoleFormFactory;
use UnicaenAuth\Guard\PrivilegeControllerFactory;
use UnicaenAuth\Guard\PrivilegeRouteFactory;
use UnicaenAuth\ORM\Event\Listeners\HistoriqueListenerFactory;
use UnicaenAuth\Provider\Rule\PrivilegeRuleProviderFactory;
use UnicaenAuth\Service\ShibService;
use UnicaenAuth\Service\ShibServiceFactory;
......@@ -490,6 +491,9 @@ return [
'UnicaenAuth\Guard\PrivilegeController' => PrivilegeControllerFactory::class,
'UnicaenAuth\Guard\PrivilegeRoute' => PrivilegeRouteFactory::class,
'UnicaenAuth\Provider\Rule\PrivilegeRuleProvider' => PrivilegeRuleProviderFactory::class,
'UnicaenApp\HistoriqueListener' => HistoriqueListenerFactory::class,
'UnicaenAuth\HistoriqueListener' => HistoriqueListenerFactory::class,
],
'lazy_services' => [
// Mapping services to their class names is required since the ServiceManager is not a declarative DIC.
......
......@@ -104,7 +104,7 @@ class AbstractFactory implements AbstractFactoryInterface
$userService = $container->get('unicaen-auth_user_service');
$adapter->setUserService($userService);
/** @var TreeRouteStack $router */
/** @var mixed $router */
$router = $container->get('router');
$adapter->setRouter($router);
......
......@@ -2,6 +2,7 @@
namespace UnicaenAuth\Authentication\Adapter;
use Exception;
use phpCAS;
use UnicaenApp\Mapper\Ldap\People as LdapPeopleMapper;
use UnicaenAuth\Options\ModuleOptions;
......@@ -13,7 +14,8 @@ use Zend\EventManager\EventInterface;
use Zend\EventManager\EventManager;
use Zend\EventManager\EventManagerAwareInterface;
use Zend\EventManager\EventManagerInterface;
use Zend\Router\Http\TreeRouteStack;
use Zend\Router\RouteInterface;
use Zend\Router\RouteStackInterface;
use ZfcUser\Authentication\Adapter\AbstractAdapter;
use ZfcUser\Authentication\Adapter\ChainableAdapter;
......@@ -63,14 +65,14 @@ class Cas extends AbstractAdapter implements EventManagerAwareInterface
}
/**
* @var TreeRouteStack
* @var RouteInterface
*/
private $router;
/**
* @param TreeRouteStack $router
* @param RouteInterface $router
*/
public function setRouter(TreeRouteStack $router)
public function setRouter(RouteInterface $router)
{
$this->router = $router;
}
......@@ -263,10 +265,14 @@ class Cas extends AbstractAdapter implements EventManagerAwareInterface
}
/**
* @param TreeRouteStack $router
* @param RouteInterface $router
*/
public function reconfigureRoutesForCasAuth(TreeRouteStack $router)
public function reconfigureRoutesForCasAuth(RouteInterface $router)
{
if(!$router instanceof RouteStackInterface) {
return;
}
$router->addRoutes([
// remplace les routes existantes (cf. config du module)
'zfcuser' => [
......
......@@ -7,8 +7,8 @@ use UnicaenApp\Mapper\Ldap\People as LdapPeopleMapper;
use UnicaenAuth\Entity\Db\AbstractUser;
use UnicaenAuth\Entity\Ldap\People;
use UnicaenAuth\Entity\Shibboleth\ShibUser;
use UnicaenAuth\Formatter\RoleFormatter;
use UnicaenAuth\Options\ModuleOptions;
use UnicaenAuth\Service\ShibService;
use UnicaenAuth\Service\Traits\ShibServiceAwareTrait;
use UnicaenAuth\Service\Traits\UserContextServiceAwareTrait;
use UnicaenAuth\Service\UserContext;
......@@ -16,7 +16,7 @@ use Zend\Authentication\AuthenticationService;
use Zend\Http\Request;
use Zend\Http\Response;
use Zend\Mvc\Controller\AbstractActionController;
use ZfcUser\Mapper\User as UserMapper;
use ZfcUser\Mapper\UserInterface;
/**
* @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
......@@ -40,7 +40,7 @@ class UtilisateurController extends AbstractActionController
}
/**
* @var UserMapper
* @var UserInterface
*/
private $userMapper;
......@@ -55,9 +55,9 @@ class UtilisateurController extends AbstractActionController
protected $options;
/**
* @param UserMapper $userMapper
* @param UserInterface $userMapper
*/
public function setUserMapper(UserMapper $userMapper)
public function setUserMapper(UserInterface $userMapper)
{
$this->userMapper = $userMapper;
}
......@@ -78,15 +78,6 @@ class UtilisateurController extends AbstractActionController
$this->options = $options;
}
/**
* @param UserContext $userContextService
* @deprecated Utiliser UserContextServiceAwareTrait::setServiceUserContext() à la place, svp.
*/
public function setUserContextService(UserContext $userContextService)
{
$this->serviceUserContext = $userContextService;
}
/**
* Traite les requêtes AJAX POST de sélection d'un profil utilisateur.
* La sélection est mémorisé en session par le service AuthUserContext.
......@@ -111,8 +102,11 @@ class UtilisateurController extends AbstractActionController
}
if ($addFlashMessage) {
$selectedRole = $this->serviceUserContext->getSelectedIdentityRoleToString();
$message = sprintf("Vous endossez à présent le profil utilisateur <strong>%s</strong>.", $selectedRole);
$selectedRole = $this->serviceUserContext->getSelectedIdentityRole();
$message = sprintf(
"Vous endossez à présent le rôle utilisateur '<strong>%s</strong>'.",
(new RoleFormatter())->format($selectedRole)
);
$this->flashMessenger()->setNamespace('UnicaenAuth/success')->addMessage($message);
}
......@@ -212,7 +206,7 @@ class UtilisateurController extends AbstractActionController
}
/**
* @return UserMapper
* @return UserInterface
*/
public function getUserMapper()
{
......
......@@ -8,7 +8,7 @@ use UnicaenAuth\Options\ModuleOptions;
use UnicaenAuth\Service\ShibService;
use UnicaenAuth\Service\UserContext;
use Zend\Authentication\AuthenticationService;
use ZfcUser\Mapper\UserInterface as UserMapper;
use ZfcUser\Mapper\UserInterface;
class UtilisateurControllerFactory
{
......@@ -18,7 +18,7 @@ class UtilisateurControllerFactory
*/
public function __invoke(ContainerInterface $container)
{
/** @var UserMapper $mapper */
/** @var UserInterface $mapper */
$userMapper = $container->get('zfcuser_user_mapper');
/** @var AuthenticationService $authenticationService */
......
......@@ -2,41 +2,66 @@
namespace UnicaenAuth\Formatter;
use Zend\Permissions\Rbac\RoleInterface;
use Zend\Permissions\Acl\Role\RoleInterface;
class RoleFormatter
{
/**
* Retourne le rôle utilisateur spécifié au format littéral.
* Retourne le rôle spécifié au format littéral.
*
* @param $role
* @param object|RoleInterface|string $role
* @return string
*
* @see formatOne()
*/
public function format($role)
{
return $this->roleToString($role);
return $this->formatOne($role);
}
/**
* Retourne le rôle utilisateur spécifié au format littéral.
* Retourne le rôle spécifié au format littéral.
*
* @param object|RoleInterface|string $role
* @return string
*/
private function roleToString($role)
public function formatOne($role)
{
$string = '?';
$formattedRole = '?';
if ($role instanceof RoleInterface) {
$formattedRole = $role->getRoleId();
}
elseif (is_string($role)) {
$formattedRole = (string) $role;
}
elseif (is_object($role) && method_exists($role, '__toString')) {
$formattedRole = $role;
}
if (is_object($role) && method_exists($role, '__toString')) {
$string = (string) $role;
return $formattedRole;
}
elseif ($role instanceof RoleInterface) {
$string = $role->getRoleId();
/**
* Retourne les rôles spécifiés au format littéral.
*
* @param object[]|RoleInterface[]|string[] $roles
* @return string[]
*/
public function formatMany(array $roles)
{
$formattedRoles = [];
foreach ($roles as $key => $role) {
if ($role instanceof RoleInterface) {
$key = $role->getRoleId();
}
elseif (is_string($role)) {
$string = $role;
$key = $role;
}
$formattedRoles[$key] = $this->formatOne($role);
}
return $string;
return $formattedRoles;
}
}
\ No newline at end of file
......@@ -17,17 +17,18 @@ class MouchardCompleterAuth implements MouchardCompleterInterface
use UserContextServiceAwareTrait;
/**
* @param MouchardMessage $message
* @return $this
*/
public function complete(MouchardMessage $message)
{
$user = $this->getServiceUserContext()->getDbUser();
$user = $this->serviceUserContext->getDbUser();
if ($user){
$message->setUser($user->getDisplayName());
$message->setLogin($user->getUsername());
}
$message->setRole((string)$this->getServiceUserContext()->getSelectedIdentityRole());
$message->setRole((string)$this->serviceUserContext->getSelectedIdentityRole());
return $this;
}
......
<?php
namespace UnicaenAuth\ORM\Event\Listeners;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Events;
use RuntimeException;
use UnicaenApp\Entity\HistoriqueAwareInterface;
use UnicaenAuth\Entity\Db\AbstractUser;
use Zend\Authentication\AuthenticationService;
/**
* Listener Doctrine.
*
* Renseigne si besoin l'heure et l'auteur de la création/modification
* de toute entité dont la classe implémente HistoriqueAwareInterface.
*
* Déclenchement : avant que l'enregistrement ne soit persisté (création) ou mis à jour (update).
*
* @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
* @see HistoriqueAwareInterface
*/
class HistoriqueListener implements EventSubscriber
{
/**
* @var AuthenticationService
*/
private $authenticationService;
/**
* @var mixed
*/
protected $identity;
/**
* @param AuthenticationService $authenticationService
*/
public function setAuthenticationService(AuthenticationService $authenticationService)
{
$this->authenticationService = $authenticationService;
}
/**
* @param LifecycleEventArgs $args
* @throws RuntimeException Aucun utilisateur disponible pour en faire l'auteur de la création/modification
*/
protected function updateHistorique(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
// l'entité doit implémenter l'interface requise
if (! $entity instanceof HistoriqueAwareInterface) {
return;
}
$now = new \DateTime();
if (null === $entity->getHistoCreation()) {
$entity->setHistoCreation($now);
}
// on tente d'abord d'obtenir l'utilisateur connecté pour en faire l'auteur de la création/modification.
$user = $this->getAuthenticatedUser();
// si aucun utilisateur connecté n'est disponible, on utilise l'éventuel auteur existant
if (null === $user) {
$user = $entity->getHistoCreateur();
}
// si nous ne disposons d'aucun utilisateur, basta!
if (null === $user) {
throw new RuntimeException("Aucun utilisateur disponible pour en faire l'auteur de la création/modification.");
}
if (null === $entity->getHistoCreateur()) {
$entity->setHistoCreateur($user);
}
$entity->setHistoModificateur($user);
$entity->setHistoModification($now);
/* ce bloc a été mis en commentaire car il est inutile: cf. 2 lignes précédentes !
if (null === $entity->getHistoDestruction() && null === $entity->getHistoDestructeur()) {
$entity
->setHistoModification($now)
->setHistoModificateur($user);
}
*/
if (null !== $entity->getHistoDestruction() && null === $entity->getHistoDestructeur()) {
$entity->setHistoDestructeur($user);
}
}
/**
* Recherche l'utilisateur connecté pour l'utiliser comme auteur de la création/modification.
*
* @return AbstractUser
*/
private function getAuthenticatedUser()
{
$user = null;
if (($identity = $this->getIdentity())) {
if (isset($identity['db']) && $identity['db'] instanceof AbstractUser) {
/* @var $user AbstractUser */
$user = $identity['db'];
}
}
return $user;
}
/**
* @param LifecycleEventArgs $args
*/
public function prePersist(LifecycleEventArgs $args)
{
$this->updateHistorique($args);
}
/**
* @param PreUpdateEventArgs $args
*/
public function preUpdate(PreUpdateEventArgs $args)
{
$this->updateHistorique($args);
}
/**
* Injecte l'identité authentifiée courante.
*
* @param mixed $identity
* @return self
*/
public function setIdentity($identity)
{
$this->identity = $identity;
return $this;
}
/**
* Retourne l'identité authentifiée courante.
*
* @return mixed
*/
public function getIdentity()
{
if (null === $this->identity) {
$authenticationService = $this->authenticationService;
if ($authenticationService->hasIdentity()) {
$this->identity = $authenticationService->getIdentity();
}
}
return $this->identity;
}
/**
* {@inheritdoc}
*/
public function getSubscribedEvents()
{
return [Events::prePersist, Events::preUpdate];
}
}
\ No newline at end of file
<?php
namespace UnicaenAuth\ORM\Event\Listeners;
use Interop\Container\ContainerInterface;
use Zend\Authentication\AuthenticationService;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
/**
* Description of MouchardServiceFactory
*
* @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
*/
class HistoriqueListenerFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
return $this->__invoke($serviceLocator, '?');
}
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
/** @var AuthenticationService $authenticationService */
$authenticationService = $container->get('Zend\Authentication\AuthenticationService');
$listener = new HistoriqueListener();
$listener->setAuthenticationService($authenticationService);
return $listener;
}
}
......@@ -34,7 +34,7 @@ class AuthorizeService extends \BjyAuthorize\Service\Authorize
if ($this->loading) return 'bjyauthorize-identity';
// on retourne par défaut le rôle sélectionné
$role = $this->getServiceUserContext()->getSelectedIdentityRole();
$role = $this->serviceUserContext->getSelectedIdentityRole();
if ($role) return $role;
$roles = $this->getIdentityProvider()->getIdentityRoles();
......
......@@ -470,8 +470,8 @@ EOS;
'options' => [
'route' => '/connexion',
'defaults' => [
'controller' => 'zfcuser',
'action' => 'login',
'controller' => 'zfcuser', // NB: lorsque l'auth Shibboleth est activée, la page propose
'action' => 'login', // 2 possibilités d'auth : LDAP et Shibboleth.
],
],
],
......
......@@ -3,25 +3,19 @@
namespace UnicaenAuth\Service\Traits;
use UnicaenAuth\Service\UserContext;
use RuntimeException;
/**
* Description of UserContextServiceAwareTrait
*
* @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
* @author Unicaen
*/
trait UserContextServiceAwareTrait
{
/**
* @var UserContext
*/
private $serviceUserContext;
protected $serviceUserContext;
/**
* @param UserContext $serviceUserContext
*
* @return self
*/
public function setServiceUserContext(UserContext $serviceUserContext)
......@@ -30,15 +24,4 @@ trait UserContextServiceAwareTrait
return $this;
}
/**
* @return UserContext
* @throws RuntimeException
*/
public function getServiceUserContext()
{
return $this->serviceUserContext;
}
}
\ No newline at end of file
......@@ -19,6 +19,16 @@ class UserContextFactory
$service = new UserContext();
$service->setAuthenticationService($authenticationService);
//
// NB: il serait souhaitable d'injecter l'identity provider dans le service UserContext en faisant :
//
// $identityProvider = $container->get('BjyAuthorize\Provider\Identity\ProviderInterface');
// $service->setIdentityProvider($identityProvider);
//
// mais c'est impossible pour l'instant car il y a un cycle dans les dépendances entre services qui
// provoque une boucle infinie.
//
return $service;
}
}
\ No newline at end of file
......@@ -5,9 +5,10 @@ namespace UnicaenAuth\Service;
use Doctrine\ORM\EntityManagerInterface;
use UnicaenAuth\Entity\Db\AbstractUser;
use UnicaenAuth\Options\ModuleOptions;
use Zend\Hydrator\HydratorInterface;
use ZfcUser\Entity\UserInterface as UserEntityInterface;
use ZfcUser\Mapper\UserInterface;
class UserMapper extends \ZfcUser\Mapper\User
class UserMapper implements UserInterface
{
//========== repris du module zf-commons/zfc-user-doctrine-orm abandonné =========
/**
......@@ -20,12 +21,21 @@ class UserMapper extends \ZfcUser\Mapper\User
*/
protected $options;
/**
* UserMapper constructor.