<?php
namespace MedBrief\MSR\EventSubscriber;
use MedBrief\MSR\Entity\AuditRecord\User as UserAuditRecord;
use MedBrief\MSR\Event\AuditRecordEvent;
use MedBrief\MSR\Factory\AuditRecordEventFactory;
use MedBrief\MSR\Factory\AuditRecordFactory;
use Override;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Event\LogoutEvent;
class LogoutSubscriber implements EventSubscriberInterface
{
public function __construct(private readonly SessionInterface $session, private readonly EventDispatcherInterface $eventDispatcher)
{
}
/**
* @inheritDoc
*/
#[Override]
public static function getSubscribedEvents()
{
return [
LogoutEvent::class => 'onLogout',
];
}
/**
* Invalidates the current session, but retains any flashes to display
*
* @param LogoutEvent $event
*/
public function onLogout(LogoutEvent $event): void
{
$flashes = $this->session->getFlashBag()->all();
// This will effectively log out the user by clearing all session data
// associated with the user's session.
$this->session->invalidate();
// Re-add the flashes back to the new session
$this->session->getFlashBag()->setAll($flashes);
$this->logLogoutEvent($event);
}
/**
* Logs an audit record of the logout event.
*
* @param LogoutEvent $event
*/
private function logLogoutEvent(LogoutEvent $event): void
{
$token = $event->getToken();
// Check if there is a token, this will prevent an error being thrown when $token->getUser() runs
if (!$token instanceof TokenInterface) {
return;
}
$user = $token->getUser();
$auditRecord = AuditRecordFactory::create(
UserAuditRecord::class,
$user,
null,
UserAuditRecord::VERB_LOGOUT
);
$this->eventDispatcher->dispatch(
AuditRecordEventFactory::create($auditRecord),
AuditRecordEvent::AUDIT
);
}
}