<?php
namespace Seidemann\Hanagud\EventSubscriber;
use Seidemann\Hanagud\Http\ApiResponse;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\DataCollector\ExceptionDataCollector;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Profiler\Profiler;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
class ApiAccessDeniedSubscriber implements EventSubscriberInterface
{
public function __construct(private ?Profiler $profiler = null)
{
}
/**
* Creates the ApiResponse from a given AccessDeniedException.
*/
private function createApiResponse(AccessDeniedException $exception): ApiResponse
{
return new ApiResponse(null, $exception, 403);
}
public function onKernelException(ExceptionEvent $event): void
{
$exception = $event->getThrowable();
if (!$exception instanceof AccessDeniedException) {
return;
}
$request = $event->getRequest();
if (in_array('application/json', $request->getAcceptableContentTypes())) {
$response = $this->createApiResponse($exception);
$event->setResponse($response);
// If profiler is enabled, log exception into it
if (null !== $this->profiler) {
/** @var ExceptionDataCollector $exceptionCollector */
$exceptionCollector = $this->profiler->get('exception');
$exceptionCollector->collect($request, $response, $exception);
}
}
}
public static function getSubscribedEvents()
{
return [
KernelEvents::EXCEPTION => [
// we need a higher priority than Security HTTP ExceptionListener,
// however we use a different priority for the rest of the responses,
// hence this is in its own class
['onKernelException', 2],
],
];
}
}