<?php
namespace App\Listeners;
use App\Annotation\Authorization;
use App\Security\CallerAuthorizationService;
use Doctrine\Common\Annotations\Reader;
use Doctrine\Common\Util\ClassUtils;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as Controller;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
class ControllerListener
{
/**
* @var Reader
*/
protected $reader;
/**
* @var RequestStack
*/
protected $requestStack;
/**
* @var CallerAuthorizationService
*/
protected $callerAuthorizationService;
/**
* @param Reader $reader
* @param RequestStack $requestStack
* @param CallerAuthorizationService $callerAuthorizationService
*/
public function __construct(
Reader $reader,
RequestStack $requestStack,
CallerAuthorizationService $callerAuthorizationService
) {
$this->reader = $reader;
$this->requestStack = $requestStack;
$this->callerAuthorizationService = $callerAuthorizationService;
}
/**
* @param ControllerArgumentsEvent $event
*
* @throws \App\Exception\AccessDeniedException
* @throws \ReflectionException
*/
public function onKernelControllerArguments(ControllerArgumentsEvent $event)
{
$controller = $event->getController();
if (!is_array($controller)) {
return;
}
/** @var Controller $controllerObject */
list($controllerObject, $methodName) = $controller;
$request = $this->requestStack->getCurrentRequest();
if (null == $request) {
return;
}
$callerId = $request->headers->get('X-CALLER-ID');
$callers = $controllerObject;
$annotation = Authorization::class;
$classAnnotation = $this->reader->getClassAnnotation(
new \ReflectionClass(ClassUtils::getClass($controllerObject)),
$annotation
);
$controllerReflectionMethod = (new \ReflectionObject($controllerObject))->getMethod($methodName);
$methodAnnotation = $this->reader->getMethodAnnotation($controllerReflectionMethod, $annotation);
if ($classAnnotation || $methodAnnotation) {
$annotation = $classAnnotation ?? $methodAnnotation;
if (null == $annotation) {
return;
}
$callers = $annotation->apps;
$this->callerAuthorizationService->checkCallerAuthorization(
$callerId,
$callers,
$request->attributes->get('_route')
);
}
}
}