src/Security/UserVoter.php line 11

Open in your IDE?
  1. <?php
  2. namespace App\Security;
  3. use App\Entity\Users;
  4. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  5. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  6. use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
  7. use Doctrine\ORM\EntityManagerInterface;
  8. use App\Service\UserHelper;
  9. class UserVoter extends Voter
  10. {
  11.     const ACCESS= [ 
  12.         'user_edit_super_critical_info' => 'user_edit_super_critical_info'//super admins only
  13.         'user_allowed_4_profile_editor'
  14.             => 'user_allowed_4_profile_editor'//super admins and profiles editor only
  15.         'user_allowed_4_profile_editor_or_self_user_if_only_empty'
  16.             => 'user_allowed_4_profile_editor_or_self_user_if_only_empty'//super admins & profiles editors. And if field is empty then also the user
  17.         'user_edit_critical_info' => 'user_edit_critical_info'//all admins
  18.         'user_edit_info_if_only_empty' => 'user_edit_info_if_only_empty',  //all admins. And if field is empty then also the user
  19.         'user_edit_mobile_num_if_only_empty'
  20.             => 'user_edit_mobile_num_if_only_empty' //super admins. and if field is empty then also vehicles admin and profiles admin
  21.         ];
  22.     /**
  23.      * @var AccessDecisionManager|null
  24.      */
  25.     protected $decisionManager;
  26.     /**
  27.      * @var EntityManager|null
  28.      */
  29.     protected $entityManager;
  30.     /**
  31.      * @var EntityManager|null
  32.      */
  33.     protected $userHelper;
  34.     /**
  35.      * DelegateVoter constructor.
  36.      * @param AccessDecisionManager|null $decisionManager
  37.      * @param EntityManager|null $entityManager
  38.      */
  39.     public function __construct(AccessDecisionManagerInterface $decisionManagerEntityManagerInterface $entityManagerUserHelper $userHelper)
  40.     {
  41.         $this->decisionManager $decisionManager;
  42.         $this->entityManager $entityManager;
  43.         $this->userHelper $userHelper;
  44.     }
  45.     /**
  46.      * determines if your voter should vote on the attribute/subject combination. If you return true, 
  47.      * voteOnAttribute() will be called. Otherwise, your voter is done: some other voter should process this
  48.      */
  49.     protected function supports($attribute$subject)
  50.     {
  51.         // if the attribute isn't one we support, return false
  52.         if (!in_array($attributeself::ACCESS)) {
  53.             return false;
  54.         }
  55.         // only vote on Users objects inside this voter
  56. //        if ($subject && !$subject instanceof Users) {
  57. //            return false;
  58. //        }
  59.         return true;
  60.     }
  61.     /**
  62.      * If you return true from supports(), then this method is called. Your job is simple: return true to allow access 
  63.      * and false to deny access
  64.      */
  65.     protected function voteOnAttribute($attribute$subjectTokenInterface $token)
  66.     {
  67.         $loggedinUser $token->getUser();
  68.         if (!$loggedinUser instanceof Users) {
  69.             return false// the user must be logged in; if not, deny access
  70.         }
  71.         
  72.         // ROLE_SUPER_ADMIN can do anything! The power! Calling decide() on the AccessDecisionManager is essentially the same
  73.         // as calling isGranted() from a controller or other places (it's just a little lower-level, which is necessary for a voter).
  74.         if ($this->decisionManager->decide($token, ['ROLE_SUPER_ADMIN'])) {
  75.             return true;
  76.         }
  77.         switch ($attribute) {
  78.             case self::ACCESS['user_edit_super_critical_info']:
  79.                 //no one except super admins can edit
  80.                 return false;
  81.             case self::ACCESS['user_edit_critical_info']:
  82.                 return $this->decisionManager->decide($token, ['ROLE_ADMIN']); //all admins are allowed
  83.             case self::ACCESS['user_allowed_4_profile_editor']:
  84.                 return $this->decisionManager->decide($token, ['ROLE_PROFILES_EDITOR']); //only profile editors are allowed
  85.             case self::ACCESS['user_edit_info_if_only_empty']:
  86.                 return $this->decisionManager->decide($token, ['ROLE_ADMIN']) || empty($subject); //admin can edit. otherwise, only if field is empty it can be edited
  87.             case self::ACCESS['user_allowed_4_profile_editor_or_self_user_if_only_empty']:
  88.                 return $this->canEditIfRoleProfileEditorOrSelfUserIfEmpty($token$subject);
  89.             case self::ACCESS['user_edit_mobile_num_if_only_empty']:
  90.                 return ($this->decisionManager->decide($token, ['ROLE_VEHICLES_ADMIN']) && empty($subject))
  91.                     || ($this->decisionManager->decide($token, ['ROLE_PROFILES_ADMIN']) && empty($subject)); //vehicles admin and profiles admin can edit only if field is empty
  92.         }
  93.         throw new \LogicException('This code should not be reached!');
  94.     }
  95.     /**
  96.      * allow if
  97.      * 1- the user has ROLE_PROFILES_EDITOR role
  98.      * 2- or he is editing his own info if the field is empty
  99.      */
  100.     private function canEditIfRoleProfileEditorOrSelfUserIfEmpty($token$subject)
  101.     {
  102.         if ($this->decisionManager->decide($token, ['ROLE_PROFILES_EDITOR'])) {
  103.             return true;
  104.         }else if($subject['user']->getUserId() == $token->getUser()->getUserId()
  105.                 && empty($subject['subject']) ){
  106. //            echo "caused by form :". $subject['user']->getUserId() . ':'. $token->getUser()->getUserId();
  107.             return true;
  108.         }
  109. //        die("DIED".$subject['subject']);
  110.         return false;
  111.     }
  112. }