<?php
namespace App\Listener\Security;
use App\Entity\User;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Contracts\EventDispatcher\Event;
class IdlePolicyListener implements EventSubscriberInterface, WarmableInterface
{
/**
* @var TokenStorageInterface
*/
private $tokenStorage;
/**
* @var RequestStack
*/
private $requestStack;
/**
* @var RouterInterface
*/
private $router;
/**
* @var int
*/
private $idlePolicy;
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => [
['onRequest', 0],
],
];
}
public function __construct(TokenStorageInterface $tokenStorage, RequestStack $requestStack, RouterInterface $router, int $idlePolicy)
{
$this->tokenStorage = $tokenStorage;
$this->requestStack = $requestStack;
$this->router = $router;
$this->idlePolicy = $idlePolicy;
}
public function onRequest(RequestEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST != $event->getRequestType()) {
return;
}
if (!$this->tokenStorage->getToken() instanceof TokenInterface) {
return;
}
if (!$this->tokenStorage->getToken()->getUser() instanceof User) {
return;
}
if ($this->idlePolicy > 0) {
$session = $this->requestStack->getSession();
$session->start();
$lapse = time() - $session->getMetadataBag()->getLastUsed();
if ($lapse > $this->idlePolicy) {
$this->tokenStorage->setToken(null);
if ($session instanceof Session) {
$session->getFlashBag()->set('warning', 'You have been signed out due to inactivity.');
$event->setResponse(new RedirectResponse($this->router->generate('security.sign-out')));
$dispatcher = new Event();
$dispatcher->stopPropagation();
}
}
}
}
public function warmUp($cacheDir)
{
return [TokenStorageInterface::class, RequestStack::class, RouterInterface::class];
}
}