src/Aqarmap/Bundle/UserBundle/EventListener/SwitchUserSubscriber.php line 56

Open in your IDE?
  1. <?php
  2. namespace Aqarmap\Bundle\UserBundle\EventListener;
  3. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  4. use Symfony\Component\HttpFoundation\RedirectResponse;
  5. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  6. use Symfony\Component\Routing\RouterInterface;
  7. use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
  8. use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
  9. use Symfony\Component\Security\Core\Security;
  10. use Symfony\Component\Security\Core\User\UserInterface;
  11. use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface;
  12. use Symfony\Component\Security\Http\Event\SwitchUserEvent;
  13. use Symfony\Component\Security\Http\SecurityEvents;
  14. use Symfony\Contracts\Translation\TranslatorInterface;
  15. class SwitchUserSubscriber implements EventSubscriberInterface
  16. {
  17.     /**
  18.      * @var RouterInterface
  19.      */
  20.     private $router;
  21.     /**
  22.      * @var SessionInterface
  23.      */
  24.     private $session;
  25.     /**
  26.      * @var RoleHierarchyInterface
  27.      */
  28.     private $roleHierarchy;
  29.     /** @var TranslatorInterface */
  30.     private $translator;
  31.     /** @var Security */
  32.     private $security;
  33.     public function __construct(
  34.         RouterInterface $router,
  35.         SessionInterface $session,
  36.         TokenStorageInterface $tokenStorage,
  37.         RoleHierarchyInterface $roleHierarchy,
  38.         TranslatorInterface $translator,
  39.         Security $security
  40.     ) {
  41.         $this->router $router;
  42.         $this->session $session;
  43.         $this->roleHierarchy $roleHierarchy;
  44.         $this->translator $translator;
  45.         $this->security $security;
  46.     }
  47.     public function onSwitchUser(SwitchUserEvent $event): void
  48.     {
  49.         $token $this->security->getToken();
  50.         $impersonatedUser $event->getTargetUser();
  51.         if ($token instanceof SwitchUserToken) {
  52.             $impersonatorUser $token->getUser();
  53.         }
  54.         if (isset($impersonatorUser)) {
  55.             $this->backToAdmin($impersonatedUser$event);
  56.         } else {
  57.             $this->allowUserToSwitch($impersonatedUser$event$token);
  58.         }
  59.     }
  60.     public static function getSubscribedEvents()
  61.     {
  62.         return [
  63.             SecurityEvents::SWITCH_USER => 'onSwitchUser',
  64.         ];
  65.     }
  66.     /**
  67.      * @return RedirectResponse|void
  68.      */
  69.     private function allowUserToSwitch(UserInterface $impersonatedUser$event$token)
  70.     {
  71.         if ($this->hasRoleSuperAdmin($impersonatedUser) || $this->hasRoleAdmin($impersonatedUser)) {
  72.             $this->session->getFlashBag()->add(
  73.                 'danger',
  74.                 $this->translator->trans('switch_user.error_message')
  75.             );
  76.             $response = new RedirectResponse(
  77.                 $this->router->generate('aqarmap_admin_user')
  78.             );
  79.             // Set the token to the impersonator User's token to stop the switching
  80.             $event->setToken($token);
  81.             return $response->send();
  82.         }
  83.     }
  84.     /**
  85.      * @return void
  86.      */
  87.     private function backToAdmin(UserInterface $impersonatorUserSwitchUserEvent $event)
  88.     {
  89.         if ($this->hasRoleSwitchAccount($impersonatorUser)) {
  90.             $this->session->getFlashBag()->add(
  91.                 'success',
  92.                 $this->translator->trans('switch_user.back_to_admin')
  93.             );
  94.             $response = new RedirectResponse(
  95.                 $this->router->generate('aqarmap_admin_user')
  96.             );
  97.             // Set the token to the impresonatorUser's token to stop the switching
  98.             $event->setToken($event->getToken());
  99.             return $response->send();
  100.         }
  101.     }
  102.     /**
  103.      * Check if the user has ROLE_SUPER_ADMIN in its role hierarchy.
  104.      */
  105.     private function hasRoleSuperAdmin(UserInterface $user): bool
  106.     {
  107.         return $this->isGranted($user'ROLE_SUPER_ADMIN');
  108.     }
  109.     /**
  110.      * Check if the user has ROLE_ADMIN in its role hierarchy.
  111.      */
  112.     private function hasRoleAdmin(UserInterface $user): bool
  113.     {
  114.         return $this->isGranted($user'ROLE_ADMIN');
  115.     }
  116.     /**
  117.      * Check if the user has ROLE_SWITCH_ACCOUNT in its role hierarchy.
  118.      */
  119.     private function hasRoleSwitchAccount(UserInterface $user): bool
  120.     {
  121.         return $this->isGranted($user'ROLE_SWITCH_ACCOUNT');
  122.     }
  123.     private function isGranted(UserInterface $userstring $role): bool
  124.     {
  125.         $hasRole false;
  126.         $reachableRoles $this->roleHierarchy->getReachableRoleNames($user->getRoles());
  127.         $reachableRoles array_unique($reachableRoles);
  128.         foreach ($reachableRoles as $reachableRole) {
  129.             if ($reachableRole === $role) {
  130.                 $hasRole true;
  131.             }
  132.         }
  133.         return $hasRole;
  134.     }
  135. }