src/ContentFile/Application/Security/ContentFileVoter.php line 33

Open in your IDE?
  1. <?php
  2. /**
  3.  * This file is part of the educat package.
  4.  *
  5.  * (c) Solvee
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. declare(strict_types=1);
  11. namespace App\ContentFile\Application\Security;
  12. use App\Common\MentorApplicants\MentorApplicantsProviderInterface;
  13. use App\Common\Model\ContentFile\ContentFileInterface;
  14. use App\Common\Model\Core\AccountInterface;
  15. use App\Common\Model\Core\UserInterface;
  16. use App\Common\Model\Mentor\MentorInterface;
  17. use App\Common\Security\AccountRole;
  18. use App\Common\Security\VoterTrait;
  19. use App\ContentFile\Application\DTO\CanCopyContentFileVoterInput;
  20. use LogicException;
  21. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  22. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  23. use Symfony\Component\Security\Core\Security;
  24. /**
  25.  * Class ContentFileVoter
  26.  *
  27.  * @author JarosÅ‚aw Dylewski <jaroslaw.dylewski@interia.pl>
  28.  */
  29. class ContentFileVoter extends Voter
  30. {
  31.     use VoterTrait;
  32.     public const CAN_ACCESS 'access';
  33.     public const CAN_COPY_CONTENT_FILE 'copy_content_file';
  34.     public const CAN_MODIFY_CONTENT_FILE_ACCESS 'modify_access';
  35.     /** @var MentorApplicantsProviderInterface */
  36.     private MentorApplicantsProviderInterface $mentorApplicantsProvider;
  37.     /**
  38.      * @param Security                          $security
  39.      * @param MentorApplicantsProviderInterface $mentorApplicantsProvider
  40.      */
  41.     public function __construct(
  42.         Security                          $security,
  43.         MentorApplicantsProviderInterface $mentorApplicantsProvider
  44.     ) {
  45.         $this->security                 $security;
  46.         $this->mentorApplicantsProvider $mentorApplicantsProvider;
  47.     }
  48.     /**
  49.      * @param string $attribute
  50.      * @param mixed  $subject
  51.      *
  52.      * @return bool
  53.      */
  54.     protected function supports($attribute$subject)
  55.     {
  56.         if (!in_array(
  57.             $attribute,
  58.             [
  59.                 self::CAN_COPY_CONTENT_FILE,
  60.                 self::CAN_MODIFY_CONTENT_FILE_ACCESS,
  61.                 self::CAN_ACCESS,
  62.             ]
  63.         )) {
  64.             return false;
  65.         }
  66.         return $attribute && ($subject instanceof ContentFileInterface || $subject instanceof CanCopyContentFileVoterInput);
  67.     }
  68.     /**
  69.      * @inheritDoc
  70.      */
  71.     protected function voteOnAttribute(mixed $attributemixed $subjectTokenInterface $token)
  72.     {
  73.         $user $token->getUser();
  74.         if (!$user instanceof UserInterface) {
  75.             return false;
  76.         }
  77.         switch ($attribute) {
  78.             case self::CAN_COPY_CONTENT_FILE:
  79.                 return $this->canCopyContentFile($subject$user);
  80.             case self::CAN_MODIFY_CONTENT_FILE_ACCESS:
  81.                 return $this->canModifyAccess($subject$user);
  82.             case self::CAN_ACCESS:
  83.                 return $this->canAccess($subject$user);
  84.             default:
  85.                 throw new LogicException();
  86.         }
  87.     }
  88.     /**
  89.      * @param CanCopyContentFileVoterInput $input
  90.      * @param UserInterface                $user
  91.      *
  92.      * @return bool
  93.      */
  94.     private function canCopyContentFile(CanCopyContentFileVoterInput $inputUserInterface $user): bool
  95.     {
  96.         if ($this->currentUserIsAdmin()) {
  97.             return true;
  98.         }
  99.         $account $user->getAccount();
  100.         $contentFile $input->contentFile;
  101.         if (!$contentFile->hasAccessToContentFile($account)) {
  102.             return false;
  103.         }
  104.         if ($account->isMentor()) {
  105.             return $this->mentorCanCopyFile($input$account);
  106.         }
  107.         if ($account->isApplicant()) {
  108.             return $this->applicantCanCopyFile($input$account);
  109.         }
  110.         return false;
  111.     }
  112.     /**
  113.      * @param ContentFileInterface $contentFile
  114.      * @param UserInterface        $user
  115.      *
  116.      * @return bool
  117.      */
  118.     private function canModifyAccess(ContentFileInterface $contentFileUserInterface $user): bool
  119.     {
  120.         if ($this->currentUserIsAdmin()) {
  121.             return true;
  122.         }
  123.         $account $user->getAccount();
  124.         if (!$account->isApplicant()) {
  125.             return false;
  126.         }
  127.         return $contentFile->hasAccessToContentFile($user->getAccount());
  128.     }
  129.     /**
  130.      * @param ContentFileInterface $contentFile
  131.      * @param UserInterface        $user
  132.      *
  133.      * @return bool
  134.      */
  135.     private function canAccess(ContentFileInterface $contentFileUserInterface $user): bool
  136.     {
  137.         if ($this->currentUserIsAdmin()) {
  138.             return true;
  139.         }
  140.         return $contentFile->hasAccessToContentFile($user->getAccount());
  141.     }
  142.     /**
  143.      * @return bool
  144.      */
  145.     private function currentUserIsAdmin(): bool
  146.     {
  147.         return $this->security->isGranted(AccountRole::ADMIN);
  148.     }
  149.     /**
  150.      * @param CanCopyContentFileVoterInput $input
  151.      * @param AccountInterface             $account
  152.      *
  153.      * @return bool
  154.      */
  155.     private function mentorCanCopyFile(CanCopyContentFileVoterInput $inputAccountInterface $account): bool
  156.     {
  157.         $forAccount $input->forAccount;
  158.         if (!$forAccount->isApplicant()) {
  159.             return false;
  160.         }
  161.         /** @var MentorInterface $mentor */
  162.         $mentor $account->getMentor();
  163.         return $this->mentorApplicantsProvider->doesApplicantBelongToMentor($forAccount->getApplicant(), $mentor);
  164.     }
  165.     /**
  166.      * @param CanCopyContentFileVoterInput $input
  167.      * @param AccountInterface             $account
  168.      *
  169.      * @return bool
  170.      */
  171.     private function applicantCanCopyFile(CanCopyContentFileVoterInput $inputAccountInterface $account): bool
  172.     {
  173.         return $account === $input->forAccount;
  174.     }
  175. }