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

[FIX] Lorsque l'usurpateur stoppait l'usurpation, il ne récupérait pas son dernier endossé

parent ba084259
Loading
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ use BjyAuthorize\Provider\Role\ProviderInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use UnicaenAuth\Entity\Db\Role;

/**
 * User entity abstract mother class.
@@ -71,6 +72,13 @@ abstract class AbstractUser implements UserInterface, ProviderInterface
     */
    protected $roles;

    /**
     * @var AbstractRole
     * @ORM\ManyToOne(targetEntity="UnicaenAuth\Entity\Db\Role")
     * @ORM\JoinColumn(name="last_role_id", referencedColumnName="id")
     */
    protected $lastRole;

    /**
     * Initialies the roles variable.
     */
@@ -259,6 +267,25 @@ abstract class AbstractUser implements UserInterface, ProviderInterface
        return $this;
    }

    /**
     * @return AbstractRole|null
     */
    public function getLastRole()
    {
        return $this->lastRole;
    }

    /**
     * @param AbstractRole|null $lastRole
     * @return self
     */
    public function setLastRole(AbstractRole $lastRole = null)
    {
        $this->lastRole = $lastRole;

        return $this;
    }

    /**
     * Retourne true si cet utilisateur est local.
     *
+22 −17
Original line number Diff line number Diff line
@@ -2,11 +2,14 @@

namespace UnicaenAuth\Event\Listener;

use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\ListenerAggregateInterface;
use UnicaenApp\Service\EntityManagerAwareInterface;
use UnicaenApp\Service\EntityManagerAwareTrait;
use UnicaenAuth\Entity\Db\AbstractUser;
use UnicaenAuth\Event\UserAuthenticatedEvent;
use UnicaenAuth\Service\Traits\UserContextServiceAwareTrait;
use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\ListenerAggregateInterface;
use Zend\EventManager\ListenerAggregateTrait;

/**
 * Classe abstraites pour les classes désirant scruter un événement déclenché lors de l'authentification
@@ -14,16 +17,19 @@ use UnicaenAuth\Event\UserAuthenticatedEvent;
 *
 * Événements disponibles :
 * - juste avant que l'entité utilisateur ne soit persistée.
 * - juste après que l'entité utilisateur ait été persistée.
 *
 * @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
 * @see UserAuthenticatedEvent
 */
abstract class AuthenticatedUserSavedAbstractListener implements ListenerAggregateInterface, EntityManagerAwareInterface
{
    use ListenerAggregateTrait;
    use EntityManagerAwareTrait;
    use UserContextServiceAwareTrait;

    /**
     * @var \Zend\Stdlib\CallbackHandler[]
     * @var callable[]
     */
    protected $listeners = [];

@@ -31,20 +37,33 @@ abstract class AuthenticatedUserSavedAbstractListener implements ListenerAggrega
     * Méthode appelée juste avant que l'entité utilisateur soit persistée.
     *
     * @param UserAuthenticatedEvent $e
     * @return void
     */
    public function onUserAuthenticatedPrePersist(UserAuthenticatedEvent $e)
    {
        /** @var AbstractUser $user */
        $user = $e->getDbUser();

        // Sélection du dernier rôle endossé.
        $this->selectLastUserRole($user);
    }

    /**
     * Méthode appelée juste après que l'entité utilisateur soit persistée.
     *
     * @param UserAuthenticatedEvent $e
     * @return void
     */
    public function onUserAuthenticatedPostPersist(UserAuthenticatedEvent $e)
    {
        // nop
    }

    protected function selectLastUserRole(AbstractUser $user)
    {
        if ($role = $user->getLastRole()) {
            $this->serviceUserContext->setNextSelectedIdentityRole($role);
        }
    }

    /**
@@ -66,18 +85,4 @@ abstract class AuthenticatedUserSavedAbstractListener implements ListenerAggrega
            [$this, 'onUserAuthenticatedPostPersist'],
            100);
    }

    /**
     * Detach all previously attached listeners
     *
     * @param EventManagerInterface $events
     */
    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $listener) {
            if ($events->detach($listener)) {
                unset($this->listeners[$index]);
            }
        }
    }
}
 No newline at end of file
+37 −3
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@

namespace UnicaenAuth\Service;

use BjyAuthorize\Acl\Role;
use Doctrine\ORM\ORMException;
use UnicaenApp\Exception\RuntimeException;
use UnicaenApp\Traits\SessionContainerTrait;
use UnicaenAuth\Acl\NamedRole;
@@ -10,6 +10,8 @@ use UnicaenAuth\Authentication\SessionIdentity;
use UnicaenAuth\Authentication\Storage\Auth;
use UnicaenAuth\Authentication\Storage\Usurpation;
use UnicaenAuth\Entity\Db\AbstractUser;
use UnicaenAuth\Entity\Db\AbstractRole;
use UnicaenAuth\Entity\Db\Role;
use UnicaenAuth\Entity\Ldap\People;
use UnicaenAuth\Entity\Shibboleth\ShibUser;
use UnicaenAuth\Event\UserRoleSelectedEvent;
@@ -19,8 +21,6 @@ use UnicaenAuth\Provider\Identity\Chain;
use Zend\Authentication\AuthenticationService;
use Zend\EventManager\EventManagerAwareInterface;
use Zend\EventManager\EventManagerAwareTrait;
use Zend\Http\Request;
use Zend\Http\Response;
use Zend\Permissions\Acl\Role\RoleInterface;
use ZfcUser\Entity\UserInterface;

@@ -335,11 +335,35 @@ class UserContext extends AbstractService implements EventManagerAwareInterface
            unset($this->getSessionContainer()->selectedIdentityRole);
        }

        $role = $this->getSelectableIdentityRoles()[$role];
        if ($role instanceof AbstractRole) {
            $this->saveUserLastRole($role);
        }

        $this->triggerUserRoleSelectedEvent(UserRoleSelectedEvent::POST_SELECTION, $role);

        return $this;
    }

    /**
     * @param AbstractRole $role
     */
    private function saveUserLastRole(AbstractRole $role)
    {
        /** @var AbstractUser $user */
        $user = $this->getDbUser();
        if (! $user) {
            return;
        }

        $user->setLastRole($role);
        try {
            $this->getEntityManager()->flush($user);
        } catch (ORMException $e) {
            throw new RuntimeException("Erreur rencontrée lors de l'enregistrement en bdd", null, $e);
        }
    }

    /**
     * Retourne l'éventuel rôle spécifié en session devant être le prochain rôle sélectionné.
     *
@@ -372,6 +396,11 @@ class UserContext extends AbstractService implements EventManagerAwareInterface
            unset($this->getSessionContainer()->nextSelectedIdentityRole);
        }

        $role = $this->getSelectableIdentityRoles()[$role];
        if ($role instanceof AbstractRole) {
            $this->saveUserLastRole($role);
        }

        $this->triggerUserRoleSelectedEvent(UserRoleSelectedEvent::POST_SELECTION, $role);

        return $this;
@@ -499,5 +528,10 @@ class UserContext extends AbstractService implements EventManagerAwareInterface

        $sessionIdentity = SessionIdentity::newInstance($usurpateur->getUsername(), $this->getAuthenticationType());
        $this->authenticationService->getStorage()->write($sessionIdentity);

        // Sélection du dernier rôle endossé.
        if ($role = $usurpateur->getLastRole()) {
            $this->setNextSelectedIdentityRole($role);
        }
    }
}
 No newline at end of file