src/Security/Voter/ChronologyRequestDetailVoter.php line 14

Open in your IDE?
  1. <?php
  2. namespace MedBrief\MSR\Security\Voter;
  3. use InvalidArgumentException;
  4. use MedBrief\MSR\Entity\ChronologyRequestDetail;
  5. use MedBrief\MSR\Entity\User;
  6. use Override;
  7. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  8. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  9. use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
  10. use Symfony\Component\Security\Core\User\UserInterface;
  11. class ChronologyRequestDetailVoter implements VoterInterface
  12. {
  13. public const CREATE = 'CREATE';
  14. public const READ = 'READ';
  15. public const UPDATE = 'UPDATE';
  16. public const DELETE = 'DELETE';
  17. public const ADMINISTRATION = 'ADMINISTRATION';
  18. /**
  19. * @param AuthorizationChecker $authorizationChecker
  20. */
  21. public function __construct(private readonly AuthorizationCheckerInterface $authorizationChecker)
  22. {
  23. }
  24. public function supportsAttribute($attribute): bool
  25. {
  26. return in_array($attribute, [
  27. self::CREATE,
  28. self::READ,
  29. self::UPDATE,
  30. self::DELETE,
  31. self::ADMINISTRATION,
  32. ]);
  33. }
  34. public function supportsClass($class): bool
  35. {
  36. $supportedClass = ChronologyRequestDetail::class;
  37. return $supportedClass === $class || is_subclass_of($class, $supportedClass);
  38. }
  39. /**
  40. *
  41. * @param mixed $entity
  42. */
  43. #[Override]
  44. public function vote(TokenInterface $token, $entity, array $attributes)
  45. {
  46. /**
  47. * START: This is common code for all Voter::vote() methods
  48. */
  49. // check if class of this object is supported by this voter
  50. if (!$this->supportsClass($entity && !is_array($entity) ? $entity::class : '')) {
  51. return VoterInterface::ACCESS_ABSTAIN;
  52. }
  53. // check if the voter is used correct, only allow one attribute
  54. // this isn't a requirement, it's just one easy way for you to
  55. // design your voter
  56. if (1 !== count($attributes)) {
  57. throw new InvalidArgumentException(
  58. 'Only one attribute is allowed for Medbrief Voters.'
  59. );
  60. }
  61. // set the attribute to check against
  62. $attribute = $attributes[0];
  63. // check if the given attribute is covered by this voter
  64. if (!$this->supportsAttribute($attribute)) {
  65. return VoterInterface::ACCESS_ABSTAIN;
  66. }
  67. // get current logged in user
  68. /** @var User $user */
  69. $user = $token->getUser();
  70. // make sure there is a user object (i.e. that the user is logged in)
  71. if (!$user instanceof UserInterface) {
  72. return VoterInterface::ACCESS_DENIED;
  73. }
  74. // Admin users can do everything
  75. if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) {
  76. return VoterInterface::ACCESS_GRANTED;
  77. }
  78. /**
  79. * END: Common code for all Voter:vote() methods. Put custom logic below.
  80. */
  81. // If you created the ChronologyRequest detail, then you can UPDATE and DELETE it,
  82. // else, only MedBrief Admins and Super Admins can.
  83. // Consequently, only MedBrief Admins and Super Admins can UPDATE and DELETE a
  84. // detail generated by an incoming/outgoing email, as it has no creator attached.
  85. if (($attribute === self::UPDATE || $attribute === self::DELETE) && ($entity->getCreator() && $entity->getCreator()->getId() == $user->getId())) {
  86. return VoterInterface::ACCESS_GRANTED;
  87. }
  88. // If we get to the end of this function, then no decisions have been
  89. // made so we deny access
  90. return VoterInterface::ACCESS_DENIED;
  91. }
  92. }