src/Security/AdminVoter.php line 29

Open in your IDE?
  1. <?php
  2. //----------------------------------------------------------------------
  3. // src/Security/AdminVoter.php
  4. //----------------------------------------------------------------------
  5. namespace App\Security;
  6. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  7. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  8. use Symfony\Component\Security\Core\Security;
  9. use Doctrine\Persistence\ManagerRegistry;
  10. use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
  11. use Symfony\Component\Security\Core\Role\SwitchUserRole;
  12. use App\Entity\Access;
  13. use App\Entity\Security\Acl;
  14. class AdminVoter extends Voter
  15. {
  16.     const ROLE_ADMIN "is_admin";
  17.     const CAN_BE_IMPERSONATED "can_be_impersonated";
  18.     const IS_GRANTED_CONSTANTS = array(
  19.         self::ROLE_ADMIN,
  20.         self::CAN_BE_IMPERSONATED,
  21.     );
  22.     public function __construct(ManagerRegistry $doctrine)
  23.     {
  24.         $this->em $doctrine->getManager();
  25.     }
  26.     // Plan.io Task #4453 [See AccessVoter for details]
  27.     public function supportsAttribute(string $attribute): bool
  28.     {
  29.         return in_array($attributeself::IS_GRANTED_CONSTANTStrue);
  30.     }
  31.     protected function supports(string $attribute$subject): bool
  32.     {
  33.         // if the attribute isn't one we support, return false
  34.         if (!in_array($attributeself::IS_GRANTED_CONSTANTS))
  35.         {
  36.             return false;
  37.         }
  38.         return true;
  39.     }
  40.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  41.     {
  42.         $user $token->getUser();
  43.         if (!$user instanceof Access)
  44.         {
  45.             // the user must be logged in; if not, deny access
  46.             return false;
  47.         }
  48.         if (!$user->hasRoleAdmin())
  49.         {
  50.             return false;
  51.         }
  52.         switch ($attribute)
  53.         {
  54.             case self::ROLE_ADMIN:
  55.                 return $this->isAdmin($user$token);
  56.             case self::CAN_BE_IMPERSONATED:
  57.                 return $this->canBeImpersonated($user$subject$token);
  58.         }
  59.         throw new \LogicException('This code should not be reached!');
  60.     }
  61.     // https://symfony.com/doc/5.4/security/impersonating_user.html
  62.     private function getOriginalUser($access$token)
  63.     {
  64.         $originalUser null;
  65.         if ($token instanceof SwitchUserToken)
  66.         {
  67.             $originalUser $token->getOriginalToken()->getUser();
  68.         }
  69.         if ($originalUser !== null)
  70.         {
  71.             return $originalUser;
  72.         }
  73.         return $access;
  74.     }
  75.     private function isAdmin(Access $access$token)
  76.     {
  77.         // Make sure we are looking at the right user
  78.         // This ensures that a ROLE_ADMIN with canSwitch
  79.         // cannot have access to stuff limited to true ROLE_ADMIN
  80.         $originalUser $this->getOriginalUser($access$token);
  81.         if ($originalUser !== null)
  82.         {
  83.             if ($originalUser->isAdmin())
  84.             {
  85.                 return true;
  86.             }
  87.             else
  88.             {
  89.                 return false;
  90.             }
  91.         }
  92.         // We already know that this Access is a true ROLE_ADMIN
  93.         return true;
  94.     }
  95.     private function canBeImpersonated(Access $theOneWhoWantsToSwitchAccess $theOneBeingImpersonated$token)
  96.     {
  97.         if ($this->isAdmin($theOneWhoWantsToSwitch$token))
  98.         {
  99.             if ($theOneBeingImpersonated->isActive())
  100.             {
  101.                 return true;
  102.             }
  103.         }
  104.         return false;
  105.     }
  106. }