src/Security/Voter/UserVoter.php line 10

Open in your IDE?
  1. <?php
  2. namespace App\Security\Voter;
  3. use App\Entity\User;
  4. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  5. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  6. use Symfony\Component\Security\Core\Security;
  7. class UserVoter extends Voter
  8. {
  9. // these strings are just invented: you can use anything
  10. const VIEW = 'view';
  11. const EDIT = 'edit';
  12. const DELETE = 'delete';
  13. /**
  14. * @var Security
  15. */
  16. private Security $security;
  17. public function __construct(Security $security)
  18. {
  19. $this->security = $security;
  20. }
  21. protected function supports(string $attribute, $subject): bool
  22. {
  23. // if the attribute isn't one we support, return false
  24. if (!in_array($attribute, [self::VIEW, self::EDIT, self::DELETE], true)) {
  25. return false;
  26. }
  27. // only vote on `Post` objects
  28. if (!$subject instanceof User) {
  29. return false;
  30. }
  31. return true;
  32. }
  33. protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
  34. {
  35. $loggedUser = $token->getUser();
  36. if (!$loggedUser instanceof User) {
  37. // the user must be logged in; if not, deny access
  38. return false;
  39. }
  40. // you know $subject is a Post object, thanks to `supports()`
  41. /** @var User $targetUser */
  42. $targetUser = $subject;
  43. switch ($attribute) {
  44. case self::VIEW:
  45. return $this->canSee($targetUser, $loggedUser);
  46. case self::EDIT:
  47. return $this->canEdit($targetUser, $loggedUser);
  48. case self::DELETE:
  49. return $this->canDelete($targetUser, $loggedUser);
  50. }
  51. throw new \LogicException('This code should not be reached!');
  52. }
  53. /**
  54. * @param User $targetUser
  55. * @param User $loggedUser
  56. * @return bool
  57. */
  58. private function canEdit(User $targetUser, User $loggedUser): bool
  59. {
  60. if ($this->security->isGranted('ROLE_ADMIN')) {
  61. return true;
  62. }
  63. if ($this->security->isGranted('ROLE_CAN_EDIT_USER') && $this->sameClient($targetUser) && $this->inUserHierarchy($targetUser, $loggedUser)) {
  64. return true;
  65. }
  66. return false;
  67. }
  68. /**
  69. * @param User $targetUser
  70. * @param User $loggedUser
  71. * @return bool
  72. */
  73. private function canDelete(User $targetUser, User $loggedUser): bool
  74. {
  75. if ($targetUser === $loggedUser) {
  76. return false;
  77. }
  78. if ($this->security->isGranted('ROLE_ADMIN')) {
  79. return true;
  80. }
  81. if ($this->security->isGranted('ROLE_CAN_DELETE_USER') && $this->sameClient($targetUser) && $this->inUserHierarchy($targetUser, $loggedUser)) {
  82. return true;
  83. }
  84. return false;
  85. }
  86. /**
  87. * @param User $targetUser
  88. * @param User $loggedUser
  89. * @return bool
  90. */
  91. private function canSee(User $targetUser, User $loggedUser): bool
  92. {
  93. if ($this->security->isGranted('ROLE_ADMIN')) {
  94. return true;
  95. }
  96. return $this->sameClient($targetUser) && $this->inUserHierarchy($targetUser, $loggedUser);
  97. }
  98. private function sameClient(User $targetUser): bool
  99. {
  100. /** @var User $loggedUser */
  101. $loggedUser = $this->security->getUser();
  102. return $loggedUser->getClient() === $targetUser->getClient();
  103. }
  104. private function sameBuildings(User $targetUser): bool
  105. {
  106. /** @var User $loggedUser */
  107. $loggedUser = $this->security->getUser();
  108. //pracovník manažer uvidí a může to co manažer ale jen u jemu přiřazených objektů
  109. if ($this->security->isGranted('ROLE_WORKER_MANAGER')) {
  110. foreach ($loggedUser->getBuildings() as $loggedUserBuilding) {
  111. foreach ($targetUser->getBuildings() as $targetUserBuilding) {
  112. if ($targetUserBuilding === $loggedUserBuilding) {
  113. return true;
  114. }
  115. }
  116. }
  117. return false;
  118. }
  119. return true;
  120. }
  121. private function inUserHierarchy(User $targetUser, User $loggedUser): bool
  122. {
  123. $hierarchy = [
  124. 'ROLE_ADMIN_MANAGER' => [
  125. 'ROLE_ADMIN_MANAGER',
  126. 'ROLE_MANAGER',
  127. 'ROLE_CLIENT_BOSS',
  128. 'ROLE_WORKER_MANAGER',
  129. 'ROLE_WORKER',
  130. 'ROLE_GUEST_EXPERT',
  131. 'ROLE_GUEST'
  132. ],
  133. 'ROLE_MANAGER' => [
  134. 'ROLE_MANAGER',
  135. 'ROLE_CLIENT_BOSS',
  136. 'ROLE_WORKER_MANAGER',
  137. 'ROLE_WORKER',
  138. 'ROLE_GUEST_EXPERT',
  139. 'ROLE_GUEST'
  140. ],
  141. 'ROLE_CLIENT_BOSS' => [
  142. 'ROLE_CLIENT_BOSS',
  143. 'ROLE_WORKER_MANAGER',
  144. 'ROLE_WORKER',
  145. 'ROLE_GUEST_EXPERT',
  146. 'ROLE_GUEST'
  147. ],
  148. 'ROLE_WORKER_MANAGER' => [
  149. 'ROLE_WORKER_MANAGER',
  150. 'ROLE_WORKER',
  151. 'ROLE_GUEST_EXPERT',
  152. 'ROLE_GUEST'
  153. ],
  154. 'ROLE_GUEST_EXPERT' => [
  155. 'ROLE_CLIENT_BOSS',
  156. 'ROLE_WORKER_MANAGER',
  157. 'ROLE_WORKER',
  158. 'ROLE_GUEST_EXPERT',
  159. 'ROLE_GUEST'
  160. ],
  161. ];
  162. $userRole = $loggedUser->getRole()->getName();
  163. if (isset($hierarchy[$userRole]) && in_array($targetUser->getRole()->getName(), $hierarchy[$userRole], true)) {
  164. return true;
  165. }
  166. return false;
  167. }
  168. }