vendor/datenwerk/ginger-bundle/Security/PersonVoter.php line 12

Open in your IDE?
  1. <?php
  2. namespace DW\GingerBundle\Security;
  3. use DW\GingerBundle\Entity\PersonInterface;
  4. use DW\GingerBundle\Entity\User;
  5. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  6. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  7. use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
  8. use DW\GingerBundle\Entity\GroupInterface;
  9. class PersonVoter extends Voter
  10. {
  11.     const VIEW 'view';
  12.     const EDIT 'edit';
  13.     const CREATE 'create';
  14.     const FIND 'find';
  15.     const ANONYMIZE 'anonymize';
  16.     const DELETE 'delete';
  17.     const EDIT_TROUGH_API 'editTroughApi';
  18.     private AccessDecisionManagerInterface $decisionManager;
  19.     public function __construct(AccessDecisionManagerInterface $decisionManager)
  20.     {
  21.         $this->decisionManager $decisionManager;
  22.     }
  23.     protected function supports($attribute$subject): bool
  24.     {
  25.         // if the attribute isn't one we support, return false
  26.         if (!in_array($attribute, array(self::VIEWself::FINDself::EDITself::CREATEself::ANONYMIZEself::DELETEself::EDIT_TROUGH_API))) {
  27.             return false;
  28.         }
  29.         // only vote on person objects inside this voter
  30.         if (!$subject instanceof PersonInterface) {
  31.             return false;
  32.         }
  33.         return true;
  34.     }
  35.     protected function voteOnAttribute($attribute$subjectTokenInterface $token): bool
  36.     {
  37.         $user $token->getUser();
  38.         if (!$user instanceof User) {
  39.             // the user must be logged in; if not, deny access
  40.             return false;
  41.         }
  42.         /** @var PersonInterface $person */
  43.         $person $subject;
  44.         switch ($attribute) {
  45.             case self::VIEW:
  46.                 return $this->canView($person$token);
  47.             case self::FIND:
  48.                 return $this->canFind($person$token);
  49.             case self::EDIT:
  50.                 return $this->canEdit($person$token);
  51.             case self::CREATE:
  52.                 return $this->canCreate($person$token);
  53.             case self::ANONYMIZE:
  54.                 return $this->canAnonymize($person$token);
  55.             case self::DELETE:
  56.                 return $this->canDelete($person$token);
  57.             case self::EDIT_TROUGH_API:
  58.                 return $this->canEditTroughApi($person$token);
  59.         }
  60.         throw new \LogicException('This code should not be reached!');
  61.     }
  62.     private function canCreate(PersonInterface $personTokenInterface $token): bool
  63.     {
  64.         if ($this->decisionManager->decide($token, ['ROLE_GINGER_CONTACT_CREATE'])) {
  65.             return true;
  66.         }
  67.         return false;
  68.     }
  69.     private function canView(PersonInterface $personTokenInterface $token): bool
  70.     {
  71.         $user $token->getUser();
  72.         if ($user->isGod()) {
  73.             return true;
  74.         }
  75.         // Users groups must share at least one tag with person
  76.         /**@var GroupInterface $group */
  77.         foreach ($user->getGroups() as $group) {
  78.             foreach ($group->getTags() as $groupTag) {
  79.                 if ($person->getTags()->contains($groupTag)) {
  80.                     return true;
  81.                 }
  82.             }
  83.         }
  84.         return false;
  85.     }
  86.     private function canFind(PersonInterface $personTokenInterface $token): bool
  87.     {
  88.         /*
  89.          * Temporarily, all registered users may find any persons.
  90.          * Review/Discussion to be done as part of #22083 et.al.
  91.          *
  92.          * @see https://mantis.dwerk.at/view.php?id=22083
  93.          */
  94.         if ($this->canView($person$token) || $this->decisionManager->decide($token, ['ROLE_USER'])) {
  95.             return true;
  96.         }
  97.         return false;
  98.     }
  99.     private function canEdit(PersonInterface $personTokenInterface $token): bool
  100.     {
  101.         $user $token->getUser();
  102.         if ($this->canView($person$token) && $this->decisionManager->decide($token, ['ROLE_GINGER_CONTACT_EDIT'])) {
  103.             return true;
  104.         }
  105.         if ($user->getPerson() === $token->getUser() && $this->decisionManager->decide($token, ['ROLE_GINGER_USER_EDIT_MYPROFILE'])) {
  106.             // User is linked to contact
  107.             return true;
  108.         }
  109.         return false;
  110.     }
  111.     private function canAnonymize(PersonInterface $personTokenInterface $token): bool
  112.     {
  113.         if ($this->decisionManager->decide($token, ['ROLE_GINGER_CONTACT_ANONYMIZE'])
  114.         && $this->canEdit($person$token)) {
  115.             return true;
  116.         }
  117.         return false;
  118.     }
  119.     private function canDelete(PersonInterface $personTokenInterface $token): bool
  120.     {
  121.         if ($this->canEdit($person$token) && $this->decisionManager->decide($token, ['ROLE_GINGER_CONTACT_DELETE'])) {
  122.             return true;
  123.         }
  124.         return false;
  125.     }
  126.     private function canEditTroughApi(PersonInterface $personTokenInterface $token): bool
  127.     {
  128.         // Anyone can edit persons through the API
  129.         // Is there a better way?
  130.         return true;
  131.     }
  132. }