src/CoreBundle/Security/PublicationVoter.php line 13

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