src/Auth/Application/UseCase/IdempiereTokenOnLoginSuccessSubscriber.php line 36

Open in your IDE?
  1. <?php
  2. namespace App\Auth\Application\UseCase;
  3. use App\Auth\Application\Exception\BadLoginResponse;
  4. use App\Auth\Application\Exception\InvalidCredentials;
  5. use App\Auth\Application\Exception\LoginFailed;
  6. use App\Auth\Application\UseCase\LoginUseCase;
  7. use App\Entity\Idempiere\AdUser;
  8. use App\Repository\Idempiere\AdUserRepository;
  9. use Psr\Log\LoggerInterface;
  10. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  11. use Symfony\Component\HttpFoundation\RedirectResponse;
  12. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  13. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  14. use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
  15. final class IdempiereTokenOnLoginSuccessSubscriber implements EventSubscriberInterface
  16. {
  17. public function __construct(
  18. private readonly LoginUseCase $loginUseCase,
  19. private readonly UrlGeneratorInterface $urlGenerator,
  20. private readonly TokenStorageInterface $tokenStorage,
  21. private readonly LoggerInterface $logger,
  22. private readonly AdUserRepository $userRepository
  23. ) {
  24. }
  25. public static function getSubscribedEvents(): array
  26. {
  27. return [
  28. LoginSuccessEvent::class => 'onLoginSuccess',
  29. ];
  30. }
  31. public function onLoginSuccess(LoginSuccessEvent $event): void
  32. {
  33. $request = $event->getRequest();
  34. $route = (string) $request->attributes->get('_route', '');
  35. // Solo para el login normal manejado por security form_login.
  36. if ($route !== 'app_login') {
  37. return;
  38. }
  39. if (!$request->hasSession()) {
  40. return;
  41. }
  42. $session = $request->getSession();
  43. $username = (string) $request->request->get('username', $request->request->get('_username', ''));
  44. $password = (string) $request->request->get('password', $request->request->get('_password', ''));
  45. if ($username === '' || $password === '') {
  46. return;
  47. }
  48. try {
  49. $roleId = $this->resolveRoleId($event);
  50. $dto = $this->loginUseCase->execute($username, $password, $roleId);
  51. $session->set('idempiere.token', $dto->token);
  52. $session->set('idempiere.refresh_token', $dto->refreshtoken);
  53. $session->set('idempiere.userId', $dto->userId);
  54. $session->set('idempiere.language', $dto->language);
  55. $session->set('idempiere.org', $dto->org);
  56. $session->set('idempiere.client', $dto->client);
  57. $session->set('idempiere.role', $dto->role);
  58. $session->set('idempiere.warehouse_id', $dto->warehouse);
  59. $session->set('idempiere.tree', $dto->tree);
  60. } catch (InvalidCredentials | BadLoginResponse | LoginFailed $e) {
  61. $this->logger->error('Idempiere token creation failed after successful app login.', [
  62. 'route' => $route,
  63. 'username' => $username,
  64. 'error' => $e->getMessage(),
  65. 'exception' => $e,
  66. ]);
  67. $session->invalidate();
  68. $this->tokenStorage->setToken(null);
  69. if ($request->hasSession()) {
  70. $request->getSession()->getFlashBag()->add('error', 'No se pudo crear token de iDempiere: ' . $e->getMessage());
  71. }
  72. $event->setResponse(new RedirectResponse($this->urlGenerator->generate('app_login')));
  73. }
  74. }
  75. private function resolveRoleId(LoginSuccessEvent $event): int
  76. {
  77. $user = $event->getAuthenticatedToken()->getUser();
  78. if (!$user instanceof AdUser) {
  79. return 0;
  80. }
  81. $roles = $this->userRepository->findRoles($user->getId());
  82. if (empty($roles)) {
  83. return 0;
  84. }
  85. $vendorRoleId = (int)($_ENV['IDEMPIERE_ROLE_ID'] ?? 0);
  86. // Si el usuario tiene el rol de vendedor, usarlo; si no, usar su primer rol
  87. foreach ($roles as $role) {
  88. if ((int)$role['ad_role_id'] === $vendorRoleId) {
  89. return $vendorRoleId;
  90. }
  91. }
  92. return (int)$roles[0]['ad_role_id'];
  93. }
  94. }