src/Security/Voter/GaugeReadingVoter.php line 13

Open in your IDE?
  1. <?php
  2. namespace App\Security\Voter;
  3. use App\Entity\Gauge\GaugeReading;
  4. use App\Entity\User;
  5. use App\Repository\Gauge\GaugeReadingRepository;
  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 GaugeReadingVoter extends Voter
  11. {
  12. // these strings are just invented: you can use anything
  13. const EDIT = 'edit';
  14. const DELETE = 'delete';
  15. /**
  16. * @var Security
  17. */
  18. private Security $security;
  19. /**
  20. * @var EntityManagerInterface
  21. */
  22. private EntityManagerInterface $entityManager;
  23. public function __construct(Security $security, EntityManagerInterface $entityManager)
  24. {
  25. $this->security = $security;
  26. $this->entityManager = $entityManager;
  27. }
  28. protected function supports(string $attribute, $subject): bool
  29. {
  30. // if the attribute isn't one we support, return false
  31. if (!in_array($attribute, [self::EDIT, self::DELETE], true)) {
  32. return false;
  33. }
  34. // only vote on `GaugeReading` objects
  35. if (!$subject instanceof GaugeReading) {
  36. return false;
  37. }
  38. return true;
  39. }
  40. protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
  41. {
  42. $loggedUser = $token->getUser();
  43. if (!$loggedUser instanceof User) {
  44. // the user must be logged in; if not, deny access
  45. return false;
  46. }
  47. // you know $subject is a Post object, thanks to `supports()`
  48. /** @var GaugeReading $targetGauge */
  49. $targetGaugeReading = $subject;
  50. switch ($attribute) {
  51. case self::EDIT:
  52. return $this->canEdit($targetGaugeReading, $loggedUser);
  53. case self::DELETE:
  54. return $this->canDelete($targetGaugeReading, $loggedUser);
  55. }
  56. throw new \LogicException('This code should not be reached!');
  57. }
  58. /**
  59. * @param GaugeReading $targetGaugeReading
  60. * @param User $loggedUser
  61. * @return bool
  62. */
  63. private function canEdit(GaugeReading $targetGaugeReading, User $loggedUser): bool
  64. {
  65. if (!$this->security->isGranted('view', $targetGaugeReading->getGauge())) {
  66. return false;
  67. }
  68. if ($this->security->isGranted('ROLE_CAN_EDIT_ALL_GAUGE_READINGS')) {
  69. return true;
  70. }
  71. if ($this->isLast($targetGaugeReading) && $this->security->isGranted('ROLE_CAN_EDIT_LAST_GAUGE_READINGS')) {
  72. return true;
  73. }
  74. return false;
  75. }
  76. /**
  77. * @param GaugeReading $targetGaugeReading
  78. * @param User $loggedUser
  79. * @return bool
  80. */
  81. private function canDelete(GaugeReading $targetGaugeReading, User $loggedUser): bool
  82. {
  83. if (!$this->security->isGranted('view', $targetGaugeReading->getGauge())) {
  84. return false;
  85. }
  86. if ($this->security->isGranted('ROLE_CAN_DELETE_ALL_GAUGE_READINGS')) {
  87. return true;
  88. }
  89. if ($this->isLast($targetGaugeReading) && $this->security->isGranted('ROLE_CAN_DELETE_LAST_GAUGE_READINGS')) {
  90. return true;
  91. }
  92. return false;
  93. }
  94. /**
  95. * @param GaugeReading $targetGaugeReading
  96. * @return bool
  97. */
  98. private function isLast(GaugeReading $targetGaugeReading): bool
  99. {
  100. /** @var GaugeReadingRepository $grRepository */
  101. $grRepository = $this->entityManager->getRepository(GaugeReading::class);
  102. $lastGr = $grRepository->getLastForGauge($targetGaugeReading->getGauge());
  103. if ($lastGr !== null && $lastGr->getId() === $targetGaugeReading->getId()) {
  104. return true;
  105. }
  106. return false;
  107. }
  108. }