src/Security/Voter/FileVoter.php line 13

Open in your IDE?
  1. <?php
  2. namespace App\Security\Voter;
  3. use App\Entity\Client\Client;
  4. use App\Entity\File;
  5. use App\Entity\User;
  6. use Doctrine\ORM\EntityManagerInterface;
  7. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  8. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  9. use Symfony\Component\Security\Core\Security;
  10. class FileVoter extends Voter
  11. {
  12. // these strings are just invented: you can use anything
  13. const VIEW = 'view';
  14. const EDIT = 'edit';
  15. const DELETE = 'delete';
  16. /**
  17. * @var Security
  18. */
  19. private Security $security;
  20. /**
  21. * @var EntityManagerInterface
  22. */
  23. private EntityManagerInterface $entityManager;
  24. public function __construct(Security $security, EntityManagerInterface $entityManager)
  25. {
  26. $this->security = $security;
  27. $this->entityManager = $entityManager;
  28. }
  29. protected function supports(string $attribute, $subject): bool
  30. {
  31. // if the attribute isn't one we support, return false
  32. if (!in_array($attribute, [self::VIEW, self::EDIT, self::DELETE], true)) {
  33. return false;
  34. }
  35. // only vote on `File` objects
  36. if (!$subject instanceof File) {
  37. return false;
  38. }
  39. return true;
  40. }
  41. protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
  42. {
  43. $loggedUser = $token->getUser();
  44. if (!$loggedUser instanceof User) {
  45. // the user must be logged in; if not, deny access
  46. return false;
  47. }
  48. // you know $subject is a Post object, thanks to `supports()`
  49. /** @var File $targetFile */
  50. $targetFile = $subject;
  51. switch ($attribute) {
  52. case self::VIEW:
  53. return $this->canSee($targetFile, $loggedUser);
  54. case self::EDIT:
  55. return $this->canEdit($targetFile, $loggedUser);
  56. case self::DELETE:
  57. return $this->canDelete($targetFile, $loggedUser);
  58. }
  59. throw new \LogicException('This code should not be reached!');
  60. }
  61. /**
  62. * @param File $targetFile
  63. * @param User $loggedUser
  64. * @return bool
  65. */
  66. private function canSee(File $targetFile, User $loggedUser): bool
  67. {
  68. if ($targetFile->isCommon() && $this->security->isGranted('IS_AUTHENTICATED_FULLY')) {
  69. return true;
  70. }
  71. // file has no client
  72. if ($targetFile->getClient() === null) {
  73. return false;
  74. }
  75. /** @var Client $fileClient */
  76. $fileClient = $targetFile->getClient();
  77. // sanity check (different client than logged user client)
  78. if ($fileClient->getId() !== $loggedUser->getClient()->getId()) {
  79. return false;
  80. }
  81. /** user who created this file is granted */
  82. if ($targetFile->getCreatedBy() === $loggedUser) {
  83. return true;
  84. }
  85. // vote by sharing options - context client
  86. if ($targetFile->getContext() === File::CONTEXT_CLIENT) {
  87. return in_array($targetFile->getSharedWith(), File::getSharedWithOptionsByRole($loggedUser->getRole()->getName()), true);
  88. }
  89. // vote by buildings
  90. if ($this->security->isGranted('ROLE_CAN_SEE_ALL_BUILDINGS')) {
  91. return true;
  92. }
  93. if (!$targetFile->getBuildings()->isEmpty()) {
  94. foreach ($targetFile->getBuildings() as $building) {
  95. if ($loggedUser->getBuildings()->contains($building)) {
  96. return true;
  97. }
  98. }
  99. }
  100. if (!$targetFile->getGauges()->isEmpty()) {
  101. foreach ($targetFile->getGauges() as $gauge) {
  102. if ($loggedUser->getBuildings()->contains($gauge->getBuilding())) {
  103. return true;
  104. }
  105. }
  106. }
  107. return false;
  108. }
  109. /**
  110. * @param File $targetFile
  111. * @param User $loggedUser
  112. * @return bool
  113. */
  114. private function canEdit(File $targetFile, User $loggedUser):bool
  115. {
  116. if ($targetFile->isCommon()) {
  117. return $this->security->isGranted('ROLE_CAN_EDIT_COMMON_FILE') && $this->canSee($targetFile, $loggedUser);
  118. }
  119. return $this->security->isGranted('ROLE_CAN_EDIT_FILE') && $this->canSee($targetFile, $loggedUser);
  120. }
  121. /**
  122. * @param File $targetFile
  123. * @param User $loggedUser
  124. * @return bool
  125. */
  126. private function canDelete(File $targetFile, User $loggedUser):bool
  127. {
  128. if ($targetFile->isCommon()) {
  129. return $this->security->isGranted('ROLE_CAN_DELETE_COMMON_FILE') && $this->canSee($targetFile, $loggedUser);
  130. }
  131. return $this->security->isGranted('ROLE_CAN_DELETE_FILE') && $this->canSee($targetFile, $loggedUser);
  132. }
  133. }