<?php
/**
* Copyright (C) SUEZ Smart Solutions - All Rights Reserved
* On’Connect Gateway Management, 2018
* Unauthorized copying of this file, via any medium is strictly prohibited
* Proprietary and confidential
* For the full copyright and license information, please report to the LICENSE CONTRACT.
*/
/**
* Created by PhpStorm.
* User: dhaoui.walid<dhaoui.walid@gmail.com>
* Date: 10/03/2015
* Time: 15:51.
*/
namespace TSMS\TsmsBundle\Security\Listener;
use Doctrine\ORM\EntityManager;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use TSMS\AdminBundle\Entity\MaintenanceMessage;
use TSMS\CoreBundle\Entity\User;
class SessionListener
{
/**
* @var SessionInterface
*/
protected $session;
/**
* @var RouterInterface
*/
protected $router;
/**
* @var int
*/
protected $maxIdleTime;
/**
* @var bool
*/
protected $modeMaintenance;
/**
* @var TokenStorageInterface
*/
protected $securityToken;
/**
* @var bool
*/
private $authorizedAccount;
/**
* @var bool
*/
private $entityManager;
/**
* @param SessionInterface $session
* @param RouterInterface $router
* @param int $maxIdleTime
* @param bool $modeMaintenance
*/
public function __construct(
SessionInterface $session,
RouterInterface $router,
TokenStorageInterface $securityToken,
$maxIdleTime = 0,
$modeMaintenance = false,
$authorizedAccount = [],
EntityManager $entityManager
) {
$this->session = $session;
$this->router = $router;
$this->securityToken = $securityToken;
$this->maxIdleTime = $maxIdleTime;
$this->modeMaintenance = $modeMaintenance;
$this->authorizedAccount = $authorizedAccount;
$this->entityManager = $entityManager;
}
public function onKernelRequest(GetResponseEvent $event)
{
$maintenanceMessageRepository = $this->entityManager->getRepository(MaintenanceMessage::class);
$maintenanceMessage = $maintenanceMessageRepository->findFirst();
/** si mode maintenance est activé rediriger l'utilisateur vers la page "site en maintenance" */
$isEnabledMaintenance = ($this->modeMaintenance || $maintenanceMessage instanceof MaintenanceMessage);
$token = $this->securityToken->getToken();
$user = null;
if ($token) {
$user = $token->getUser();
}
if($isEnabledMaintenance
&& ($user InstanceOf User && !in_array($user->getEmail(), $this->authorizedAccount)
&& !in_array($event->getRequest()->get('_route') ,['login','site_under_maintenance']))){
$event->setResponse(new RedirectResponse($this->router->generate('site_under_maintenance')));
return;
}
if(!$isEnabledMaintenance && $event->getRequest()->get('_route') == 'site_under_maintenance'){
$event->setResponse(new RedirectResponse($this->router->generate('login')));
return;
}
if ($this->maxIdleTime <= 0) {
return;
}
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
if ($this->checkIfShouldContinueSession($event)) {
return;
}
// Beyond this points, session is killed.
$this->session->invalidate();
$response = $this->getResponse($event);
$event->setResponse($response);
return;
}
/**
* Checks if session is fresh enough against max allowed idle time and sends signal to destroy it or not.
*
* @param GetResponseEvent $event
*
* @return bool should stop and destroy session
*/
protected function checkIfShouldContinueSession(GetResponseEvent $event)
{
$this->session->start();
if (false !== ($lastUsed = $this->defineLastUsed($event))) {
$this->session->set('last_used', $lastUsed);
}
$refreshLastUsed = $this->session->get('last_used');
if ((time() - $refreshLastUsed) <= $this->maxIdleTime) {
return true;
}
return;
}
/**
* Determines whether the session's last used should be refresh or not.
*
* @param GetResponseEvent $event
*
* @return int|bool whether to refresh or not
*/
protected function defineLastUsed(GetResponseEvent $event)
{
// If route is checking session, there fore it musn't be refresh prior to having its idle time looked at.
if ('check_session' !== $event->getRequest()->get('_route')) {
return time();
}
// If last used is absent from Session data, refresh it using metadata bag's lastUsed.
if (!$this->session->get('last_used')) {
return $this->session->getMetadataBag()->getLastUsed();
}
// If reaching this point, then nothing to do.
return false;
}
protected function getResponse(GetResponseEvent $event)
{
if ($event->getRequest()->isXmlHttpRequest()) {
$response = new Response('Session expired');
$response->setStatusCode(Response::HTTP_FORBIDDEN);
return $response;
}
$redirectParameters = [];
if (!in_array($event->getRequest()->get('_route'), array('login', 'logout', 'check_session', 'login_check'))) {
$redirectParameters['_target_path'] = $event->getRequest()->getRequestUri();
}
if ('check_session' === $event->getRequest()->getRequestUri()) {
$redirectParameters['_inactivity'] = true;
}
return new RedirectResponse($this->router->generate('logout', $redirectParameters));
}
}