src/Permission/Listener/PermissionCheckListener.php line 37

Open in your IDE?
  1. <?php
  2. namespace App\Permission\Listener;
  3. use App\Permission\Annotation\PermissionCheck;
  4. use Doctrine\Common\Annotations\Reader;
  5. use ReflectionClass;
  6. use ReflectionException;
  7. use RuntimeException;
  8. use Symfony\Component\HttpKernel\Event\ControllerEvent;
  9. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  10. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  11. use Symfony\Contracts\Translation\TranslatorInterface;
  12. class PermissionCheckListener
  13. {
  14.     /**
  15.      * @param Reader $annotationReader
  16.      * @param AuthorizationCheckerInterface $authorizationChecker
  17.      * @param TranslatorInterface $translator
  18.      */
  19.     public function __construct(
  20.         protected Reader                        $annotationReader,
  21.         protected AuthorizationCheckerInterface $authorizationChecker,
  22.         protected TranslatorInterface           $translator,
  23.     )
  24.     {
  25.     }
  26.     /**
  27.      * @param ControllerEvent $event
  28.      * @return void
  29.      * @throws ReflectionException
  30.      */
  31.     public function onKernelController(ControllerEvent $event): void
  32.     {
  33.         if (!$event->getRequest()) {
  34.             return;
  35.         }
  36.         $controllers $event->getController();
  37.         if (!is_array($controllers)) {
  38.             return;
  39.         }
  40.         $this->handleAnnotation($controllers);
  41.     }
  42.     /**
  43.      * @param iterable $controllers
  44.      * @return void
  45.      * @throws ReflectionException
  46.      */
  47.     private function handleAnnotation(iterable $controllers): void
  48.     {
  49.         list($controller$method) = $controllers;
  50.         try {
  51.             $controller = new ReflectionClass($controller);
  52.         } catch (ReflectionException) {
  53.             throw new RuntimeException($this->translator->trans('api.failedToReadAnnotation'));
  54.         }
  55.         $this->handleClassAnnotation($controller);
  56.         $this->handleMethodAnnotation($controller$method);
  57.     }
  58.     /**
  59.      * @param ReflectionClass $controller
  60.      * @return void
  61.      */
  62.     private function handleClassAnnotation(ReflectionClass $controller): void
  63.     {
  64.         $annotation $this->annotationReader->getClassAnnotation($controllerPermissionCheck::class);
  65.         $this->extracted($annotation);
  66.     }
  67.     /**
  68.      * @param ReflectionClass $controller
  69.      * @param string $method
  70.      * @return void
  71.      * @throws ReflectionException
  72.      */
  73.     private function handleMethodAnnotation(ReflectionClass $controllerstring $method): void
  74.     {
  75.         $method $controller->getMethod($method);
  76.         $annotation $this->annotationReader->getMethodAnnotation($methodPermissionCheck::class);
  77.         $this->extracted($annotation);
  78.     }
  79.     /**
  80.      * @param PermissionCheck|null $annotation
  81.      * @return void
  82.      */
  83.     private function extracted(?PermissionCheck $annotation): void
  84.     {
  85.         if ($annotation instanceof PermissionCheck) {
  86.             $isGranted $this->authorizationChecker->isGranted($annotation->permission$annotation->role);
  87.             if (!$isGranted) {
  88.                 $message sprintf($this->translator->trans('api.rolePermissionNotFound'), $annotation->roleimplode(' ' $this->translator->trans('api.or') . ' '$annotation->permission));
  89.                 throw new AccessDeniedException($message);
  90.             }
  91.         }
  92.     }
  93. }