<?php declare(strict_types=1);
namespace App\Security\Subscriber;
use App\Entity\LoginLog;
use App\Entity\User;
use App\Model\UserLoginInfoInterface;
use App\RabbitMq\Writer\LoginLogWriter;
use App\Security\Login\LastLogin;
use App\Service\LocationProvider;
use Sindrive\RabbitMqTaskBundle\Service\TaskHandler;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
class LoginSubscriber implements EventSubscriberInterface
{
private LastLogin $lastLogin;
private TaskHandler $taskHandler;
private LocationProvider $locationProvider;
public function __construct(LastLogin $lastLogin, TaskHandler $taskHandler, LocationProvider $locationProvider)
{
$this->lastLogin = $lastLogin;
$this->taskHandler = $taskHandler;
$this->locationProvider = $locationProvider;
}
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event): void
{
if (($user = $event->getAuthenticationToken()->getUser()) instanceof UserLoginInfoInterface) {
$this->lastLogin->updateUser($user);
}
if (!($user instanceof User) || !($event->getAuthenticationToken() instanceof RememberMeToken)) {
return;
}
$request = $event->getRequest();
$loginLog = new LoginLog();
$loginLog->setStatus('success-remembered');
$loginLog->setUserAgent($request->headers->get('user-agent'));
$loginLog->setIp($request->getClientIp());
$loginLog->setCountry($this->locationProvider->getCountry());
$loginLog->setReferrer($request->headers->get('referer'));
$loginLog->setUsername($user->getUserIdentifier());
$loginLog->setPassword(null);
// getId here is right choice, because this entity is not being persisted, but being serialized.
$loginLog->setUserId($user->getId());
$this->taskHandler->sendTask(LoginLogWriter::QUEUE_NAME, serialize($loginLog));
}
/**
* @return array<string, array<int|string, array<int|string, int|string>|int|string>|string>
*/
public static function getSubscribedEvents(): array
{
return [
InteractiveLoginEvent::class => 'onSecurityInteractiveLogin',
];
}
}