<?php
declare(strict_types=1);
namespace Harmonizely\EventSubscriber;
use Harmonizely\Core\Security\Contract\ISecurityHelper;
use Harmonizely\Model\UserInterface;
use Harmonizely\Service\Panel\Terms\Contract\IGetTermsAcceptanceStatusService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\RouterInterface;
final class RequireTermsAcceptanceSubscriber implements EventSubscriberInterface
{
private const SKIP_ROUTE_PREFIXES = [
'fos_user_security_',
'fos_user_registration_',
'fos_user_resetting_',
'panel.login.',
'panel.api.login.',
'panel.api.sso.',
'panel.api.reauth.',
'panel.api.logout',
'panel.user_relation.login',
'okta.oauth.',
'login.',
'reauth.',
'consent_',
'hrm_welcome_index',
'validate_user_verification_code.base',
'validate_user_verification_code',
];
private RouterInterface $router;
private ISecurityHelper $securityHelper;
private IGetTermsAcceptanceStatusService $statusService;
public function __construct(
RouterInterface $router,
ISecurityHelper $securityHelper,
IGetTermsAcceptanceStatusService $statusService
)
{
$this->router = $router;
$this->securityHelper = $securityHelper;
$this->statusService = $statusService;
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => ['redirect'],
];
}
public function redirect(RequestEvent $event): void
{
if (!$event->isMasterRequest()) {
return;
}
if (!$this->securityHelper->getUser() instanceof UserInterface) {
return;
}
if ($this->securityHelper->getLoginType() === ISecurityHelper::LOGIN_TYPE_API_TOKEN) {
return;
}
$routeName = $event->getRequest()->get('_route');
if (null === $routeName || $this->shouldSkipRoute($routeName)) {
return;
}
if ($this->statusService->perform()->requiresAcceptance()) {
$event->setResponse(new RedirectResponse($this->router->generate('terms_acceptance_index')));
}
}
private function shouldSkipRoute(string $routeName): bool
{
if ($routeName === 'terms_acceptance_index') {
return true;
}
foreach (self::SKIP_ROUTE_PREFIXES as $prefix) {
if (0 === strpos($routeName, $prefix)) {
return true;
}
}
return false;
}
}