FileVoter.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Security\Voter;
  4. use App\Entity\Access\Access;
  5. use App\Entity\Core\BankAccount;
  6. use App\Entity\Core\File;
  7. use AppBundle\Entity\Organization\Organization;
  8. use AppBundle\Entity\Person\Person;
  9. use AppBundle\Enum\Core\FileTypeEnum;
  10. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  11. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  12. use Symfony\Bundle\SecurityBundle\Security;
  13. use Symfony\Component\Security\Core\User\UserInterface;
  14. /**
  15. * Contrôle l'accès à l'entité File
  16. */
  17. class FileVoter extends AbstractVoter
  18. {
  19. protected const FILE_READ = 'FILE_READ';
  20. protected const FILE_EDIT = 'FILE_EDIT';
  21. protected const FILE_CREATE = 'FILE_CREATE';
  22. protected const FILE_DELETE = 'FILE_DELETE';
  23. public function __construct(
  24. private Security $security
  25. ) {}
  26. protected function supports(string $attribute, $subject): bool
  27. {
  28. return $subject instanceof File && in_array($attribute, [self::FILE_READ, self::FILE_EDIT, self::FILE_DELETE]);
  29. }
  30. /**
  31. * Retourne True si l'utilisateur a le droit d'effectuer l'opération demandée
  32. *
  33. * @param string $attribute
  34. * @param mixed $subject
  35. * @param TokenInterface $token
  36. * @return bool
  37. */
  38. protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
  39. {
  40. if(!$this->isAvailabilityDatePassed($subject)) {
  41. // Le fichier n'est pas encore disponible TODO: à revoir
  42. return false;
  43. }
  44. switch ($attribute) {
  45. case self::FILE_READ:
  46. return $this->canView($subject);
  47. case self::FILE_EDIT:
  48. return $this->canEdit($subject, $user);
  49. case self::FILE_CREATE:
  50. return $this->canCreate($subject, $user);
  51. case self::FILE_DELETE:
  52. return $this->canDelete($subject, $user);
  53. }
  54. return false;
  55. }
  56. /**
  57. * Returns True if the current user has the right to GET this record
  58. *
  59. * @param $subject \AppBundle\Entity\Core\File
  60. * @param $user
  61. * @return boolean
  62. */
  63. public function canView(File $subject): bool
  64. {
  65. // File has public visibility
  66. if ($subject->getVisibility() === FileVisibilityEnum::EVERYBODY) {
  67. return true;
  68. }
  69. // Is this an internal request? (@see https://gitlab.2iopenservice.com/opentalent/ap2i/-/blob/develop/doc/internal_requests.md)
  70. $clientIp = $_SERVER['REMOTE_ADDR'];
  71. $internalRequestToken = $_SERVER['HTTP_INTERNAL_REQUESTS_TOKEN'] ?? '';
  72. if ($this->internalRequestsService->isAllowed($clientIp, $internalRequestToken)) {
  73. return true;
  74. }
  75. // If the user has not logged in, the file is not available
  76. if (!$this->user) {
  77. return false;
  78. }
  79. // If the logged user is in accessUser of File
  80. if ($subject->getAccessPersons()->count() !== 0) {
  81. foreach ($subject->getAccessPersons() as $accessPerson) {
  82. if ($user->getId() == $accessPerson->getId()) {
  83. return true;
  84. }
  85. }
  86. }
  87. /**
  88. * If the logged user is in accessRole of File
  89. */
  90. if(0 !== count($subject->getAccessRoles())
  91. &&(
  92. ($subject->getOrganization() instanceof Organization && $subject->getOrganization()->getId() === $this->accessService->getAccess()->getOrganization()->getId())
  93. || ($subject->getPerson() instanceof Person && $subject->getPerson()->getId() === $this->accessService->getAccess()->getPerson()->getId())
  94. )
  95. ){
  96. foreach ($subject->getAccessRoles() as $accessRole){
  97. if($this->accessService->hasRole($accessRole)){
  98. return true;
  99. }
  100. }
  101. }
  102. return false;
  103. }
  104. /**
  105. * @param $subject \AppBundle\Entity\Core\File
  106. * @param $user
  107. * @return boolean
  108. */
  109. public function canEdit($subject, $user)
  110. {
  111. /**
  112. * If user is not logged, the file is not available
  113. */
  114. if (!$user instanceof Person) {
  115. return false;
  116. } /**
  117. * If user has ROLE_FILE
  118. */
  119. elseif ($this->accessService->hasRole('ROLE_FILE')
  120. && (
  121. ($subject->getOrganization() instanceof Organization && $subject->getOrganization()->getId() === $this->accessService->getAccess()->getOrganization()->getId())
  122. || ($subject->getPerson() instanceof Person && $subject->getPerson()->getId() === $this->accessService->getAccess()->getPerson()->getId())
  123. )
  124. ) {
  125. return true;
  126. } /**
  127. * If proprietary person of file is same of logged user
  128. */
  129. elseif ($subject->getPerson() instanceof Person && $subject->getPerson()->getId() === $user->getId()) {
  130. return true;
  131. }
  132. return false;
  133. }
  134. /**
  135. * @param $subject File
  136. * @param $user
  137. * @return boolean
  138. */
  139. public function canCreate($subject, $user)
  140. {
  141. /**
  142. * If user is not logged, the file is not available
  143. */
  144. if (!$user instanceof Person) {
  145. return false;
  146. }
  147. return true;
  148. }
  149. /**
  150. * @param $subject File
  151. * @param $user
  152. * @return boolean
  153. */
  154. public function canDelete($subject, $user){
  155. return $this->canEdit($subject, $user);
  156. }
  157. /**
  158. * @param $subject
  159. * @return bool
  160. * @throws \Exception
  161. */
  162. private function isAvailabilityDatePassed($subject){
  163. $isAvailabilityDatePassed = true;
  164. $today = new \DateTime();
  165. if (!empty($subject->getAvailabilityDate()) && $subject->getAvailabilityDate() > $today) {
  166. $userHasRole = false;
  167. // Si l'utilisateur a les droits suffisant pour voir le fichier meme si la date n'est pas passé: exemple: liste des factures
  168. if($subject->getType() === FileTypeEnum::BILL && $this->roleServiceUtils->checkIfUserHasRoles($this->accessService->getRoles(), ['ROLE_BILLACCOUNTING'])){
  169. $userHasRole = true;
  170. }
  171. if(!$userHasRole)
  172. $isAvailabilityDatePassed = false;
  173. }
  174. return $isAvailabilityDatePassed;
  175. }
  176. }