src/Security/Voter/SortingSessionDetailVoter.php line 17

Open in your IDE?
  1. <?php
  2. namespace MedBrief\MSR\Security\Voter;
  3. use InvalidArgumentException;
  4. use MedBrief\MSR\Entity\Project;
  5. use MedBrief\MSR\Entity\SortingSession;
  6. use MedBrief\MSR\Entity\SortingSessionDetail;
  7. use MedBrief\MSR\Entity\User;
  8. use MedBrief\MSR\Traits\Security\Authorization\Voter\ClientSortingSessionTrait;
  9. use Override;
  10. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  11. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  12. use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
  13. use Symfony\Component\Security\Core\User\UserInterface;
  14. class SortingSessionDetailVoter implements VoterInterface
  15. {
  16. use ClientSortingSessionTrait;
  17. public const CREATE = 'CREATE';
  18. public const READ = 'READ';
  19. public const UPDATE = 'UPDATE';
  20. public const DELETE = 'DELETE';
  21. public const ADMINISTRATION = 'ADMINISTRATION';
  22. public function __construct(private AuthorizationCheckerInterface $authorizationChecker)
  23. {
  24. }
  25. public function supportsAttribute($attribute): bool
  26. {
  27. return in_array($attribute, [
  28. self::CREATE,
  29. self::READ,
  30. self::UPDATE,
  31. self::DELETE,
  32. self::ADMINISTRATION,
  33. ]);
  34. }
  35. public function supportsClass($class): bool
  36. {
  37. $supportedClass = SortingSessionDetail::class;
  38. return $supportedClass === $class || is_subclass_of($class, $supportedClass);
  39. }
  40. /**
  41. *
  42. * @param mixed $entity
  43. */
  44. #[Override]
  45. public function vote(TokenInterface $token, $entity, array $attributes)
  46. {
  47. /**
  48. * START: This is common code for all Voter::vote() methods
  49. */
  50. // check if class of this object is supported by this voter
  51. if (!$this->supportsClass($entity && !is_array($entity) ? $entity::class : '')) {
  52. return VoterInterface::ACCESS_ABSTAIN;
  53. }
  54. // check if the voter is used correct, only allow one attribute
  55. // this isn't a requirement, it's just one easy way for you to
  56. // design your voter
  57. if (1 !== count($attributes)) {
  58. throw new InvalidArgumentException(
  59. 'Only one attribute is allowed for Medbrief Voters.'
  60. );
  61. }
  62. // set the attribute to check against
  63. $attribute = $attributes[0];
  64. // check if the given attribute is covered by this voter
  65. if (!$this->supportsAttribute($attribute)) {
  66. return VoterInterface::ACCESS_ABSTAIN;
  67. }
  68. /** @var SortingSessionDetail $sortingSessionDetail */
  69. $sortingSessionDetail = $entity;
  70. // Get the sortingSession the by using the SortingSessionDetail being passed into this voter in the $entity variable.
  71. /** @var SortingSession $sortingSession */
  72. $sortingSession = $sortingSessionDetail->getSortingSession();
  73. // Grab Project this SortingSession belongs to, so we can do permission checks at the Project level.
  74. /** @var Project $project */
  75. $project = $sortingSession->getProject();
  76. // get current logged in user.
  77. /** @var User $user */
  78. $user = $token->getUser();
  79. // make sure there is a user object (i.e. that the user is logged in)
  80. if (!$user instanceof UserInterface) {
  81. return VoterInterface::ACCESS_DENIED;
  82. }
  83. // Admin users can do everything
  84. if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) {
  85. return VoterInterface::ACCESS_GRANTED;
  86. }
  87. /**
  88. * END: Common code for all Voter:vote() methods. Put custom logic below.
  89. */
  90. // Check to see if the sorting session and project match
  91. if ($project->getId() !== $sortingSession->getProject()->getId()) {
  92. throw new InvalidArgumentException(
  93. 'The sorting session does not match with this project.'
  94. );
  95. }
  96. // if user is client, grant permission to DELETE
  97. if ($attribute === self::DELETE && $this->hasClientSessionAccess($project, $user, $sortingSession)) {
  98. return VoterInterface::ACCESS_GRANTED;
  99. ;
  100. }
  101. // If we get to the end of this function, then no decisions have been
  102. // made so we deny access
  103. return VoterInterface::ACCESS_DENIED;
  104. }
  105. }