vendor/crea/security-bundle/src/Voter/UserVoter.php line 15

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Crea\SecurityBundle\Voter;
  4. use Crea\SecurityBundle\Entity\User;
  5. use Crea\SecurityBundle\Entity\UserInterface;
  6. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  7. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  8. /**
  9. * @extends Voter<string, User>
  10. */
  11. class UserVoter extends Voter
  12. {
  13. public const USER_LIST = 'SECURITY_USER_LIST';
  14. public const USER_CREATE = 'SECURITY_USER_CREATE';
  15. public const USER_UPDATE_PASSWORD = 'SECURITY_USER_UPDATE_PASSWORD';
  16. public const USER_UPDATE = 'SECURITY_USER_UPDATE';
  17. public const USER_REMOVE = 'SECURITY_USER_REMOVE';
  18. public const USER_IMPERSONATE = 'SECURITY_USER_IMPERSONATE';
  19. public const USER_CONNECT = 'SECURITY_USER_CONNECT';
  20. public const USER_DETAIL = 'SECURITY_USER_DETAIL';
  21. public const USER_ACTIVE = 'SECURITY_USER_ACTIVE';
  22. protected function supports($attribute, $subject): bool
  23. {
  24. return in_array($attribute, [
  25. self::USER_LIST,
  26. self::USER_CREATE,
  27. self::USER_UPDATE_PASSWORD,
  28. self::USER_UPDATE,
  29. self::USER_REMOVE,
  30. self::USER_IMPERSONATE,
  31. self::USER_CONNECT,
  32. self::USER_DETAIL,
  33. self::USER_ACTIVE,
  34. ]) && (null === $subject || $subject instanceof User);
  35. }
  36. protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
  37. {
  38. /** @var User $loggedUser */
  39. $loggedUser = $token->getUser();
  40. if (!$loggedUser instanceof UserInterface) {
  41. return false;
  42. }
  43. switch ($attribute) {
  44. case self::USER_DETAIL:
  45. return $this->voteOnDetail($subject, $loggedUser);
  46. case self::USER_LIST:
  47. return $this->voteOnList($loggedUser);
  48. case self::USER_ACTIVE:
  49. return $this->voteOnActive($loggedUser);
  50. case self::USER_CREATE:
  51. return $this->voteOnCreate($loggedUser);
  52. case self::USER_UPDATE_PASSWORD:
  53. return $this->voteOnpassword($loggedUser);
  54. case self::USER_UPDATE:
  55. return $this->voteOnUpdate($subject, $loggedUser);
  56. case self::USER_REMOVE:
  57. return $this->voteOnRemove($subject, $loggedUser);
  58. case self::USER_IMPERSONATE:
  59. return $this->voteOnImpersonate($subject, $loggedUser);
  60. case self::USER_CONNECT:
  61. return $this->voteOnConnect($subject);
  62. }
  63. return false;
  64. }
  65. private function voteOnImpersonate(?User $subject, UserInterface $loggedUser): bool
  66. {
  67. if (null === $subject) {
  68. if (in_array(self::USER_IMPERSONATE, $loggedUser->getRoles())) {
  69. return true;
  70. }
  71. } else {
  72. /** @var User $user */
  73. $user = $subject;
  74. if (
  75. in_array(self::USER_IMPERSONATE, $loggedUser->getRoles())
  76. && $user->getLogin() !== $loggedUser->getUsername()
  77. && $this->voteOnConnect($user)
  78. ) {
  79. return true;
  80. }
  81. }
  82. return false;
  83. }
  84. public function voteOnConnect(?UserInterface $subject): bool
  85. {
  86. return null !== $subject && null !== $subject->getProfile() && $subject->isEnabled();
  87. }
  88. private function voteOnList(UserInterface $loggedUser): bool
  89. {
  90. if (in_array(self::USER_LIST, $loggedUser->getRoles())) {
  91. return true;
  92. }
  93. return false;
  94. }
  95. private function voteOnCreate(UserInterface $loggedUser): bool
  96. {
  97. if (in_array(self::USER_CREATE, $loggedUser->getRoles())) {
  98. return true;
  99. }
  100. return false;
  101. }
  102. private function voteOnPassword(UserInterface $loggedUser): bool
  103. {
  104. if (in_array(self::USER_UPDATE_PASSWORD, $loggedUser->getRoles())) {
  105. return true;
  106. }
  107. return false;
  108. }
  109. private function voteOnUpdate(?UserInterface $subject, UserInterface $loggedUser): bool
  110. {
  111. if (!in_array(self::USER_UPDATE, $loggedUser->getRoles())) {
  112. return false;
  113. }
  114. if (null === $subject) {
  115. return true;
  116. }
  117. if ($loggedUser !== $subject) {
  118. return true;
  119. }
  120. if (in_array('ROLE_ADMIN', $loggedUser->getRoles())) {
  121. return true;
  122. }
  123. return false;
  124. }
  125. private function voteOnRemove(?UserInterface $subject, UserInterface $loggedUser): bool
  126. {
  127. if (!in_array(self::USER_REMOVE, $loggedUser->getRoles())) {
  128. return false;
  129. }
  130. if (null === $subject) {
  131. return true;
  132. }
  133. if ($loggedUser !== $subject) {
  134. return true;
  135. }
  136. return false;
  137. }
  138. /**
  139. * By default, a user can see its own detail, the right let him see the other details.
  140. */
  141. private function voteOnDetail(UserInterface $subject, UserInterface $loggedUser): bool
  142. {
  143. if ($subject->getUsername() === $loggedUser->getUsername()) {
  144. return true;
  145. }
  146. if (in_array(self::USER_DETAIL, $loggedUser->getRoles())) {
  147. return true;
  148. }
  149. return false;
  150. }
  151. private function voteOnActive(UserInterface $loggedUser): bool
  152. {
  153. if (in_array(self::USER_ACTIVE, $loggedUser->getRoles())) {
  154. return true;
  155. }
  156. return false;
  157. }
  158. }