<?php
namespace App\Controller\Api\Subscribers;
use App\Controller\Api\Interfaces\IImportController;
use App\Services\ApiRequestQueueService;
use App\Tools\IndexHelper;
use Pimcore\Log\ApplicationLogger;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Finder\Exception\AccessDeniedException;
use Symfony\Component\HttpClient\Exception\JsonException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Exception\RuntimeException;
class PostRequestSubscriber implements EventSubscriberInterface
{
protected const COMPONENT = 'PostRequestSubscriber';
protected string $token;
public function __construct(protected string $apiToken, protected ApiRequestQueueService $apiRequestProcessorService, protected ApplicationLogger $applicationLogger)
{
$this->token = hash('haval224,3', $apiToken);
}
//https://symfony.com/doc/4.0/event_dispatcher/before_after_filters.html
/**
* @param ControllerEvent $event
*
* @throws JsonException
*/
public function onKernelController(ControllerEvent $event): void
{
$controller = $event->getController();
/**
* $controller passed can be either a class or a Closure.
* This is not usual in Symfony but it may happen.
* If it is a class, it comes in array format
*/
if (!is_array($controller)) {
return;
}
if ($controller[0] instanceof IImportController) {
$request = $event->getRequest();
$isPost = $request->isMethod('POST');
if (!$isPost) {
throw new MethodNotAllowedHttpException([Request::METHOD_GET]);
}
$token = hash('haval224,3', $request->headers->get('api-token'));
if(!$token || $token !== $this->token) {
$this->applicationLogger->error("Error trying to access api without or wrong token from " . $request->getClientIp(), [IndexHelper::INDEX_COMPONENT => self::COMPONENT]);
throw new AccessDeniedException('Security');
}
$systemName = $controller[0]->getSourceSystemName();
/**
* json_decode throws exeption automatically due to last param
*/
try {
json_decode($request->getContent(), true, 512, JSON_THROW_ON_ERROR);
} catch (\JsonException $jsonException) {
$this->applicationLogger->error("Invalid json from $systemName " . $request->getPathInfo() . "\n" . $request->getContent(). "\n" . $jsonException, [IndexHelper::INDEX_COMPONENT => self::COMPONENT]);
throw new RuntimeException('Invalid json', 400);
}
try {
$this->apiRequestProcessorService->process($request->getContent(), $systemName, $request->getMethod(), $request->getPathInfo());
} catch (\Exception $ex) {
$this->applicationLogger->info("Failed to insert $systemName data. Cause: $ex", [IndexHelper::INDEX_COMPONENT => self::COMPONENT]);
}
}
}
/**
* @return string[]
*/
public static function getSubscribedEvents(): array
{
return [
KernelEvents::CONTROLLER => 'onKernelController',
];
}
}