<?php
namespace App\Security;
use App\Component\ActivityLogger\ActivityLoggerStrategy;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class AppAccessDeniedHandler implements AccessDeniedHandlerInterface
{
/**
* @var UrlGeneratorInterface
*/
private UrlGeneratorInterface $urlGenerator;
/**
* @var SessionInterface
*/
private SessionInterface $session;
/**
* @var TranslatorInterface
*/
private TranslatorInterface $translator;
/**
* @var ActivityLoggerStrategy
*/
private ActivityLoggerStrategy $logger;
/**
* AccessDeniedHandler constructor.
* @param UrlGeneratorInterface $urlGenerator
* @param SessionInterface $session
* @param TranslatorInterface $translator
* @param ActivityLoggerStrategy $logger
*/
public function __construct(
UrlGeneratorInterface $urlGenerator,
TranslatorInterface $translator,
ActivityLoggerStrategy $logger,
RequestStack $requestStack
) {
$this->urlGenerator = $urlGenerator;
$this->translator = $translator;
$this->logger = $logger;
$this->session = $requestStack->getCurrentRequest()->getSession();
}
/**
* @param Request $request
* @param AccessDeniedException $accessDeniedException
* @return Response
*/
public function handle(Request $request, AccessDeniedException $accessDeniedException): Response
{
// If incoming request expects JsonResponse, return it
$acceptHeader = $request->headers->get('Accept');
$message = ($accessDeniedException->getMessage() === 'Access Denied.') ? $this->translator->trans('errors.access_denied', [], 'security') : $accessDeniedException->getMessage();
$this->logger->log('access.denied', $request, $message);
if ($acceptHeader === 'json' || $acceptHeader === 'application/json') {
return new JsonResponse(
[
'status' => 'error',
'message' => $message,
],
Response::HTTP_FORBIDDEN
);
}
/** @var Session $session */
$session = $this->session;
// Add flash message about missing permissions
$session->getFlashBag()->add(
'access-error',
$message
);
// If the request comes from administration, redirect at dashboard
if (strpos('app_', $request->attributes->get('_route')) === 0) {
return new RedirectResponse($this->urlGenerator->generate('index'));
}
return new RedirectResponse($this->urlGenerator->generate('login'));
}
}