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

Open in your IDE?
  1. <?php
  2. namespace EasyCorp\Bundle\EasyAdminBundle\Security;
  3. use EasyCorp\Bundle\EasyAdminBundle\Contracts\Provider\AdminContextProviderInterface;
  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 Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  10. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  11. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  12. /*
  13.  * @author Javier Eguiluz <[email protected]>
  14.  */
  15. final class SecurityVoter extends Voter
  16. {
  17.     public function __construct(
  18.         private readonly AuthorizationCheckerInterface $authorizationChecker,
  19.         private readonly AdminContextProviderInterface $adminContextProvider,
  20.     ) {
  21.     }
  22.     protected function supports(string $permissionNamemixed $subject): bool
  23.     {
  24.         return $this->supportsAttribute($permissionName);
  25.     }
  26.     public function supportsAttribute(string $permissionName): bool
  27.     {
  28.         return Permission::exists($permissionName);
  29.     }
  30.     protected function voteOnAttribute($permissionName$subjectTokenInterface $token): bool
  31.     {
  32.         if (Permission::EA_VIEW_MENU_ITEM === $permissionName) {
  33.             return $this->voteOnViewMenuItemPermission($subject);
  34.         }
  35.         if (Permission::EA_EXECUTE_ACTION === $permissionName) {
  36.             return $this->voteOnExecuteActionPermission($this->adminContextProvider->getContext()->getCrud(), $subject['action'] ?? null$subject['entity'] ?? null$subject['entityFqcn'] ?? null);
  37.         }
  38.         if (Permission::EA_VIEW_FIELD === $permissionName) {
  39.             return $this->voteOnViewPropertyPermission($subject);
  40.         }
  41.         if (Permission::EA_ACCESS_ENTITY === $permissionName) {
  42.             return $this->voteOnViewEntityPermission($subject);
  43.         }
  44.         if (Permission::EA_EXIT_IMPERSONATION === $permissionName) {
  45.             return $this->voteOnExitImpersonationPermission();
  46.         }
  47.         return true;
  48.     }
  49.     private function voteOnViewMenuItemPermission(MenuItemDto $menuItemDto): bool
  50.     {
  51.         // users can see the menu item if they have the permission required by the menu item
  52.         return $this->authorizationChecker->isGranted($menuItemDto->getPermission(), $menuItemDto);
  53.     }
  54.     private function voteOnExecuteActionPermission(CrudDto $crudDtoActionDto|string $actionNameOrDto, ?EntityDto $entityDto, ?string $entityFqcn): bool
  55.     {
  56.         // users can run the Crud action if:
  57.         // * they have the required permission to execute the action on the given entity instance
  58.         // * the action is not disabled
  59.         $actionName \is_string($actionNameOrDto) ? $actionNameOrDto $actionNameOrDto->getName();
  60.         $actionPermission $crudDto->getActionsConfig()->getActionPermissions()[$actionName] ?? null;
  61.         $disabledActionNames $crudDto->getActionsConfig()->getDisabledActions();
  62.         $subject $entityDto?->getInstance() ?? $entityFqcn;
  63.         return !\in_array($actionName$disabledActionNamestrue) && $this->authorizationChecker->isGranted($actionPermission$subject);
  64.     }
  65.     private function voteOnViewPropertyPermission(FieldDto $field): bool
  66.     {
  67.         // users can see the field if they have the permission required by the field
  68.         return $this->authorizationChecker->isGranted($field->getPermission(), $field);
  69.     }
  70.     private function voteOnViewEntityPermission(EntityDto $entityDto): bool
  71.     {
  72.         // users can see the entity if they have the required permission on the specific entity instance
  73.         return $this->authorizationChecker->isGranted($entityDto->getPermission(), $entityDto->getInstance());
  74.     }
  75.     private function voteOnExitImpersonationPermission(): bool
  76.     {
  77.         // users can exit impersonation if they are currently impersonating another user.
  78.         // In Symfony, that means that current user has the special impersonator permission
  79.         if (\defined('Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter::IS_IMPERSONATOR')) {
  80.             $impersonatorPermission 'IS_IMPERSONATOR';
  81.         } else {
  82.             $impersonatorPermission 'ROLE_PREVIOUS_ADMIN';
  83.         }
  84.         return $this->authorizationChecker->isGranted($impersonatorPermission);
  85.     }
  86. }