src/Security/Voter/TimeEntryVoter.php line 9

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace App\Security\Voter;
  3. use App\Entity\{Project\ManagerTimeControl\TimeEntryTimeControl\TimeEntryValidationUser};
  4. use App\Service\TimeEntryManagement\IsTimeBlocked;
  5. use Symfony\Component\Security\Core\{Authentication\Token\TokenInterfaceAuthorization\Voter\VoterSecurity};
  6. class TimeEntryVoter extends Voter
  7. {
  8.     public const ENTRY_CREATE 'ENTRY_CREATE';
  9.     public const ENTRY_OPEN 'ENTRY_OPEN';
  10.     public const ENTRY_DELETE 'ENTRY_DELETE';
  11.     public const ENTRY_MODIFY 'ENTRY_MODIFY';
  12.     public const ENTRY_APPROVED 'ENTRY_APPROVED';
  13.     public function __construct(private Security $security, private IsTimeBlocked $isTimeBlocked)
  14.     {
  15.     }
  16.     protected function supports($attribute$subject): bool
  17.     {
  18.         $operations = [
  19.             self::ENTRY_CREATE,
  20.             self::ENTRY_DELETE,
  21.             self::ENTRY_OPEN,
  22.             self::ENTRY_MODIFY,
  23.             self::ENTRY_APPROVED,
  24.         ];
  25.         return \in_array($attribute$operationstrue)
  26.             && $subject instanceof TimeEntry;
  27.     }
  28.     protected function voteOnAttribute($attribute$subjectTokenInterface $token): bool
  29.     {
  30.         $user $token->getUser();
  31.         if (!$user instanceof User) {
  32.             return false;
  33.         }
  34.         try {
  35.             if (!$this->checkFixPermission($user$subject$attribute)) {
  36.                 return false;
  37.             }
  38.             return match ($attribute) {
  39.                 self::ENTRY_CREATE => $this->canUserCreateTimeEntry($user$subject),
  40.                 self::ENTRY_MODIFY => $this->canUserModifyTimeEntry($user$subject),
  41.                 self::ENTRY_DELETE => $this->canUserDeleteTimeEntry($user$subject),
  42.                 self::ENTRY_OPEN => $this->canUserOpenTimeEntry($user$subject),
  43.                 self::ENTRY_APPROVED => $this->canUserApproveTimeEntry($user$subject),
  44.                 default => false,
  45.             };
  46.         } catch (\UnhandledMatchError) {
  47.             return false;
  48.         }
  49.     }
  50.     protected function canUserCreateTimeEntry(User $currentUserTimeEntry $subj): bool
  51.     {
  52.         return $currentUser === $subj->getTask()?->getUser();
  53.     }
  54.     protected function canUserModifyTimeEntry(User $currentUserTimeEntry $subj): bool
  55.     {
  56.         if ($this->canUserCreateTimeEntry($currentUser$subj)) {
  57.             return true;
  58.         }
  59.         return $this->isResponsibleManagerOrHighPrivileges($currentUser$subj);
  60.     }
  61.     protected function isResponsibleManagerOrHighPrivileges(User $currentUserTimeEntry $subj): bool
  62.     {
  63.         if ($this->security->isGranted('ROLE_MASTER_MANAGER')) {
  64.             return true;
  65.         }
  66.         if (!$this->security->isGranted('ROLE_MANAGER')) {
  67.             return false;
  68.         }
  69.         return $this->isUserIsManagerOfProjectForTimeEntry($currentUser$subj);
  70.     }
  71.     protected function canUserDeleteTimeEntry(User $currentUserTimeEntry $subj): bool
  72.     {
  73.         $project $subj->getProject();
  74.         $start $subj->getStart();
  75.         if (!$project) {
  76.             $project $subj->getTask()?->getProject();
  77.         }
  78.         if ((!$project) || ($this->isTimeBlocked)($project$start)) {
  79.             return false;
  80.         }
  81.         if ($currentUser === $subj->getTask()?->getUser()) {
  82.             return true;
  83.         }
  84.         if ($this->security->isGranted('ROLE_MASTER_MANAGER')) {
  85.             return true;
  86.         }
  87.         return false;
  88.     }
  89.     protected function canUserOpenTimeEntry(User $currentUserTimeEntry $subj): bool
  90.     {
  91.         return $this->canUserCreateTimeEntry($currentUser$subj);
  92.     }
  93.     protected function canUserApproveTimeEntry(User $currentUserTimeEntry $subj): bool
  94.     {
  95.         return $this->hasFixedPermission($currentUser$subj);
  96.     }
  97.     protected function isUserIsManagerOfProjectForTimeEntry(User $currentUserTimeEntry $subj): bool
  98.     {
  99.         $manager $currentUser->getManager();
  100.         if (!$manager instanceof Manager) {
  101.             return false;
  102.         }
  103.         $projects $manager->getProjects();
  104.         return $projects->contains($subj->getTask()?->getProject());
  105.     }
  106.     protected function checkFixPermission(User $currentUserTimeEntry $subjstring $attribute): bool
  107.     {
  108.         $fixed $subj->getIsFixed();
  109.         $fixedPermission $this->hasFixedPermission($currentUser$subj);
  110.         $isDeleteOperation = ($attribute === self::ENTRY_DELETE);
  111.         // ТЕ не зафиксирована или Есть доступ на изменение фиксированной ТЕ и это не операция удаления.
  112.         return !($fixed && (!$fixedPermission || $isDeleteOperation));
  113.     }
  114.     protected function hasFixedPermission(User $currentUserTimeEntry $subj): bool
  115.     {
  116.         if ($this->security->isGranted('ROLE_PROJECT_FIXER')) {
  117.             return true;
  118.         }
  119.         if (!$this->security->isGranted('ROLE_USER_FIXER')) {
  120.             return false;
  121.         }
  122.         return $this->isUserIsManagerOfProjectForTimeEntry($currentUser$subj);
  123.     }
  124. }