src/Security/Core/PublicationVoter.php line 14

Open in your IDE?
  1. <?php
  2. namespace App\Security\Core;
  3. use App\Entity\Core\Publication;
  4. use App\Entity\Core\PublisherPermission;
  5. use App\Entity\Core\PublisherPermissionRepository;
  6. use Doctrine\ORM\EntityManagerInterface;
  7. use LogicException;
  8. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  9. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  10. use Symfony\Component\Security\Core\Security;
  11. class PublicationVoter extends Voter
  12. {
  13. const PERMISSION = 'publicationEntityPermission';
  14. const INDEX_ACTION = 'publicationIndexAction';
  15. const NEW_ACTION = 'publicationNewAction';
  16. const EDIT_ACTION = 'publicationEditAction';
  17. const DELETE_ACTION = 'publicationDeleteAction';
  18. private EntityManagerInterface $em;
  19. private Security $security;
  20. public function __construct(EntityManagerInterface $em, Security $security)
  21. {
  22. $this->em = $em;
  23. $this->security = $security;
  24. }
  25. protected function supports(string $attribute, $subject): bool
  26. {
  27. // For index and new, $subject will always be null. For permission, it will be null when trying to create a new entity.
  28. if (in_array($attribute, [self::INDEX_ACTION, self::NEW_ACTION, self::PERMISSION])) {
  29. return true;
  30. }
  31. if (in_array($attribute, [self::EDIT_ACTION, self::DELETE_ACTION])) {
  32. return $subject instanceof Publication;
  33. }
  34. return false;
  35. }
  36. protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
  37. {
  38. if ($attribute === self::INDEX_ACTION) {
  39. // Allow everyone to list - the entity permissions will still apply and hide entities you are not allowed
  40. // to access.
  41. return true;
  42. }
  43. if ($attribute === self::NEW_ACTION || $attribute === self::PERMISSION && $subject === null) {
  44. // Includes ROLE_SUPER_ADMIN by inheritance.
  45. // Authors should not be allowed to create new publications.
  46. return $this->security->isGranted('ROLE_ADMIN') ||
  47. $this->security->isGranted('ROLE_EDITOR');
  48. }
  49. if (!$subject instanceof Publication) {
  50. throw new LogicException("Invalid type for voter and attribute.");
  51. }
  52. return $this->checkEntityPermissions($attribute, $subject, $token);
  53. }
  54. public function checkEntityPermissions(string $attribute, Publication $subject, TokenInterface $token): bool
  55. {
  56. if ($subject->isDeleted() || $subject->isHidden() || $subject->getPublisher()->isDeleted()
  57. || $subject->getPublisher()->isHidden() || !$subject->isAvailableForBackendUserCreation()) {
  58. return false;
  59. }
  60. // ROLE_SUPER_ADMIN inherits ROLE_ADMIN, and will also be included here.
  61. if ($this->security->isGranted('ROLE_ADMIN')) {
  62. return true;
  63. }
  64. /** @var PublisherPermissionRepository $permissionRepo */
  65. $permissionRepo = $this->em->getRepository(PublisherPermission::class);
  66. if ($this->security->isGranted('ROLE_EDITOR')) {
  67. return $permissionRepo->hasEditorPermission($token->getUser(), $subject->getPublisher()) ||
  68. $permissionRepo->hasAuthorPermission($token->getUser(), $subject);
  69. }
  70. if ($this->security->isGranted('ROLE_AUTHOR')) {
  71. if ($attribute !== self::PERMISSION) {
  72. // Don't allow authors to edit or delete publications.
  73. return false;
  74. }
  75. return $permissionRepo->hasAuthorPermission($token->getUser(), $subject);
  76. }
  77. // Should not get here due to EasyAdmin firewall on any other roles.
  78. return false;
  79. }
  80. }