src/Security/Voter/SortingSessionVoter.php line 16

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\User;
  7. use MedBrief\MSR\Traits\Security\Authorization\Voter\ClientSortingSessionTrait;
  8. use Override;
  9. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  10. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  11. use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
  12. use Symfony\Component\Security\Core\User\UserInterface;
  13. class SortingSessionVoter implements VoterInterface
  14. {
  15. use ClientSortingSessionTrait;
  16. public const CREATE = 'CREATE';
  17. public const READ = 'READ';
  18. public const UPDATE = 'UPDATE';
  19. public const UPDATE_SIMPLE = 'UPDATE_SIMPLE';
  20. public const DELETE = 'DELETE';
  21. public const ADMINISTRATION = 'ADMINISTRATION';
  22. public const SEND_TO_SORTER = 'SEND_TO_SORTER';
  23. public const DOWNLOAD = 'DOWNLOAD';
  24. public const SORT = 'SORT';
  25. public const LIST_MEMO = 'LIST_MEMO';
  26. public const PREVIEW_MEMO = 'PREVIEW_MEMO';
  27. public const EDIT_MEMO_NOTES = 'EDIT_MEMO_NOTES';
  28. public const CREATE_MEMO = 'CREATE_MEMO';
  29. public const PUSH_UNSORTED = 'PUSH_UNSORTED';
  30. public const UNLOCK_SORT = 'UNLOCK_SORT';
  31. public const MORE_OPTIONS = 'MORE_OPTIONS';
  32. public const NOTE_ADMINISTRATION = 'NOTE_ADMINISTRATION';
  33. public const PREVIEW_INDEX = 'PREVIEW_INDEX';
  34. public const UPDATE_CENTRE = 'UPDATE_CENTRE';
  35. public const MANAGE_RESTORE_POINT = 'MANAGE_RESTORE_POINT';
  36. public const CANCEL_PREPROCESSING = 'CANCEL_PREPROCESSING';
  37. public const RESUBMIT_PREPROCESSING = 'RESUBMIT_PREPROCESSING';
  38. public function __construct(private AuthorizationCheckerInterface $authorizationChecker)
  39. {
  40. }
  41. public function supportsAttribute($attribute): bool
  42. {
  43. return in_array($attribute, [
  44. self::CREATE,
  45. self::READ,
  46. self::UPDATE,
  47. self::UPDATE_SIMPLE,
  48. self::DELETE,
  49. self::ADMINISTRATION,
  50. self::SEND_TO_SORTER,
  51. self::DOWNLOAD,
  52. self::SORT,
  53. self::LIST_MEMO,
  54. self::PREVIEW_MEMO,
  55. self::EDIT_MEMO_NOTES,
  56. self::CREATE_MEMO,
  57. self::PUSH_UNSORTED,
  58. self::UNLOCK_SORT,
  59. self::MORE_OPTIONS,
  60. self::NOTE_ADMINISTRATION,
  61. self::PREVIEW_INDEX,
  62. self::UPDATE_CENTRE,
  63. self::MANAGE_RESTORE_POINT,
  64. self::CANCEL_PREPROCESSING,
  65. self::RESUBMIT_PREPROCESSING,
  66. ]);
  67. }
  68. public function supportsClass($class): bool
  69. {
  70. $supportedClass = SortingSession::class;
  71. return $supportedClass === $class || is_subclass_of($class, $supportedClass);
  72. }
  73. /**
  74. *
  75. * @param mixed $entity
  76. */
  77. #[Override]
  78. public function vote(TokenInterface $token, $entity, array $attributes)
  79. {
  80. /**
  81. * START: This is common code for all Voter::vote() methods
  82. */
  83. // check if class of this object is supported by this voter
  84. if (!$this->supportsClass($entity && !is_array($entity) ? $entity::class : '')) {
  85. return VoterInterface::ACCESS_ABSTAIN;
  86. }
  87. // check if the voter is used correct, only allow one attribute
  88. // this isn't a requirement, it's just one easy way for you to
  89. // design your voter
  90. if (1 !== count($attributes)) {
  91. throw new InvalidArgumentException(
  92. 'Only one attribute is allowed for Medbrief Voters.'
  93. );
  94. }
  95. // set the attribute to check against
  96. $attribute = $attributes[0];
  97. // check if the given attribute is covered by this voter
  98. if (!$this->supportsAttribute($attribute)) {
  99. return VoterInterface::ACCESS_ABSTAIN;
  100. }
  101. /** @var SortingSession $sortingSession */
  102. $sortingSession = $entity;
  103. // Grab Project this SortingSession belongs to, so we can do permission checks at the Project level.
  104. $project = $sortingSession->getProject();
  105. // get current logged in user
  106. /** @var User $user */
  107. $user = $token->getUser();
  108. // make sure there is a user object (i.e. that the user is logged in)
  109. if (!$user instanceof UserInterface) {
  110. return VoterInterface::ACCESS_DENIED;
  111. }
  112. // Deny deletion of a sorting session to everyone except super admins
  113. if ($attribute === self::DELETE && $this->authorizationChecker->isGranted('ROLE_SUPER_ADMIN')) {
  114. return VoterInterface::ACCESS_GRANTED;
  115. }
  116. // Deny updating of sorting session/batchrequest centre to everyone except SuperAdmins
  117. if ($attribute === self::UPDATE_CENTRE && !$this->authorizationChecker->isGranted('ROLE_SUPER_ADMIN')) {
  118. return VoterInterface::ACCESS_DENIED;
  119. }
  120. // Admin users can do everything, except sort a sorting session, this is strictly controlled to the attached user.
  121. if ($attribute !== self::SORT && $this->authorizationChecker->isGranted('ROLE_ADMIN')) {
  122. return VoterInterface::ACCESS_GRANTED;
  123. }
  124. /**
  125. * END: Common code for all Voter:vote() methods. Put custom logic below.
  126. */
  127. if ($attribute === self::SORT) {
  128. // Grant currently assigned sorter access
  129. // This applies to both medbrief and client sorting sessions
  130. if ($entity->getRelevantUserAssigned() === $user) {
  131. return VoterInterface::ACCESS_GRANTED;
  132. }
  133. // If external editing is allowed (via the embedded DocSorter), allow all internal user types to edit all sorting sessions.
  134. if ($entity->allowExternalEditing($user) && $user->isUserTypeInternal()) {
  135. return VoterInterface::ACCESS_GRANTED;
  136. }
  137. }
  138. $clientSessionAccess = [
  139. self::READ,
  140. self::SEND_TO_SORTER,
  141. self::DOWNLOAD,
  142. self::DELETE,
  143. self::UPDATE_SIMPLE,
  144. self::NOTE_ADMINISTRATION,
  145. self::LIST_MEMO,
  146. self::PREVIEW_MEMO,
  147. self::EDIT_MEMO_NOTES,
  148. self::CREATE_MEMO,
  149. self::PREVIEW_INDEX,
  150. ];
  151. // if user is client, grant permission to export, send-to-sorter when that client has DocSorter access and client is administrator for Account
  152. // For the self::SORT permission, the sorting session needs to be externally editable to allow sorting. The allowedExternLEditing function encapsulates the logic for this.
  153. if ((in_array($attribute, $clientSessionAccess) || $attribute === self::SORT && $entity->allowExternalEditing($user)) && $this->hasClientSessionAccess($project, $user, $sortingSession)) {
  154. return VoterInterface::ACCESS_GRANTED;
  155. ;
  156. }
  157. // If we get to the end of this function, then no decisions have been
  158. // made so we deny access
  159. return VoterInterface::ACCESS_DENIED;
  160. }
  161. }