<?php
namespace App\EventListener;
use App\Controller\Admin\PermissionCheckerControllerInterface;
use App\Entity\Menu;
use App\Entity\Permission;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Sogec\BOBundle\Controller\CRUDController;
use Sogec\BOBundle\Routing\CRUDAction;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
/**
* Class AdminPermissionSubscriber.
*/
class AdminPermissionSubscriber implements EventSubscriberInterface
{
/**
* @var EntityManagerInterface
*/
private $manager;
/**
* @var TokenStorageInterface
*/
private $token;
/**
* @var AuthorizationCheckerInterface
*/
private $authChecker;
/**
* @var array
*/
private $whitListRoutes;
/**
* AdminPermissionSubscriber constructor.
*
* @param EntityManagerInterface $manager
* @param TokenStorageInterface $token
* @param AuthorizationCheckerInterface $authChecker
* @param array $whitListRoutes
*/
public function __construct(EntityManagerInterface $manager, TokenStorageInterface $token, AuthorizationCheckerInterface $authChecker, array $whitListRoutes)
{
$this->manager = $manager;
$this->token = $token;
$this->authChecker = $authChecker;
$this->whitListRoutes = $whitListRoutes;
}
/**
* Filter Controller.
*
* @param FilterControllerEvent $event
*/
public function onKernelController(FilterControllerEvent $event)
{
if (!$event->isMasterRequest()) {
return;
}
if (!strpos($event->getRequest()->get('_firewall_context'), 'admin')) {
return;
}
if ($this->authChecker->isGranted('ROLE_SUPER_ADMIN')) {
return;
}
$controller = $event->getController();
if (!is_array($controller)) {
return;
}
if (in_array($event->getRequest()->get('_route'), $this->whitListRoutes)) {
return;
}
/**
* @var Controller $currentController
*/
$currentController = $controller[0];
if ($currentController instanceof PermissionCheckerControllerInterface || $currentController instanceof CRUDController) {
/**
* @var User $user
*/
$user = $this->token->getToken()->getUser();
if (!$profile = $user->getProfile()) {
throw new AccessDeniedHttpException('This action needs a permission!');
}
$routeTab = explode('_', $event->getRequest()->get('_route'));
$filterMenu = $event->getRequest()->get('_route');
$action = CRUDAction::LIST;
if (3 == count($routeTab)) {
list($prefix, $section, $action) = $routeTab;
$filterMenu = $prefix.'_'.$section;
} elseif (4 === count($routeTab)) {
list($prefix, $section, $subsection, $action) = $routeTab;
$filterMenu = $prefix.'_'.$section.'_'.$subsection;
} elseif ('admin_permissions_ajax_change_access' === $filterMenu) {
list($prefix) = $routeTab;
$action = 'edit';
$filterMenu = $prefix.'_permissions';
}
$menu = $this->manager->getRepository(Menu::class)
->findByRoutePrefix($filterMenu);
$permission = $this->manager->getRepository(Permission::class)
->findOneBy(['menu' => $menu, 'profile' => $profile]);
if (null === $permission || !$permission->getActions()[$action]) {
throw new AccessDeniedHttpException('This action needs a permission!');
}
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return array(
KernelEvents::CONTROLLER => 'onKernelController',
);
}
}