<?php
/**
* Created by PhpStorm.
* User: matijajanc
* Date: 22/05/2018
* Time: 15:18
*/
namespace App\Adapter\Api\EventListener;
use App\Adapter\Api\Annotations\ApiAuthorization;
use App\Adapter\Api\Exception\ApiException;
use App\Adapter\Api\Service\Validators\ApiValidator;
use Doctrine\Common\Annotations\Reader;
use Doctrine\Common\Util\ClassUtils;
use Nelmio\ApiDocBundle\Controller\SwaggerUiController;
use ReflectionClass;
use ReflectionObject;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
class ApiAuthorizationListener
{
/**
* @var Reader
*/
private $reader;
/**
* @var ApiValidator
*/
private $validator;
/**
* ApiAuthorizationListener constructor.
* @param Reader $reader
* @param ApiValidator $validator
*/
public function __construct(Reader $reader, ApiValidator $validator)
{
$this->reader = $reader;
$this->validator = $validator;
}
/**
* @param FilterControllerEvent $event
* @throws ApiException
* @throws \ReflectionException
*/
public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
$request = $event->getRequest();
if (!$controller instanceof SwaggerUiController) {
/** @var Controller $controllerObject */
list($controllerObject, $methodName) = $controller;
if ($controllerObject instanceof Controller
&& $this->hasApiAuthorizationAnnotation($controllerObject, $methodName)
) {
if (!$this->validator->validateUserAgent($request)) {
throw new ApiException(['ERR-301', 'User agent is required'], Response::HTTP_UNAUTHORIZED);
}
}
}
}
/**
* @param Controller $controllerObject
* @param $methodName
* @return bool
* @throws \ReflectionException
*/
private function hasApiAuthorizationAnnotation(Controller $controllerObject, $methodName)
{
$tokenAnnotation = ApiAuthorization::class;
$hasAnnotation = false;
$classAnnotation = $this->reader->getClassAnnotation(
new ReflectionClass(ClassUtils::getClass($controllerObject)),
$tokenAnnotation
);
if ($classAnnotation) {
$hasAnnotation = true;
}
$controllerReflectionObject = new ReflectionObject($controllerObject);
$reflectionMethod = $controllerReflectionObject->getMethod($methodName);
$methodAnnotation = $this->reader->getMethodAnnotation($reflectionMethod, $tokenAnnotation);
if ($methodAnnotation) {
$hasAnnotation = true;
}
return $hasAnnotation;
}
}