src/App/Security/Subscriber/LoginLogSubscriber.php line 46

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace App\Security\Subscriber;
  3. use App\Entity\LoginLog;
  4. use App\Entity\User;
  5. use App\RabbitMq\Writer\LoginLogWriter;
  6. use App\Service\LocationProvider;
  7. use Sindrive\RabbitMqTaskBundle\Service\TaskHandler;
  8. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  9. use Symfony\Component\HttpFoundation\Request;
  10. use Symfony\Component\Security\Core\Exception\BadCredentialsException;
  11. use Symfony\Component\Security\Core\Exception\DisabledException;
  12. use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
  13. use Symfony\Component\Security\Core\Exception\LockedException;
  14. use Symfony\Component\Security\Core\Exception\SessionUnavailableException;
  15. use Symfony\Component\Security\Core\Exception\UserNotFoundException;
  16. use Symfony\Component\Security\Http\Event\LoginFailureEvent;
  17. use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
  18. use Symfony\Component\Validator\Exception\UnexpectedTypeException;
  19. class LoginLogSubscriber implements EventSubscriberInterface
  20. {
  21.     private TaskHandler $taskHandler;
  22.     private LocationProvider $locationProvider;
  23.     public function __construct(TaskHandler $taskHandlerLocationProvider $locationProvider)
  24.     {
  25.         $this->taskHandler $taskHandler;
  26.         $this->locationProvider $locationProvider;
  27.     }
  28.     public function onSuccess(LoginSuccessEvent $event): void
  29.     {
  30.         $user $event->getUser();
  31.         if (!$user instanceof User) {
  32.             return;
  33.         }
  34.         $this->processAuthenticationAttempt($event->getRequest(), 'success'$usernullnull);
  35.     }
  36.     public function onFailure(LoginFailureEvent $event): void
  37.     {
  38.         $exception $event->getException();
  39.         $request $event->getRequest();
  40.         $user null;
  41.         $username $request->get('email');
  42.         $password $request->get('password');
  43.         $previousException $exception->getPrevious();
  44.         if ($previousException instanceof DisabledException || $previousException instanceof LockedException) {
  45.             $status 'disabled';
  46.             $username null;
  47.             $password null;
  48.             $user $previousException->getUser();
  49.         } elseif ($exception instanceof BadCredentialsException) {
  50.             if ($previousException instanceof UserNotFoundException) {
  51.                 $username $previousException->getUserIdentifier();
  52.                 $status 'wrong username';
  53.             } else {
  54.                 $status 'wrong password';
  55.             }
  56.         } elseif ($exception instanceof InvalidCsrfTokenException) {
  57.             $status $exception->getMessage();
  58.         } elseif ($exception instanceof SessionUnavailableException) {
  59.             $status $exception->getMessage();
  60.         } else {
  61.             $status $exception->getMessage();
  62.         }
  63.         if (!($user instanceof User)) {
  64.             $user null;
  65.         }
  66.         if (null !== $username && !is_string($username)) {
  67.             throw new UnexpectedTypeException($username'string');
  68.         }
  69.         if (null !== $password && !is_string($password)) {
  70.             throw new UnexpectedTypeException($username'string');
  71.         }
  72.         $this->processAuthenticationAttempt($request$status$user$username$password);
  73.     }
  74.     /**
  75.      * @return array<string, array<int|string, array<int|string, int|string>|int|string>|string>
  76.      */
  77.     public static function getSubscribedEvents(): array
  78.     {
  79.         return [
  80.             LoginSuccessEvent::class => 'onSuccess',
  81.             LoginFailureEvent::class => 'onFailure',
  82.         ];
  83.     }
  84.     private function processAuthenticationAttempt(Request $requeststring $status, ?User $user, ?string $username, ?string $password): void
  85.     {
  86.         $loginLog = new LoginLog();
  87.         $loginLog->setStatus($status);
  88.         $loginLog->setUserAgent($request->headers->get('user-agent'));
  89.         $loginLog->setIp($request->getClientIp());
  90.         $loginLog->setCountry($this->locationProvider->getCountry());
  91.         $loginLog->setReferrer($request->headers->get('referer'));
  92.         $loginLog->setUsername($username);
  93.         $loginLog->setPassword($password);
  94.         // getId here is right choice, because this entity is not being persisted, but being serialized.
  95.         $loginLog->setUserId(null !== $user $user->getId() : null);
  96.         $this->taskHandler->sendTask(LoginLogWriter::QUEUE_NAMEserialize($loginLog));
  97.     }
  98. }