<?php
namespace App\EventSubscriber;
use App\Controller\Api\ApiMessages;
use App\Controller\Api\AssessmentController;
use App\Controller\UserAuthenticatedController;
use App\Enum\CsrfToken as TokenNames;
use App\Model\Common\ResponseModel;
use App\Response\ApiResponse;
use App\Service\Config\ConfigLoader;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
class UserAuthenticatedSubscriber implements EventSubscriberInterface
{
private $security;
private $csrfTokenManager;
private $configLoader;
public function __construct(Security $security, CsrfTokenManagerInterface $csrfTokenManager, ConfigLoader $configLoader)
{
$this->security = $security;
$this->csrfTokenManager = $csrfTokenManager;
$this->configLoader = $configLoader;
}
public function onKernelController(ControllerEvent $event)
{
$controllers = $event->getController();
if (!is_array($controllers) || !$controllers[0] instanceof UserAuthenticatedController) {
return;
}
if (isset($_ENV['MAINTENANCE_MODE']) && $_ENV['MAINTENANCE_MODE']) {
$event->setController(
function () {
$response = new ResponseModel();
$response->success = false;
$response->message = ApiMessages::UNAUTHENTICATED;
return new JsonResponse($response, Response::HTTP_UNAUTHORIZED);
}
);
}
if (!$this->checkAuthenticated()) {
$response = new ResponseModel();
$response->success = false;
$response->message = ApiMessages::UNAUTHENTICATED;
$event->setController(
function () use ($response) {
return new JsonResponse($response, Response::HTTP_UNAUTHORIZED);
}
);
}
if (!$this->checkCsrfToken($event)) {
$event->setController(
function () {
return ApiResponse::error(ApiMessages::INVALID_CSRF_TOKEN, 0, Response::HTTP_FORBIDDEN);
}
);
}
if ($controllers[0] instanceof AssessmentController) {
if (!$this->configLoader->getValue("core_feature_assessment")) {
$event->setController(
function () {
return ApiResponse::error(ApiMessages::ACTION_NOT_ALLOWED, 0, Response::HTTP_FORBIDDEN);
}
);
}
}
}
private function checkAuthenticated(): bool
{
return $this->security->isGranted('IS_AUTHENTICATED_FULLY');
}
private function checkCsrfToken($event): bool
{
$method = $event->getRequest()->getMethod();
$stateChangingMethods = ['post', 'put', 'patch', 'delete'];
if (!in_array(strtolower($method), $stateChangingMethods)) {
return true;
}
$tokenValue = $event->getRequest()->headers->get("x-csrf-token");
$csrfToken = new CsrfToken(TokenNames::API_TOKEN, $tokenValue);
return $this->csrfTokenManager->isTokenValid($csrfToken);
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::CONTROLLER => 'onKernelController',
];
}
}