<?php
/**
* Created by IntelliJ IDEA.
* User: dogukan
* Date: 2019-01-27
* Time: 18:21
*/
namespace App\Security;
use App\Entity\Role;
use App\Entity\Route;
use App\Service\SessionService;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
/**
* Class CrudVoter
* @package App\Security
*/
class CrudVoter extends Voter
{
const ATTR = 'CRUD_VOTER';
/**
* @var EntityManagerInterface
*/
private $entityManager;
/**
* @var Request|null
*/
private $request = null;
/**
* @var Security
*/
private $security;
/**
* @var CacheItemPoolInterface
*/
private $cacheItemPool;
/**
* @var SessionService
*/
private $sessionService;
/**
* CrudVoter constructor.
* @param EntityManagerInterface $entityManager
* @param RequestStack $requestStack
* @param Security $security
* @param CacheItemPoolInterface $cacheItemPool
* @param SessionService $sessionService
*/
public function __construct(
EntityManagerInterface $entityManager,
RequestStack $requestStack,
Security $security,
CacheItemPoolInterface $cacheItemPool,
SessionService $sessionService
) {
$this->entityManager = $entityManager;
$this->request = $requestStack->getMasterRequest();
$this->security = $security;
$this->cacheItemPool = $cacheItemPool;
$this->sessionService = $sessionService;
}
/**
* @return EntityManagerInterface
*/
public function getEntityManager(): EntityManagerInterface
{
return $this->entityManager;
}
/**
* @return Request|null
*/
public function getRequest(): ?Request
{
return $this->request;
}
/**
* @return Security
*/
public function getSecurity(): Security
{
return $this->security;
}
/**
* {@inheritdoc}
*/
protected function supports($attribute, $subject)
{
return $attribute === self::ATTR && $this->request !== null;
}
/**
* {@inheritdoc}
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
// todo: may be we can handle security exceptions to throw more meaningful exceptions
$endpoint = $this->request->attributes->get('_route');
$routeRoles = [];
$cacheItem = $this->cacheItemPool->getItem($endpoint);
if ($cacheItem->isHit()) {
$routeRoles = $cacheItem->get();
} else {
/** @var Route $route */
$route = $this->entityManager
->getRepository(Route::class)
->findOneBy(['endpoint' => $endpoint]);
if ($route !== null) {
$routeRoles = $route->getRoles()->map(function (Role $role) {
return $role->getIdentifier();
})->toArray();
}
}
return $this->sessionService->hasOneOfRoles($routeRoles);
}
}