src/Security/Voter/AccountVoter.php line 16

Open in your IDE?
  1. <?php
  2. namespace MedBrief\MSR\Security\Voter;
  3. use Doctrine\ORM\EntityManagerInterface;
  4. use MedBrief\MSR\Entity\Account;
  5. use MedBrief\MSR\Entity\Firm;
  6. use MedBrief\MSR\Entity\User;
  7. use MedBrief\MSR\Repository\UserInternalRepository;
  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\Voter;
  12. use Symfony\Component\Security\Core\User\UserInterface;
  13. class AccountVoter extends Voter
  14. {
  15. public const CREATE = 'CREATE';
  16. public const READ = 'READ';
  17. public const UPDATE = 'UPDATE';
  18. public const DELETE = 'DELETE';
  19. public const ADMINISTRATION = 'ADMINISTRATION';
  20. public const USER_ADMINISTRATION = 'USER_ADMINISTRATION';
  21. public const SORTING_SETTINGS_ADMINISTRATION = 'SORTING_SETTINGS_ADMINISTRATION';
  22. public const MATTER_REQUEST_DEFAULTS_ADMINISTRATION = 'MATTER_REQUEST_DEFAULTS_ADMINISTRATION';
  23. public const INDEX_HEADER_ADMINISTRATION = 'INDEX_HEADER_ADMINISTRATION';
  24. public const TECHNICAL_ADMINISTRATION = 'TECHNICAL_ADMINISTRATION';
  25. public const UPDATE_PHYSICAL_ADDRESS = 'UPDATE_PHYSICAL_ADDRESS';
  26. public const ADD_OFFICE = 'ADD_OFFICE';
  27. public const ADD_MATTER_REQUEST = 'ADD_MATTER_REQUEST';
  28. public const ADD_LICENCE_RENEWAL_TERM = 'ADD_LICENCE_RENEWAL_TERM';
  29. public const ACCESS_GRANTED = true;
  30. public const ACCESS_DENIED = false;
  31. public function __construct(
  32. private readonly AuthorizationCheckerInterface $authorizationChecker,
  33. private readonly UserInternalRepository $userInternalRepository,
  34. private readonly EntityManagerInterface $entityManager
  35. ) {
  36. }
  37. #[Override]
  38. protected function supports($attribute, $subject)
  39. {
  40. return in_array($attribute, [
  41. self::CREATE,
  42. self::READ,
  43. self::UPDATE,
  44. self::DELETE,
  45. self::ADMINISTRATION,
  46. self::USER_ADMINISTRATION,
  47. self::SORTING_SETTINGS_ADMINISTRATION,
  48. self::MATTER_REQUEST_DEFAULTS_ADMINISTRATION,
  49. self::INDEX_HEADER_ADMINISTRATION,
  50. self::UPDATE_PHYSICAL_ADDRESS,
  51. self::ADD_OFFICE,
  52. self::TECHNICAL_ADMINISTRATION,
  53. self::ADD_MATTER_REQUEST,
  54. self::ADD_LICENCE_RENEWAL_TERM,
  55. ])
  56. && ($subject instanceof Account || is_subclass_of($subject, Account::class));
  57. }
  58. #[Override]
  59. protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
  60. {
  61. /** @var User $user */
  62. $user = $token->getUser();
  63. // if the user is anonymous, do not grant access
  64. if (!$user instanceof UserInterface) {
  65. return self::ACCESS_DENIED;
  66. }
  67. if ($user instanceof Firm && $user->getClientAreas()->contains($subject)) {
  68. return self::ACCESS_GRANTED;
  69. }
  70. // Super Admin and Admin users can add/edit terms
  71. if ($attribute === self::ADD_LICENCE_RENEWAL_TERM) {
  72. return $this->canCreate();
  73. }
  74. // Super Admin users can do everything
  75. if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) {
  76. return self::ACCESS_GRANTED;
  77. }
  78. // Only Super Admins may create, delete Accounts or have full administration rights
  79. if ($attribute === self::MATTER_REQUEST_DEFAULTS_ADMINISTRATION) {
  80. return self::ACCESS_DENIED;
  81. }
  82. // Attributes that only internal users (MedBrief staff) can perform
  83. $internalOnlyAttributes = [
  84. self::CREATE,
  85. self::DELETE,
  86. self::ADMINISTRATION,
  87. self::SORTING_SETTINGS_ADMINISTRATION,
  88. self::UPDATE,
  89. ];
  90. // Attributes that both internal users and client administrators can perform
  91. $internalAndClientAdminAttributes = [
  92. self::UPDATE_PHYSICAL_ADDRESS,
  93. self::ADD_OFFICE,
  94. ];
  95. // Internal users (MedBrief staff) can update any account
  96. if ($user instanceof User
  97. && $user->isUserInternal($this->userInternalRepository, $this->entityManager)
  98. && (in_array($attribute, array_merge($internalOnlyAttributes, $internalAndClientAdminAttributes)))) {
  99. return self::ACCESS_GRANTED;
  100. }
  101. // For client users, deny by default and only allow if user has specific account permissions
  102. // This will be evaluated by the role checks below (ADMINISTRATOR or SUPERADMINISTRATOR for this account)
  103. // If this user is a Client Super Administrator for the Account then they can
  104. // do everything else
  105. if ($this->authorizationChecker->isGranted('ROLE_ACCOUNT_' . $subject->getId() . '_SUPERADMINISTRATOR')
  106. && !in_array($attribute, $internalOnlyAttributes)
  107. ) {
  108. return self::ACCESS_GRANTED;
  109. }
  110. // Otherwise if this user is a Client Administrator for the Account then they can
  111. // do everything else except for User Administration and Technical Admin
  112. if ($this->authorizationChecker->isGranted('ROLE_ACCOUNT_' . $subject->getId() . '_ADMINISTRATOR')
  113. && !in_array($attribute, array_merge([
  114. self::USER_ADMINISTRATION,
  115. self::TECHNICAL_ADMINISTRATION,
  116. ], $internalOnlyAttributes))
  117. ) {
  118. return self::ACCESS_GRANTED;
  119. }
  120. // A Client technical administrator may perform technical administration as well as other duties
  121. if ($this->authorizationChecker->isGranted('ROLE_ACCOUNT_' . $subject->getId() . '_TECHNICAL_ADMIN')
  122. && in_array($attribute, array_merge([
  123. self::READ,
  124. self::TECHNICAL_ADMINISTRATION,
  125. self::ADD_MATTER_REQUEST,
  126. ], $internalAndClientAdminAttributes))) {
  127. return self::ACCESS_GRANTED;
  128. }
  129. return self::ACCESS_DENIED;
  130. }
  131. private function canCreate(): bool
  132. {
  133. return $this->authorizationChecker->isGranted('ROLE_ADMIN');
  134. }
  135. }