vendor/easycorp/easyadmin-bundle/src/Security/SecurityVoter.php line 21

Open in your IDE?
  1. <?php
  2. namespace EasyCorp\Bundle\EasyAdminBundle\Security;
  3. use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
  4. use EasyCorp\Bundle\EasyAdminBundle\Dto\ActionDto;
  5. use EasyCorp\Bundle\EasyAdminBundle\Dto\CrudDto;
  6. use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
  7. use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
  8. use EasyCorp\Bundle\EasyAdminBundle\Dto\MenuItemDto;
  9. use EasyCorp\Bundle\EasyAdminBundle\Provider\AdminContextProvider;
  10. use Symfony\Component\HttpKernel\Kernel;
  11. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  12. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  13. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  14. /*
  15.  * @author Javier Eguiluz <javier.eguiluz@gmail.com>
  16.  */
  17. if (Kernel::MAJOR_VERSION >= 6) {
  18.     final class SecurityVoter extends Voter
  19.     {
  20.         private $authorizationChecker;
  21.         private $adminContextProvider;
  22.         public function __construct(AuthorizationCheckerInterface $authorizationCheckerAdminContextProvider $adminContextProvider)
  23.         {
  24.             $this->authorizationChecker $authorizationChecker;
  25.             $this->adminContextProvider $adminContextProvider;
  26.         }
  27.         protected function supports(string $permissionNamemixed $subject): bool
  28.         {
  29.             return Permission::exists($permissionName);
  30.         }
  31.         protected function voteOnAttribute($permissionName$subjectTokenInterface $token): bool
  32.         {
  33.             if (Permission::EA_VIEW_MENU_ITEM === $permissionName) {
  34.                 return $this->voteOnViewMenuItemPermission($subject);
  35.             }
  36.             if (Permission::EA_EXECUTE_ACTION === $permissionName) {
  37.                 return $this->voteOnExecuteActionPermission($this->adminContextProvider->getContext()->getCrud(), $subject['action'] ?? null$subject['entity'] ?? null);
  38.             }
  39.             if (Permission::EA_VIEW_FIELD === $permissionName) {
  40.                 return $this->voteOnViewPropertyPermission($subject);
  41.             }
  42.             if (Permission::EA_ACCESS_ENTITY === $permissionName) {
  43.                 return $this->voteOnViewEntityPermission($subject);
  44.             }
  45.             if (Permission::EA_EXIT_IMPERSONATION === $permissionName) {
  46.                 return $this->voteOnExitImpersonationPermission();
  47.             }
  48.             return true;
  49.         }
  50.         private function voteOnViewMenuItemPermission(MenuItemDto $menuItemDto): bool
  51.         {
  52.             // users can see the menu item if they have the permission required by the menu item
  53.             return $this->authorizationChecker->isGranted($menuItemDto->getPermission(), $menuItemDto);
  54.         }
  55.         /**
  56.          * @param string|ActionDto $actionNameOrDto
  57.          */
  58.         private function voteOnExecuteActionPermission(CrudDto $crudDto$actionNameOrDto, ?EntityDto $entityDto): bool
  59.         {
  60.             // users can run the Crud action if:
  61.             // * they have the required permission to execute the action on the given entity instance
  62.             // * the action is not disabled
  63.             if (!\is_string($actionNameOrDto) && !($actionNameOrDto instanceof ActionDto)) {
  64.                 throw new \RuntimeException(sprintf('When checking the "%s" permission with the isGranted() method, the value of the "action" parameter passed inside the voter $subject must be a string with the action name or a "%s" object.'Permission::EA_EXECUTE_ACTIONActionDto::class));
  65.             }
  66.             $actionName \is_string($actionNameOrDto) ? $actionNameOrDto $actionNameOrDto->getName();
  67.             $actionPermission $crudDto->getActionsConfig()->getActionPermissions()[$actionName] ?? null;
  68.             $disabledActionNames $crudDto->getActionsConfig()->getDisabledActions();
  69.             $subject null === $entityDto null $entityDto->getInstance();
  70.             return $this->authorizationChecker->isGranted($actionPermission$subject) && !\in_array($actionName$disabledActionNamestrue);
  71.         }
  72.         private function voteOnViewPropertyPermission(FieldDto $field): bool
  73.         {
  74.             // users can see the field if they have the permission required by the field
  75.             return $this->authorizationChecker->isGranted($field->getPermission(), $field);
  76.         }
  77.         private function voteOnViewEntityPermission(EntityDto $entityDto): bool
  78.         {
  79.             // users can see the entity if they have the required permission on the specific entity instance
  80.             return $this->authorizationChecker->isGranted($entityDto->getPermission(), $entityDto->getInstance());
  81.         }
  82.         private function voteOnExitImpersonationPermission(): bool
  83.         {
  84.             // users can exit impersonation if they are currently impersonating another user.
  85.             // In Symfony, that means that current user has the special impersonator permission
  86.             if (\defined('Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter::IS_IMPERSONATOR')) {
  87.                 $impersonatorPermission 'IS_IMPERSONATOR';
  88.             } else {
  89.                 $impersonatorPermission 'ROLE_PREVIOUS_ADMIN';
  90.             }
  91.             return $this->authorizationChecker->isGranted($impersonatorPermission);
  92.         }
  93.     }
  94. } else {
  95.     final class SecurityVoter extends Voter
  96.     {
  97.         private $authorizationChecker;
  98.         private $adminContextProvider;
  99.         public function __construct(AuthorizationCheckerInterface $authorizationCheckerAdminContextProvider $adminContextProvider)
  100.         {
  101.             $this->authorizationChecker $authorizationChecker;
  102.             $this->adminContextProvider $adminContextProvider;
  103.         }
  104.         protected function supports($permissionName$subject): bool
  105.         {
  106.             return Permission::exists($permissionName);
  107.         }
  108.         protected function voteOnAttribute($permissionName$subjectTokenInterface $token): bool
  109.         {
  110.             if (Permission::EA_VIEW_MENU_ITEM === $permissionName) {
  111.                 return $this->voteOnViewMenuItemPermission($subject);
  112.             }
  113.             if (Permission::EA_EXECUTE_ACTION === $permissionName) {
  114.                 return $this->voteOnExecuteActionPermission($this->adminContextProvider->getContext()->getCrud(), $subject['action'] ?? null$subject['entity'] ?? null);
  115.             }
  116.             if (Permission::EA_VIEW_FIELD === $permissionName) {
  117.                 return $this->voteOnViewPropertyPermission($subject);
  118.             }
  119.             if (Permission::EA_ACCESS_ENTITY === $permissionName) {
  120.                 return $this->voteOnViewEntityPermission($subject);
  121.             }
  122.             if (Permission::EA_EXIT_IMPERSONATION === $permissionName) {
  123.                 return $this->voteOnExitImpersonationPermission();
  124.             }
  125.             return true;
  126.         }
  127.         private function voteOnViewMenuItemPermission(MenuItemDto $menuItemDto): bool
  128.         {
  129.             // users can see the menu item if they have the permission required by the menu item
  130.             return $this->authorizationChecker->isGranted($menuItemDto->getPermission(), $menuItemDto);
  131.         }
  132.         /**
  133.          * @param string|ActionDto $actionNameOrDto
  134.          */
  135.         private function voteOnExecuteActionPermission(CrudDto $crudDto$actionNameOrDto, ?EntityDto $entityDto): bool
  136.         {
  137.             // users can run the Crud action if:
  138.             // * they have the required permission to execute the action on the given entity instance
  139.             // * the action is not disabled
  140.             if (!\is_string($actionNameOrDto) && !($actionNameOrDto instanceof ActionDto)) {
  141.                 throw new \RuntimeException(sprintf('When checking the "%s" permission with the isGranted() method, the value of the "action" parameter passed inside the voter $subject must be a string with the action name or a "%s" object.'Permission::EA_EXECUTE_ACTIONActionDto::class));
  142.             }
  143.             $actionName \is_string($actionNameOrDto) ? $actionNameOrDto $actionNameOrDto->getName();
  144.             $actionPermission $crudDto->getActionsConfig()->getActionPermissions()[$actionName] ?? null;
  145.             $disabledActionNames $crudDto->getActionsConfig()->getDisabledActions();
  146.             $subject null === $entityDto null $entityDto->getInstance();
  147.             return $this->authorizationChecker->isGranted($actionPermission$subject) && !\in_array($actionName$disabledActionNamestrue);
  148.         }
  149.         private function voteOnViewPropertyPermission(FieldDto $field): bool
  150.         {
  151.             // users can see the field if they have the permission required by the field
  152.             return $this->authorizationChecker->isGranted($field->getPermission(), $field);
  153.         }
  154.         private function voteOnViewEntityPermission(EntityDto $entityDto): bool
  155.         {
  156.             // users can see the entity if they have the required permission on the specific entity instance
  157.             return $this->authorizationChecker->isGranted($entityDto->getPermission(), $entityDto->getInstance());
  158.         }
  159.         private function voteOnExitImpersonationPermission(): bool
  160.         {
  161.             // users can exit impersonation if they are currently impersonating another user.
  162.             // In Symfony, that means that current user has the special impersonator permission
  163.             if (\defined('Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter::IS_IMPERSONATOR')) {
  164.                 $impersonatorPermission 'IS_IMPERSONATOR';
  165.             } else {
  166.                 $impersonatorPermission 'ROLE_PREVIOUS_ADMIN';
  167.             }
  168.             return $this->authorizationChecker->isGranted($impersonatorPermission);
  169.         }
  170.     }
  171. }