<?php
declare(strict_types=1);
namespace App\Subscriber;
use App\Logger\Log;
use App\Entity\User;
use App\Entity\BaseAuth;
use App\Form\CommonForm;
use App\Service\AuthService;
use App\Service\FileService;
use App\Service\IAppService;
use App\Service\IAuthService;
use App\Service\SchoolService;
use App\Service\IOptionService;
use App\Controller\AuthController;
use App\Controller\UserController;
use App\Controller\StaffController;
use App\Controller\WizardController;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Doctrine\ORM\Tools\Console\Command\SchemaTool\AbstractCommand;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class AppSubscriber implements EventSubscriberInterface
{
private ParameterBagInterface $parameterBag;
private SessionInterface $session;
private Security $security;
private SchoolService $schoolService;
protected TokenStorageInterface $securityToken;
protected Log $log;
protected FileService $fileService;
protected AuthService $authService;
public function __construct(
ParameterBagInterface $parameterBag,
SessionInterface $session,
Security $security,
TokenStorageInterface $securityToken,
Log $log,
FileService $fileService,
SchoolService $schoolService,
TranslatorInterface $translator,
AuthService $authService
) {
$this->session = $session;
$this->security = $security;
$this->schoolService = $schoolService;
$this->securityToken = $securityToken;
$this->fileService = $fileService;
$this->log = $log;
$this->parameterBag = $parameterBag;
$this->authService = $authService;
}
public function onInteractiveLogin(InteractiveLoginEvent $event)
{
$user = $event->getAuthenticationToken()->getUser();
/*if (null !== $user->getLocale()) {
$this->translator->setLocale($user->getLocale());
}*/
}
public function checkSubscription(ControllerEvent $event, AbstractController $controller){
// Permet de controler l'abonnement du site connecté
$user = $this->security->getUser();
if($controller instanceof UserController && !empty($user) && $user instanceof User) {
$school = $user->getSchool();
$site = null;
if(!empty($school)){
if (!empty($site = $this->session->get(IOptionService::CURRENT_SITE))) {
$site = $this->schoolService->findSite(['guid' => $site->getGuid()]);
} elseif (\count($school->getSites()) > 0) {
$site = $school->getSites()[0];
$this->session->set(IOptionService::CURRENT_SITE, $site);
}
}
if(!empty($site) && (empty($site->getExpirationDate()))) {
$event->setController(function () {
return new RedirectResponse($this->parameterBag->get('app.url').'error/expired');
});
} else if( !empty($site) && CommonForm::timeElapsed(new \DateTime('now'),$site->getExpirationDate()) <= 0){
$event->setController(function () {
return new RedirectResponse($this->parameterBag->get('app.url').'error/expired');
});
}
}
}
public function onKernelController(ControllerEvent $event)
{
$controller = $event->getController();
if (!is_array($controller)) {
return;
}
// Permet de controler l'abonnement du site connecté
if ($controller[0] instanceof StaffController || $controller[0] instanceof UserController || $controller[0] instanceof WizardController) {
$user = $this->security->getUser();
if ($this->fileService->checkFile($this->parameterBag->get('app.connection_dir').DIRECTORY_SEPARATOR.IOptionService::MAINTENANCE_FILE) && IAuthService::STAFF != $this->parameterBag->get('app.user')
&& !in_array(IAuthService::ROLE.'_'.IAuthService::ROLE_SUPER_ADMINISTRATOR,
$user->getRoles())) {
// logger - site is under maintenance
$this->log->writeLog(
[
IOptionService::KEY_CLASS => get_class($this),
IOptionService::KEY_FUNCTION => __FUNCTION__,
IOptionService::KEY_MESSAGE => 'site is under maintenance',
],
Log::MESSAGE_INFO
);
// clean session i think is not working
$session = $event->getRequest()->getSession();
$session->invalidate();
$session->clear();
// clean user activity
$this->securityToken->setToken(null);
// redirect to maintenance page
$this->redirectionMaintenance($event);
} elseif (null === $user) {
// logger - user is not log
$this->log->writeLog(
[
IOptionService::KEY_CLASS => get_class($this),
IOptionService::KEY_FUNCTION => __FUNCTION__,
IOptionService::KEY_MESSAGE => "User is not connected. He can't access to the application",
],
Log::MESSAGE_ERROR
);
$this->redirectLogout($event);
} elseif (
!$this->fileService->checkFile(
$this->parameterBag->get('app.connection_dir').DIRECTORY_SEPARATOR.
$user->getUsername().'-'.$this->session->getId()
)
) {
// logger - try to connect with no log
$this->log->writeLog(
[
IOptionService::KEY_CLASS => get_class($this),
IOptionService::KEY_FUNCTION => __FUNCTION__,
IOptionService::KEY_MESSAGE => 'User is already connected on another device',
],
Log::MESSAGE_ERROR
);
// $this->session->invalidate();
// $this->session->clear();
$this->redirectLogout($event);
} else if (!empty($user) && $user instanceof BaseAuth && !empty($user->getValidationCode()) && $event->getRequest()->attributes->get('_route') != "auth_activation") {
// logger - try to connect with no log
$this->log->writeLog(
[
IOptionService::KEY_CLASS => get_class($this),
IOptionService::KEY_FUNCTION => __FUNCTION__,
IOptionService::KEY_MESSAGE => "User has to connect with wright status. He can't access to the application"
],
Log::MESSAGE_ERROR
);
$this->redirectLogout($event);
} else {
if (null == $this->session->get(IAppService::SESSION_URL) && !empty($user)) {
$this->session->set(IAppService::SESSION_URL, [
'last_date' => new \DateTime(),
'page' => $event->getRequest()->getRequestUri(),
'route' => $event->getRequest()->get('_route'),
]);
} elseif (!empty($user)) {
$lastUrl = $this->session->get(IAppService::SESSION_URL);
if (
null != $lastUrl['last_date']
&& !CommonForm::checkActivity($lastUrl['last_date'], IAppService::MAX_IDLE_TIME)
) {
// logger - timeout
$this->log->writeLog(
[
IOptionService::KEY_CLASS => get_class($this),
IOptionService::KEY_FUNCTION => __FUNCTION__,
IOptionService::KEY_MESSAGE => 'Connection TIMEOUT',
],
Log::MESSAGE_ERROR
);
// $this->session->clear();
$this->session->remove(IAppService::SESSION_URL);
$this->redirectLogout($event);
} else {
// Permert de contrôler l'abonnement de l'utilisateur
$this->checkSubscription($event,$controller[0]);
$this->session->set(IAppService::SESSION_URL, [
'last_date' => new \DateTime(),
'page' => $event->getRequest()->getRequestUri(),
'route' => $event->getRequest()->get('_route'),
]);
$this->log->writeLog(
[
IOptionService::KEY_CLASS => get_class($this),
IOptionService::KEY_FUNCTION => __FUNCTION__,
IOptionService::KEY_ACCOUNT => $user->getUsername(),
],
Log::MESSAGE_INFO
);
}
}
}
}
}
public static function getSubscribedEvents()
{
return [
KernelEvents::CONTROLLER => 'onKernelController',
];
}
public function redirectLogout(ControllerEvent $event)
{
if ($event->getRequest()->isMethod('POST') && $event->getRequest()->isXmlHttpRequest()) {
if (!$event->getController() instanceof AuthController) {
$event->setController(function () {
return new JsonResponse([
'code' => 'signout',
'redirect' => $this->parameterBag->get('app.url').'signout',
], 400);
});
} else {
$event->setController(function () {
return new JsonResponse('signout', 200);
});
}
} else {
$event->setController(function () {
return new RedirectResponse($this->parameterBag->get('app.url').'signout');
});
}
}
public function redirectionMaintenance(ControllerEvent $event)
{
if ($event->getRequest()->isMethod('POST') && $event->getRequest()->isXmlHttpRequest()) {
if (!$event->getController() instanceof AuthController) {
$event->setController(function () {
return new JsonResponse([
'redirect' => $this->parameterBag->get('app.url').'maintenance',
], 200);
});
} else {
$event->setController(function () {
return new JsonResponse('maintenance', 200);
});
}
} else {
$event->setController(function () {
return new RedirectResponse($this->parameterBag->get('app.url').'maintenance');
});
}
}
}