src/Security/Voter/OwnerVoter.php line 21

Open in your IDE?
  1. <?php
  2. namespace App\Security\Voter;
  3. use App\Entity\Episode;
  4. use App\Entity\Program;
  5. use App\Entity\Radio;
  6. use App\Entity\User;
  7. use EasyCorp\Bundle\EasyAdminBundle\Dto\ActionDto;
  8. use EasyCorp\Bundle\EasyAdminBundle\Provider\AdminContextProvider;
  9. use EasyCorp\Bundle\EasyAdminBundle\Security\Permission;
  10. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  11. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  12. use Symfony\Component\Security\Core\Security;
  13. use Symfony\Component\Security\Core\User\UserInterface;
  14. /**
  15.  * This class vote on applications entities that may be owned by current user.
  16.  * Basically allows to view anything but edit only owned entities.
  17.  */
  18. class OwnerVoter extends Voter
  19. {
  20.     private $security;
  21.     private $adminContextProvider;
  22.     public function __construct(Security $securityAdminContextProvider $adminContextProvider)
  23.     {
  24.         $this->security $security;
  25.         $this->adminContextProvider $adminContextProvider;
  26.     }
  27.     protected function supports($attribute$subject)
  28.     {
  29.         // Currently disabled. Easyer to maintain with displayIf() in controllers.
  30.         // May need to come back to voter to enforce permission.
  31.         return false;
  32.         
  33.         // $crud = $this->adminContextProvider->getContext()?->getCrud();
  34.         $context $this->adminContextProvider->getContext();
  35.         $crud $context $context->getCrud() : null;
  36.         // dump([
  37.         //     "supports" => $attribute,
  38.         //     'subject' => $subject,
  39.         //     'crud' => $crud,
  40.         // ]);
  41.         // replace with your own logic
  42.         // https://symfony.com/doc/current/security/voters.html
  43.         $supports $attribute == Permission::EA_EXECUTE_ACTION &&
  44.             // in_array($subject?->getName(), ['new', 'edit', 'delete']) &&
  45.             $crud && in_array($crud->getEntityFqcn(), [
  46.                 Radio::class,
  47.                 Program::class,
  48.                 Episode::class,
  49.             ]);
  50.         // dump('supports: ' . ($supports ? 'true' : 'false'));
  51.         return $supports;
  52.     }
  53.     protected function voteOnAttribute($attribute$subjectTokenInterface $token)
  54.     {
  55.         $user $token->getUser();
  56.         // if the user is anonymous, do not grant access
  57.         if (!$user instanceof UserInterface) {
  58.             return false;
  59.         }
  60.         // ... (check conditions and return true to grant permission) ...
  61.         switch ($attribute) {
  62.             case Permission::EA_EXECUTE_ACTION:
  63.                 // dump([
  64.                 //     "voteOnAttribute" => $attribute,
  65.                 //     'subject' => $subject,
  66.                 //     'token' => $token,
  67.                 //     // 'crud' => $crud,
  68.                 // ]);
  69.                 if ($this->security->isGranted(User::ROLE_MANAGER)) {
  70.                     // dump("voted true for user with ROLE_MANAGER");
  71.                     // Managers and above
  72.                     return true;
  73.                 } else {
  74.                     if ($subject instanceof ActionDto) {
  75.                         $action $subject->getName();
  76.                         if ($subject->isGlobalAction()) {
  77.                             $context $this->adminContextProvider->getContext();
  78.                             $crud $context $context->getCrud() : null;
  79.                             $class $crud->getEntityFqcn();
  80.                             switch ($action) {
  81.                                 case 'new':
  82.                                     $vote in_array($class, [Program::class, Episode::class]);
  83.                                     break;
  84.                                 default:
  85.                                     $vote true;
  86.                             }
  87.                             // dump("shouldBeDisplayedFor voted " . ($vote ? "true" : 'false') . " for $action");
  88.                             return $vote;
  89.                         } elseif ($subject->isEntityAction()) {
  90.                             // Need to decide for each entity
  91.                             // Note: this only removes the action links, but does not prevent to access the page
  92.                             // if the user has a way to forge the url.
  93.                             // Find a way to enforce the permission on the (not displayed) url
  94.                             $subject->setDisplayCallable(
  95.                                 function ($entity) use ($user$action): bool {
  96.                                     // dump([
  97.                                     //     "shouldBeDisplayedFor" => $entity?->getName(),
  98.                                     //     'entity' => $entity,
  99.                                     //     'action name' => $action,
  100.                                     // ]);
  101.                                     $owner null;
  102.                                     if ($entity instanceof Radio) {
  103.                                         $owner $entity->getOwner();
  104.                                     } elseif ($entity instanceof Program) {
  105.                                         $owner $entity->getRadio()?->getOwner();
  106.                                     } elseif ($entity instanceof Episode) {
  107.                                         $owner $entity->getProgram()?->getRadio()->getOwner();
  108.                                     }
  109.                                     switch ($action) {
  110.                                         case 'edit':
  111.                                         case 'delete':
  112.                                             $vote $owner == $user;
  113.                                             break;
  114.                                         default:
  115.                                             $vote true;
  116.                                     }
  117.                                     // dump("shouldBeDisplayedFor voted " . ($vote ? "true" : 'false') . " for $action on " . $entity);
  118.                                     return $vote;
  119.                                     // throw new \LogicException('This code should not be reached!');
  120.                                 }
  121.                             );
  122.                             // dump("voted true for $attribute $action with displayCallable");
  123.                             return true;
  124.                         }
  125.                         // dump("voted true for $attribute $action with displayCallable");
  126.                         //dump("shouldBeDisplayedFor voted " . ($vote ? "true" : 'false') . " for $action");
  127.                         return false;
  128.                     }
  129.                 }
  130.         }
  131.         return false;
  132.     }
  133. }