<?php
namespace App\EventListener;
use App\Entity\Location;
use App\Entity\User;
use App\Service\UserActivityService;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Security;
class RequestAuthenticationSubscriber implements EventSubscriberInterface
{
/** @var EntityManagerInterface */
private EntityManagerInterface $entityManager;
/** @var SessionInterface */
private SessionInterface $session;
/** @var TokenStorageInterface */
private TokenStorageInterface $tokenStorage;
/** @var UserActivityService */
private UserActivityService $userActivityService;
private LoggerInterface $logger;
private Security $security;
public function __construct(
EntityManagerInterface $entityManager,
TokenStorageInterface $tokenStorage,
LoggerInterface $logger,
UserActivityService $userActivityService,
Security $security
)
{
$this->entityManager = $entityManager;
$this->tokenStorage = $tokenStorage;
$this->logger = $logger;
$this->userActivityService = $userActivityService;
$this->security = $security;
}
public function onKernelRequest(RequestEvent $event): void
{
$logout = false;
$user = $this->security->getUser();
// get url
$request = $event->getRequest();
$this->session = $request->getSession();
$url = $request->getRequestUri();
if(!$this->tokenStorage->getToken()){
$url = str_replace('/login','', $url);
}
if (strpos($url, '/login') !== false &&
$this->tokenStorage->getToken() &&
$this->tokenStorage->getToken()->getUser() instanceof User) {
$url = str_replace('/login','', $url);
}
// check if client
if(
strpos($url, '/client/') !== false
&& strpos($url, '/api/') === false
&& strpos($url, '/relational/') === false
&& strpos($url, '/client/toolbar/') === false
&& strpos($url, '/client/cform/') === false
&& strpos($url, '/client/hr-document/') === false
&& strpos($url, '/client/employee-survey/') === false
&& strpos($url, '/client/location-select') === false
){
// break apart into pieces
if($locationId = $request->get('locationId')) {
/** @var Location $location */
$location = $this->entityManager->getRepository(Location::class)->find($locationId);
//Track login when default controller is bypassed by external link
if(!$this->session->get('loginIsTracked') && $this->tokenStorage->getToken() && !strpos($url, 'select_location=1')) {
$this->userActivityService->logUserActivity(LoggableListener::ACTION_LOGIN, $user, $locationId, $user);
$this->session->set('loginIsTracked', true);
}
if( !$location || !$location->isActive()
|| !$location->getCompany() || !$location->getCompany()->isActive()
|| (
$user
&& (
!$user->isHatchAdministrator()
&& !$user->getActiveLocations()->contains($location)
)
)
){
$logout = true;
}
if($logout) {
$event->getRequest()->getSession()->getFlashBag()->add('error', "Invalid location for login");
$this->logger->error('Invalid URL: ' . $url);
// clear session - logout
$this->session->clear();
$this->tokenStorage->setToken(null);
$this->session->invalidate();
header("Location: /");
exit;
}
}
}
if ($url === '/admin/' && !$this->session->get('loginIsTracked')) {
$this->userActivityService->logAdminActivity(LoggableListener::ACTION_LOGIN, $this->security->getUser(), $this->security->getUser());
$this->session->set('loginIsTracked', true);
}
}
/**
* @inheritDoc
*/
public static function getSubscribedEvents(): array
{
return array(
KernelEvents::REQUEST => 'onKernelRequest',
);
}
}