src/Backoffice/BackofficeUser/BackofficeUserVoter.php line 16

Open in your IDE?
  1. <?php
  2. namespace App\Backoffice\BackofficeUser;
  3. use App\Backoffice\Enum\BackofficeFeatureAccessEnum;
  4. use AppBundle\Entity\User;
  5. use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
  6. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  7. use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
  8. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  9. use Symfony\Component\Security\Core\Security;
  10. /**
  11.  * Voter to allow access to Backoffice
  12.  */
  13. class BackofficeUserVoter extends Voter
  14. {
  15.     // This attribute is set on access_control in security.yml
  16.     private const BACKOFFICE 'BACKOFFICE';
  17.     public const BACKOFFICE_CAN_SWITCH 'BACKOFFICE_CAN_SWITCH';
  18.     private Security $security;
  19.     private AccessDecisionManagerInterface $accessDecisionManager;
  20.     public function __construct(Security $securityAccessDecisionManagerInterface $accessDecisionManager)
  21.     {
  22.         $this->security $security;
  23.         $this->accessDecisionManager $accessDecisionManager;
  24.     }
  25.     /**
  26.      * @inheritDoc
  27.      */
  28.     protected function supports($attribute$subject): bool
  29.     {
  30.         return in_array($attribute, [
  31.             self::BACKOFFICE,
  32.             self::BACKOFFICE_CAN_SWITCH,
  33.         ], true);
  34.     }
  35.     /**
  36.      * @inheritDoc
  37.      */
  38.     protected function voteOnAttribute($attribute$subjectTokenInterface $token): bool
  39.     {
  40.         $user $token->getUser();
  41.         // Backoffice users and real users use instance of User
  42.         // Later Backoffice users will have their own entity
  43.         if (!$user instanceof User) {
  44.             return false;
  45.         }
  46.         switch ($attribute) {
  47.             case self::BACKOFFICE:
  48.                 return $this->haveAccess($token);
  49.             case self::BACKOFFICE_CAN_SWITCH:
  50.                 return $this->canSwitch($token);
  51.             default:
  52.                 return false;
  53.         }
  54.     }
  55.     /**
  56.      * @param TokenInterface $token
  57.      * @return bool
  58.      */
  59.     private function haveAccess(TokenInterface $token): bool
  60.     {
  61.         // Vote when a Backoffice user has switched to a User
  62.         // Note: the Security service can grant access only on current user,
  63.         //       so we need to use the AccessDecisionManager instead (used by Security)
  64.         if ($token instanceof SwitchUserToken) {
  65.             return $this->accessDecisionManager->decide($token->getOriginalToken(), [User::ROLE_BACKOFFICE]);
  66.         }
  67.         return $this->security->isGranted(User::ROLE_BACKOFFICE);
  68.     }
  69.     /**
  70.      * @param TokenInterface $token
  71.      * @return bool
  72.      */
  73.     private function canSwitch(TokenInterface $token): bool
  74.     {
  75.         if (!$this->haveAccess($token)) {
  76.             return false;
  77.         }
  78.         /**
  79.          * Already switched
  80.          * @see \Symfony\Component\Security\Http\Firewall\SwitchUserListener::attemptSwitchUser
  81.          */
  82.         if ($this->security->isGranted('ROLE_PREVIOUS_ADMIN')) {
  83.             return false;
  84.         }
  85.         return $this->security->isGranted(BackofficeFeatureAccessEnum::BO_SWITCH_USER);
  86.     }
  87. }