src/Security/Authorization/Voter/AccessToPathVoter.php line 17

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace App\Security\Authorization\Voter;
  3. use App\Entity\ResourceController;
  4. use App\Modules\Users\DomainModel\Entity\User;
  5. use App\Repository\ResourceControllerRepository;
  6. use App\Service\CacheService;
  7. use Doctrine\ORM\EntityManagerInterface;
  8. use Exception;
  9. use Symfony\Component\HttpFoundation\Request;
  10. use Symfony\Component\HttpFoundation\RequestStack;
  11. use Symfony\Component\Routing\RouterInterface;
  12. use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
  13. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  14. class AccessToPathVoter implements VoterInterface
  15. {
  16.     protected ?Request $request null;
  17.     protected RequestStack $requestStack;
  18.     protected EntityManagerInterface $doctrine;
  19.     protected RouterInterface $router;
  20.     protected ResourceControllerRepository $resourceControllerRepository;
  21.     protected $_controller;
  22.     protected $resources;
  23.     protected ?array $cacheRouters null;
  24.     public function __construct(
  25.         RequestStack                 $requestStack,
  26.         EntityManagerInterface       $doctrine,
  27.         RouterInterface              $router,
  28.         ResourceControllerRepository $resourceControllerRepository
  29.     )
  30.     {
  31.         $this->requestStack $requestStack;
  32.         $this->doctrine $doctrine;
  33.         $this->router $router;
  34.         $this->resourceControllerRepository $resourceControllerRepository;
  35.         $this->resources $this->getResources();
  36.     }
  37.     private function getResources()
  38.     {
  39.         if ($this->resources)
  40.         {
  41.             return $this->resources;
  42.         }
  43.         return $this->getResourcesData();
  44.     }
  45.     private function getResourcesData(): ?array
  46.     {
  47.         /** @var ResourceController[] $resources */
  48.         $resources $this->resourceControllerRepository->findAllReturnArray();
  49.         $data null;
  50.         foreach ($resources as $resource)
  51.         {
  52.             foreach ($resource['roles'] as $role)
  53.             {
  54.                 $data[strtolower($resource['controller'])][strtolower($resource['action'])][strtolower($role['name'])] = $resource['id'];
  55.             }
  56.         }
  57.         return $data;
  58.     }
  59.     private function getRoute($controller)
  60.     {
  61.         if ($this->cacheRouters)
  62.         {
  63.             return $this->cacheRouters[$controller] ?? null;
  64.         }
  65.         $this->cacheRouters $this->getRouteData();
  66.         return $this->cacheRouters[$controller] ?? null;
  67.     }
  68.     private function getRouteData(): array
  69.     {
  70.         $data = [];
  71.         $routers $this->router->getRouteCollection()->all();
  72.         foreach ($routers as $name => $route)
  73.         {
  74.             $data[$name] = $route->getDefault('_controller');
  75.         }
  76.         return $data;
  77.     }
  78.     private function findResource($controller$action$roleName)
  79.     {
  80.         $controller strtolower($controller);
  81.         $action strtolower($action);
  82.         $roleName strtolower($roleName);
  83.         if (isset($this->resources[$controller]['*'][$roleName]))
  84.         {
  85.             return $this->resources[$controller]['*'][$roleName];
  86.         }
  87.         if (isset($this->resources[$controller][$action][$roleName]))
  88.         {
  89.             return $this->resources[$controller][$action][$roleName];
  90.         }
  91.         return null;
  92.     }
  93.     public function getRequest(): ?Request
  94.     {
  95.         if (null === $this->request)
  96.         {
  97.             $this->request $this->requestStack->getCurrentRequest();
  98.         }
  99.         return $this->request;
  100.     }
  101.     public function supportsAttribute($attribute): bool
  102.     {
  103.         return true;
  104.     }
  105.     public function supportsClass($class): bool
  106.     {
  107.         return $class instanceof User;
  108.     }
  109.     /**
  110.      * Get current controller name
  111.      */
  112.     public function getControllerName()
  113.     {
  114.         if (null !== $this -> getRequest())
  115.         {
  116.             $pattern '#(?:.+)\\\([a-zA-Z\\\]+)Controller#';
  117.             $matches = [];
  118.             preg_match($pattern$this->getController(), $matches);
  119.             if (false === isset($matches[1]))
  120.             {
  121.                 throw new Exception('Nie znaleziono nazwy kontrolera w ścieżce '.$this -> getController());
  122.             }
  123.             return strtolower($matches[1]);
  124.         }
  125.         return null;
  126.     }
  127.     /**
  128.      * Get current action name
  129.      */
  130.     public function getActionName(): ?string
  131.     {
  132.         if (null !== $this -> getRequest())
  133.         {
  134.             $pattern "#::([a-zA-Z]*?)(Action|$)#";
  135.             $matches = array();
  136.             preg_match($pattern$this -> getController(), $matches);
  137.             return strtolower($matches[1]);
  138.         }
  139.         return null;
  140.     }
  141.     public function setController($controller): self
  142.     {
  143.         $this -> _controller $this->getRoute($controller);
  144.         return $this;
  145.     }
  146.     public function getController()
  147.     {
  148.         return $this->_controller;
  149.     }
  150.     public function vote(TokenInterface $token$object, array $attributes)
  151.     {
  152.         $this->setController($attributes[0]);
  153.         if (!$this->getController())
  154.         {
  155.             return VoterInterface::ACCESS_ABSTAIN;
  156.         }
  157.         if (!$this->supportsClass($object))
  158.         {
  159.             return VoterInterface::ACCESS_ABSTAIN;
  160.         }
  161.         if (!$this->getControllerName())
  162.         {
  163.             return VoterInterface::ACCESS_ABSTAIN;
  164.         }
  165.         if (!$this->getActionName())
  166.         {
  167.             return VoterInterface::ACCESS_ABSTAIN;
  168.         }
  169.         /** @var ResourceController $resource */
  170.         $resource $this->findResource(
  171.             $this->getControllerName(),
  172.             $this->getActionName(),
  173.             $object->getRole()->getName()
  174.         );
  175.         if ($resource)
  176.         {
  177.             return VoterInterface::ACCESS_GRANTED;
  178.         }
  179.         return VoterInterface::ACCESS_DENIED;
  180.     }
  181. }