src/MyBundle/Controller/AuthController.php line 1006

Open in your IDE?
  1. <?php
  2. namespace MyBundle\Controller;
  3. use CoreBundle\Entity\User;
  4. use CoreBundle\Repository\UserRepository;
  5. use DateTime;
  6. use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
  7. use Doctrine\ORM\EntityManagerInterface;
  8. use MyBundle\Component\InfobipSmsSender;
  9. use MyBundle\Entity\AttemptLogin;
  10. use MyBundle\Entity\CrossDomainAuthToken;
  11. use MyBundle\Entity\Otp;
  12. use MyBundle\Entity\RegisterRequest;
  13. use MyBundle\Entity\UserReferral;
  14. use MyBundle\Enum\AuthDataKeys;
  15. use MyBundle\Enum\RegistrationStatusEnums;
  16. use MyBundle\Exception\DataNotValidException;
  17. use MyBundle\Exception\UserNotFoundException;
  18. use MyBundle\Factory\AuthCodeDTOFactory;
  19. use MyBundle\Factory\OtpCodeGenerator;
  20. use MyBundle\Factory\OtpEntityFactory;
  21. use MyBundle\Factory\RegUserDTOFactory;
  22. use MyBundle\Factory\StringGenerator;
  23. use MyBundle\Factory\UserEntityFactory;
  24. use MyBundle\Messages;
  25. use MyBundle\Service\AuthDataValidator;
  26. use MyBundle\Service\AuthService;
  27. use Psr\Log\LoggerInterface;
  28. use Symfony\Component\HttpFoundation\JsonResponse;
  29. use Symfony\Component\HttpFoundation\RedirectResponse;
  30. use Symfony\Component\HttpFoundation\Request;
  31. use Symfony\Component\HttpFoundation\RequestStack;
  32. use Symfony\Component\HttpFoundation\Response;
  33. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  34. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  35. use Symfony\Component\Mailer\MailerInterface;
  36. use Symfony\Component\Mime\Address;
  37. use Symfony\Component\Mime\Email;
  38. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
  39. use Symfony\Component\Routing\RouterInterface;
  40. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  41. use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
  42. use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
  43. use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
  44. use Symfony\Component\Security\Http\Util\TargetPathTrait;
  45. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  46. use Symfony\Contracts\Translation\TranslatorInterface;
  47. use Twig\Environment;
  48. class AuthController extends MyBaseController
  49. {
  50.     use TargetPathTrait;
  51.     private SessionInterface $session;
  52.     private TokenStorageInterface $tokenStorage;
  53.     public function __construct(EntityManagerInterface $emRequestStack $requestStackMessages $messages,
  54.                                 \CoreBundle\Model\User $userModelSessionInterface $session,
  55.                                 TokenStorageInterface  $tokenStorageEnvironment $twig)
  56.     {
  57.         parent::__construct($em$requestStack$messages$userModel$twig);
  58.         $this->session $session;
  59.         $this->tokenStorage $tokenStorage;
  60.     }
  61.     public function logout(AuthService $authService): RedirectResponse
  62.     {
  63.         if ($this->getUser()) {
  64.             $authService->logoutUser($this->getUser());
  65.         }
  66.         return $this->redirectToRoute('my_login_page');
  67.     }
  68.     public function resendSms(Request $request): JsonResponse
  69.     {
  70.         $hash $request->get('hash');
  71.         if (!$this->userModel->initByHash($hash)) {
  72.             return $this->errorResponce(['total' => 'Виникла помилка, будь ласка, спробуйте ще раз пізніше']);
  73.         }
  74.         if ($this->userModel->sendConfirmSms()) {
  75.             return new JsonResponse(['success' => true'phone' => $this->userModel->getPhone()]);
  76.         }
  77.         return $this->errorResponce(['total' => 'Ви використали всі спроби доставки sms']);
  78.     }
  79.     public function confirmPhone(Request $request)
  80.     {
  81.         $hash $request->request->get('hash');
  82.         if (!$this->userModel->initByHash($hash)) {
  83.             return new JsonResponse(['success' => false]);
  84.         }
  85.         $code $request->request->get('code');
  86.         if (!$this->userModel->checkConfirmPhone($code)) {
  87.             return new JsonResponse(['success' => false]);
  88.         }
  89.         $this->userModel->senConfirmEmail();
  90.         return new JsonResponse(['success' => true'hash' => $hash]);
  91.     }
  92.     public function reSendEmail(Request $request): JsonResponse
  93.     {
  94.         $hash $request->get('hash');
  95.         if (!$this->userModel->initByHash($hash)) {
  96.             return new JsonResponse(['success' => false]);
  97.         }
  98.         $this->userModel->senConfirmEmail();
  99.         return new JsonResponse(['success' => true]);
  100.     }
  101.     public function confirmEmail(Request $request): ?Response
  102.     {
  103.         if (!$this->userModel->initByHash($request->get('hash'))) {
  104.             throw new NotFoundHttpException();
  105.         }
  106.         return $this->baseMyRender('@My/Auth/confirm_email.html.twig', [
  107.             'user' => $this->userModel->getUser()
  108.         ]);
  109.     }
  110.     public function finish($userHash$hash): ?Response
  111.     {
  112.         $success false;
  113.         if ($this->userModel->initByHash($userHash)) {
  114.             $success $this->userModel->confirmEmail($hash);
  115.         }
  116.         return $this->baseMyRender(
  117.             '@My/Auth/finish_register.html.twig',
  118.             ['success' => $success'ehash' => $this->userModel->getUser()->getEmailHash(), 'hash' => $this->userModel->getHash()]
  119.         );
  120.     }
  121.     public function setPassword(Request $requestEventDispatcherInterface $eventDispatcher): JsonResponse
  122.     {
  123.         $hash $request->get('userHash');
  124.         if (!$this->userModel->initByHash($hash)) {
  125.             return new JsonResponse(['success' => false]);
  126.         }
  127.         $emailHash $request->request->get('ehash');
  128.         if ($emailHash != $this->userModel->getUser()->getEmailHash()) {
  129.             return new JsonResponse(['success' => false]);
  130.         }
  131.         $password $request->request->get('password');
  132.         $this->userModel->setPassword($password);
  133.         $token = new UsernamePasswordToken($this->userModel->getUser(), null'prifile'$this->userModel->getUser()->getRoles());
  134.         $this->tokenStorage->setToken($token);
  135.         $this->session->set('_security_prifile'serialize($token));
  136.         $event = new InteractiveLoginEvent($request$token);
  137.         //TODO refactor this to correct dispatcher
  138.         $eventDispatcher->dispatch($event"security.interactive_login");
  139.         return new JsonResponse(['success' => true]);
  140.     }
  141.     public function recover($hash$ehash)
  142.     {
  143.         if (!$this->userModel->initByHash($hash)) {
  144.             throw $this->createAccessDeniedException();
  145.         }
  146.         if ($ehash != $this->userModel->getUser()->getEmailHash()) {
  147.             throw $this->createAccessDeniedException();
  148.         }
  149.         return $this->baseMyRender('@My/Auth/recover_pass.html.twig', [
  150.             'hash' => $hash,
  151.             'ehash' => $ehash,
  152.         ]);
  153.     }
  154.     public function loginCheck(Request $requestAuthService $authServiceEncoderFactoryInterface $factory): JsonResponse
  155.     {
  156.         $phone $request->request->get('phone');
  157.         $phone substr(preg_replace('~[^0-9]+~'''$phone), -10);
  158.         $_password $request->get('password');
  159.         $cardNumber $request->request->get('card');
  160.         $cardNumber preg_replace('~[^0-9]+~'''$cardNumber);
  161.         $login $request->get('login');
  162.         if ($login) {
  163.             $user $this->em->getRepository(User::class)->findOneBy(['username' => $login]);
  164.         } else {
  165.             $user $this->em->getRepository(User::class)->findByPhoneOrCardNum($phone$cardNumber);
  166.         }
  167.         if (!$user) {
  168.             return new JsonResponse(['success' => false'error' => 'account is not found']);
  169.         }
  170.         $encoder $factory->getEncoder($user);
  171.         $salt $user->getSalt();
  172.         if (!$encoder->isPasswordValid($user->getPassword(), $_password$salt)) {
  173.             return new JsonResponse(['success' => false'error' => 'password wrong']);
  174.         }
  175.         $this->userModel->pushReferrer($request$userUser::UTM_LOGIN);
  176.         return $authService->loginUser($user);
  177.     }
  178.     public function login(Request $requestEventDispatcherInterface $eventDispatcherRouterInterface $routerAuthService $authService): RedirectResponse|Response|null
  179.     {
  180.         if ($this->getUser()) {
  181.             $referer $authService->getRefererUser($request$this->getUser());
  182.             if ($referer) {
  183.                 return $this->redirect($referer);
  184.             }
  185.         }
  186.         $url $this->getTargetPath($request->getSession(), 'main');
  187.         if ($this->getUser() && !$referer) {
  188.             return $this->redirect($router->generate('my_about_car_page'));
  189.         }
  190.         $tokenStr $request->query->get('token');
  191.         if ($tokenStr) {
  192.             $AuthToken =
  193.                 $this->em
  194.                     ->getRepository(CrossDomainAuthToken::class)
  195.                     ->findOneBy(['token' => $tokenStr]);
  196.             if (!$AuthToken) {
  197.                 return $this->baseMyRender('@My/Auth/login.html.twig');
  198.             }
  199.             $now = new DateTime();
  200.             $tokenCreateDate $AuthToken->getDateCreate();
  201.             //TODO remove to some config
  202.             if ($tokenCreateDate $now->modify('-30 min')) {
  203.                 return $this->baseMyRender('@My/Auth/login.html.twig');
  204.             }
  205.             $user $AuthToken->getUser();
  206.             $token = new UsernamePasswordToken($usernull'profile'$user->getRoles());
  207.             $this->tokenStorage->setToken($token);
  208.             $this->session->set('_security_profile'serialize($token));
  209.             $event = new InteractiveLoginEvent($request$token);
  210.             //TODO refactor this to correct dispatcher
  211.             $eventDispatcher->dispatch($event"security.interactive_login");
  212.             $this->em->remove($AuthToken);
  213.             $this->em->flush();
  214.             return $this->redirect($request->headers->get('referer'));
  215.         }
  216.         return $this->baseMyRender('@My/Auth/login.html.twig', [
  217.             'backLoginUrl' => $url
  218.         ]);
  219.     }
  220.     public function register(
  221.         Request             $request,
  222.         AuthDataValidator   $validator,
  223.         LoggerInterface     $logger,
  224.         UserEntityFactory   $userEntityFactory,
  225.         RegUserDTOFactory   $userDTOFactory,
  226.         OtpCodeGenerator    $codeGenerator,
  227.         TranslatorInterface $translator
  228.     ): JsonResponse
  229.     {
  230.         $translator->setLocale($request->getLocale());
  231.         if ($request->request->has('locale')) {
  232.             $translator->setLocale($request->get('locale'));
  233.         }
  234.         $data $request->request->all();
  235.         try {
  236.             $validator->validateForRegisterUser($data);
  237.         } catch (DataNotValidException $e) {
  238.             $logger->error($e->getMessage(), $data);
  239.             return new JsonResponse([
  240.                 'success' => false,
  241.                 'message' => $translator->trans('auth.error', [], 'loyality'),
  242.             ]);
  243.         }
  244.         $userRegDTO $userDTOFactory->createDefaultAuthDTO($data);
  245.         /** @var UserRepository $users */
  246.         $users $this->em->getRepository(User::class);
  247.         $userCount $users->checkRegisteredUsersByParams(
  248.             [
  249.                 'phone' => $userRegDTO->phone,
  250.                 'email' => $userRegDTO->email
  251.             ]
  252.         );
  253.         if ($userCount) {
  254.             return new JsonResponse([
  255.                 'success' => false,
  256.                 'message' => $translator->trans('auth.duplicate_email_or_phone', [], 'loyality'),
  257.             ]);
  258.         }
  259.         $registerRequest = new RegisterRequest();
  260.         $registerRequest->setDateCreate(new DateTime());
  261.         $registerRequest->setPhone($userRegDTO->phone);
  262.         $registerRequest->setRequest(json_encode($data));
  263.         $registerRequest->setIsComplete(false);
  264.         $this->em->persist($registerRequest);
  265.         $this->em->flush();
  266.         $otp $codeGenerator->generate();
  267.         $registerRequest->setOtp($otp);
  268.         $registerRequest->setOtpExpDate((new DateTime())->modify('+1 hour'));
  269.         try {
  270.             $em $this->em;
  271.             $em->persist($registerRequest);
  272.             $em->flush();
  273.         } catch (UniqueConstraintViolationException $ex) {
  274.             return new JsonResponse([
  275.                 'success' => false,
  276.                 'message' => $translator->trans('auth.duplicate_email', [], 'loyality'),
  277.             ]);
  278.         }
  279.         return new JsonResponse([
  280.             'success' => true,
  281.             'requestId' => $registerRequest->getId(),
  282.             'message' => $translator->trans(
  283.                 'auth.sending_to_phone_succeed',
  284.                 ['%phone%' => $this->getSecurePhone($registerRequest->getPhone())],
  285.                 'loyality'
  286.             ),
  287.         ]);
  288.     }
  289.     public function getCode(
  290.         Request             $request,
  291.         AuthDataValidator   $validator,
  292.         LoggerInterface     $logger,
  293.         AuthCodeDTOFactory  $DTOFactory,
  294.         OtpEntityFactory    $otpEntityFactory,
  295.         UserEntityFactory   $userEntityFactory,
  296.         RegUserDTOFactory   $userDTOFactory,
  297.         TranslatorInterface $translator,
  298.         InfobipSmsSender    $infobipSmsSender,
  299.         AuthService $authService
  300.     ): JsonResponse
  301.     {
  302.         $data $request->request->all();
  303.         $phone substr(preg_replace('~[^0-9]+~'''$data[AuthDataKeys::EMAIL]), -10);
  304.         if ($request->request->get('loginPhone') == 'false') {
  305.             $email $request->request->get('email');
  306.             $userAuth $DTOFactory->getUserByEmail($email);
  307.         } else {
  308.             $userAuth $DTOFactory->getUserByPhone($phone);
  309.         }
  310.         $requestId $request->get('requestId');
  311.         if (!$userAuth && $requestId) {
  312.             $RegisterRequest $this->em->getRepository(RegisterRequest::class)->find($requestId);
  313.             if (!$RegisterRequest) {
  314.                 return new JsonResponse(['success' => false'error' => $translator->trans('auth.error', [], 'loyality')]);
  315.             }
  316.             $requestData json_decode($RegisterRequest->getRequest());
  317.             $requestEmail $requestData->email;
  318.             if (($phone != '' && $RegisterRequest->getPhone() != $phone) || ($email && $requestEmail != $email)) {
  319.                 return new JsonResponse(['success' => false'error' => $translator->trans('auth.error', [], 'loyality')]);
  320.             }
  321.             $em $this->em;
  322.             $dataRegister json_decode($RegisterRequest->getRequest(), true);
  323.             $userRegDTO $userDTOFactory->createDefaultAuthDTO($dataRegister);
  324.             $user $userEntityFactory->createUser($userRegDTO);
  325.             $user->setIsLoyalty(UserEntityFactory::LOYALTY_STATUS_DEFAULT);
  326.             $user->setEnabled(UserEntityFactory::ENABLED_STATUS);
  327.             $user->setRegistrationConfirm(UserEntityFactory::REGISTRATION_STATUS_CONFIRMED);
  328.             $user->setConfirmedPhone(UserEntityFactory::REGISTRATION_STATUS_CONFIRMED);
  329.             //TODO move to some config
  330.             if (!$user->hasRole('ROLE_LOYALTY_USER')) {
  331.                 $user->addRole('ROLE_LOYALTY_USER');
  332.             }
  333.             if (!$user->getPhone()) {
  334.                 $user->setPhone($phone);
  335.             }
  336.             $RegisterRequest->setIsComplete(1);
  337.             $RegisterRequest->setUser($user);
  338.             $em->persist($user);
  339.             $em->persist($RegisterRequest);
  340.             $em->flush();
  341.             $this->userModel->pushReferrer($request$userUser::UTM_REGISTRATION);
  342.         }
  343.         $translator->setLocale($request->getLocale());
  344.         if ($request->request->has('locale')) {
  345.             $translator->setLocale($request->get('locale'));
  346.         }
  347.         try {
  348.             $validator->validateGetCodeData($data);
  349.             $authDTO $DTOFactory->createWithLoginPropertyOnly($data);
  350.         } catch (DataNotValidException $e) {
  351.             $logger->error($e->getMessage(), $data);
  352.             return new JsonResponse([
  353.                 'success' => false,
  354.                 'field' => 'other',
  355.                 'error' => $translator->trans('auth.error', [], 'loyality'),
  356.             ]);
  357.         } catch (UserNotFoundException $e) {
  358.             $logger->critical($e->getMessage(), $data);
  359.             return new JsonResponse([
  360.                 'success' => false,
  361.                 'field' => 'other',
  362.                 'error' => $translator->trans('auth.user_not_found', [], 'loyality'),
  363.             ]);
  364.         }
  365.         $em $this->em;
  366.         if (!$this->checkAttemptLogin($authDTO->user$em$authDTO->login$authService)) {
  367.             return new JsonResponse([
  368.                 'success' => false,
  369.                 'field' => 'other',
  370.                 'error' => $translator->trans('auth.access_denied', [], 'loyality'),
  371.             ]);
  372.         }
  373.         $codes $em->getRepository(Otp::class)
  374.             ->findBy(['user' => $authDTO->user'state' => RegistrationStatusEnums::CREATED_STATE]);
  375. // todo remove when realise what this number are
  376.         $now = new DateTime();
  377.         foreach ($codes as $code) {
  378.             //TODO move to config
  379.             if ($code->getDateCreate()->modify('+15 minutes') <= $now) {
  380.                 /** @var Otp $code */
  381.                 $code->setState(RegistrationStatusEnums::OUTDATED_STATE);
  382. //$code->setState(3); todo remove when realise what this number are
  383.                 $em->persist($code);
  384.                 $em->flush();
  385.                 continue;
  386.             }
  387.             $code->setState(RegistrationStatusEnums::USED_STATE);
  388. //$code->setState(4); todo remove when realise what this number are
  389.             $em->persist($code);
  390.             $em->flush();
  391.         }
  392.         $resendCount 0;
  393.         foreach ($codes as $code) {
  394.             if ($code->getDateCreate()->modify('+30 minutes') >= $now) {
  395.                 $resendCount++;
  396.             }
  397.         }
  398.         if ($resendCount RegistrationStatusEnums::MAX_AUTH_ATTEMPT) {
  399.             return new JsonResponse([
  400.                 'success' => false,
  401.                 'field' => 'other',
  402.                 'error' => $translator->trans('auth.try_again_later', [], 'loyality')
  403.             ]);
  404.         }
  405.         $otpEntity $otpEntityFactory->createOtp($authDTO->user);
  406.         $authDTO->user->setOtp($otpEntity->getCode());
  407.         $authDTO->user->setOtpExpDate((new DateTime())->modify('+1 hour'));
  408.         $em->persist($otpEntity);
  409.         $em->persist($authDTO->user);
  410.         $em->flush();
  411.         if ($authDTO->user->getPhone() == null || strlen($authDTO->user->getPhone()) < User::MIN_LENGTH_PHONE) {
  412.             $message $translator->trans(
  413.                 'auth.phone_send_error',
  414.                 ['%phone%' => $this->getSecurePhone($authDTO->user->getPhone())],
  415.                 'loyality'
  416.             );
  417.             return new JsonResponse([
  418.                 'success' => false,
  419.                 'field' => 'brokenPhone',
  420.                 'error' => $message,
  421.             ]);
  422.         }
  423.         $infobipSmsSender->sendSms(
  424.             $authDTO->user->getPhone(),
  425.             $translator->trans('auth.your_auth_code', ['%code%' => $otpEntity->getCode()], 'loyality')
  426.         );
  427.         return new JsonResponse([
  428.             'success' => true,
  429.             'phone' => $authDTO->user->getPhone(),
  430.             'message' => $translator->trans(
  431.                 'auth.sending_to_phone_succeed',
  432.                 ['%phone%' => $this->getSecurePhone($authDTO->user->getPhone())],
  433.                 'loyality'
  434.             ),
  435.             'code' => $otpEntity->getId(),
  436.         ]);
  437.     }
  438.     public function resendRegistrationCode(Request             $requestOtpEntityFactory $otpEntityFactory,
  439.                                            TranslatorInterface $translatorInfobipSmsSender $infobipSmsSender): JsonResponse
  440.     {
  441.         $translator->setLocale($request->getLocale());
  442.         if ($request->request->has('locale')) {
  443.             $translator->setLocale($request->get('locale'));
  444.         }
  445.         $data $request->request->all();
  446.         $requestId $data['requestId'];
  447.         $RegisterRequest $this->em->getRepository(RegisterRequest::class)->find($requestId);
  448.         //TODO move to config or service
  449.         $phone substr(preg_replace('~[^0-9]+~'''$data['phone']), -10);
  450.         if (!$RegisterRequest || $RegisterRequest->getPhone() != $phone) {
  451.             return new JsonResponse([
  452.                 'success' => false,
  453.                 'field' => 'other',
  454.                 'error' => $translator->trans('auth.error', [], 'loyality'),
  455.             ]);
  456.         }
  457.         $em $this->em;
  458.         $codes $em->getRepository(Otp::class)
  459.             ->findBy(['request' => $RegisterRequest'state' => RegistrationStatusEnums::CREATED_STATE]);
  460.         $now = new DateTime();
  461.         foreach ($codes as $code) {
  462.             /** @var Otp $code */
  463.             //TODO move to config
  464.             if ($code->getDateCreate()->modify('+15 minutes') <= $now) {
  465.                 $code->setState(RegistrationStatusEnums::OUTDATED_STATE);
  466.                 $em->persist($code);
  467.                 $em->flush();
  468.                 continue;
  469.             }
  470.             $code->setState(RegistrationStatusEnums::USED_STATE);
  471.             $em->persist($code);
  472.             $em->flush();
  473.         }
  474.         $resendCount 0;
  475.         foreach ($codes as $code) {
  476.             if ($code->getDateCreate()->modify('+30 minutes') >= $now) {
  477.                 $resendCount++;
  478.             }
  479.         }
  480.         if ($resendCount RegistrationStatusEnums::MAX_AUTH_ATTEMPT) {
  481.             return new JsonResponse([
  482.                 'success' => false,
  483.                 'field' => 'other',
  484.                 'error' => $translator->trans('auth.try_again_later', [], 'loyality')
  485.             ]);
  486.         }
  487.         $otpEntity $otpEntityFactory->createOtpByRequest($RegisterRequest);
  488.         $RegisterRequest->setOtp($otpEntity->getCode());
  489.         $RegisterRequest->setOtpExpDate((new DateTime())->modify('+1 hour'));
  490.         $em->persist($otpEntity);
  491.         $em->persist($RegisterRequest);
  492.         $em->flush();
  493.         $infobipSmsSender->sendSms(
  494.             $RegisterRequest->getPhone(),
  495.             $translator->trans('auth.your_auth_code', ['%code%' => $otpEntity->getCode()], 'loyality')
  496.         );
  497.         return new JsonResponse([
  498.             'success' => true,
  499.             'phone' => $RegisterRequest->getPhone(),
  500.             'message' => $translator->trans(
  501.                 'auth.sending_to_phone_succeed',
  502.                 ['%phone%' => $this->getSecurePhone($RegisterRequest->getPhone())],
  503.                 'loyality'
  504.             ),
  505.             'code' => $otpEntity->getId(),
  506.         ]);
  507.     }
  508.     public function confirmRegistration(
  509.         Request             $request,
  510.         UserEntityFactory   $userEntityFactory,
  511.         RegUserDTOFactory   $userDTOFactory,
  512.         TranslatorInterface $translator,
  513.         AuthService $authService
  514.     ): JsonResponse
  515.     {
  516.         $requestId $request->get('requestId');
  517.         $code $request->get('code');
  518.         $phone $request->get('phone');
  519.         //TODO move to config or service
  520.         $phone substr(preg_replace('~[^0-9]+~'''$phone), -10);
  521.         $RegisterRequest $this->em->getRepository(RegisterRequest::class)->find($requestId);
  522.         if (!$RegisterRequest || $RegisterRequest->getPhone() != $phone) {
  523.             return new JsonResponse(['success' => false'error' => $translator->trans('auth.error', [], 'loyality')]);
  524.         }
  525.         $em $this->em;
  526.         if ($RegisterRequest->getOtp() == $code && $RegisterRequest->getOtpExpDate() > (new DateTime)) {
  527.             $data json_decode($RegisterRequest->getRequest(), true);
  528.             $userRegDTO $userDTOFactory->createDefaultAuthDTO($data);
  529.             $user $userEntityFactory->createUser($userRegDTO);
  530.             $user->setIsLoyalty(UserEntityFactory::LOYALTY_STATUS_DEFAULT);
  531.             $user->setEnabled(UserEntityFactory::ENABLED_STATUS);
  532.             $user->setRegistrationConfirm(UserEntityFactory::REGISTRATION_STATUS_CONFIRMED);
  533.             $user->setConfirmedPhone(UserEntityFactory::REGISTRATION_STATUS_CONFIRMED);
  534.             //TODO move to some config
  535.             if (!$user->hasRole('ROLE_LOYALTY_USER')) {
  536.                 $user->addRole('ROLE_LOYALTY_USER');
  537.             }
  538.             if (!$user->getPhone()) {
  539.                 $user->setPhone($phone);
  540.             }
  541.             $RegisterRequest->setIsComplete(1);
  542.             $RegisterRequest->setUser($user);
  543.             $em->persist($user);
  544.             $em->persist($RegisterRequest);
  545.             $em->flush();
  546.             $this->userModel->pushReferrer($request$userUser::UTM_REGISTRATION);
  547.             return $authService->loginUser($user);
  548.         }
  549.         return new JsonResponse(['success' => false'error' => 'Не вiрний код']);
  550.     }
  551.     public function referralRegister(
  552.         Request                     $request,
  553.         OtpCodeGenerator            $codeGenerator,
  554.         StringGenerator             $stringGenerator,
  555.         TranslatorInterface         $translator,
  556.         UserPasswordHasherInterface $encoder,
  557.         InfobipSmsSender            $infobipSmsSender
  558.     ): JsonResponse
  559.     {
  560.         $translator->setLocale($request->getLocale());
  561.         if ($request->request->has('locale')) {
  562.             $translator->setLocale($request->get('locale'));
  563.         }
  564.         $email $request->get('email');
  565.         $password $stringGenerator->generateUpperCaseAndNumbers();
  566.         $phone $request->get('phone');
  567.         $users $this->em->getRepository(User::class);
  568.         if ($users->checkRegisteredUsersByParams(['email' => $email])) {
  569.             return new JsonResponse([
  570.                 'success' => false,
  571.                 'error' => $translator->trans('register.email_already_in_use', [], 'loyality'),
  572.             ]);
  573.         }
  574.         $user $users->findByPhoneOrCardNum($phone);
  575.         if (!$user) {
  576.             return new JsonResponse([
  577.                 'success' => false,
  578.                 'error' => $translator->trans('register.user_register_problem', [], 'loyality'),
  579.             ]);
  580.         }
  581.         /** @var User $user */
  582.         $referrerUser $this->em
  583.             ->getRepository(UserReferral::class)->findOneBy(['user_id' => $user->getId()]);
  584.         $em $this->em;
  585.         if ($user && $user->getRegistrationConfirm()) {
  586.             return new JsonResponse([
  587.                 'success' => false,
  588.                 'error' => $translator->trans('register.user_already_register', [], 'loyality'),
  589.             ]);
  590.         }
  591.         $otp $codeGenerator->generate();
  592.         $user->setRegistrationConfirm(UserEntityFactory::REGISTRATION_STATUS_DEFAULT);
  593.         $user->setEmail($email);
  594.         $user->setEnabled(UserEntityFactory::ENABLED_STATUS);
  595.         $user->setIsLoyalty(UserEntityFactory::LOYALTY_STATUS_DEFAULT);
  596.         $user->setUsername($email);
  597.         $user->setEmailCanonical($email);
  598.         $user->setPassword($encoder->hashPassword($user$password));
  599.         $user->setOtp($otp);
  600.         //TODO move to some config
  601.         $user->setOtpExpDate((new DateTime())->modify('+1 hour'));
  602.         $user->setReferrer($referrerUser->getPromoCode());
  603.         $user->setConfirmPhoneCod($otp);
  604.         $em->persist($user);
  605.         try {
  606.             $em->flush();
  607.         } catch (UniqueConstraintViolationException $ex) {
  608.             return new JsonResponse([
  609.                 'success' => false,
  610.                 'error' => $translator->trans('register.main_problem', [], 'loyality'),
  611.             ]);
  612.         }
  613.         $infobipSmsSender->sendSms(
  614.             $phone,
  615.             $translator->trans('register.your_code_for_registration', ['%code%' => $otp], 'loyality')
  616.         );
  617.         return new JsonResponse([
  618.             'success' => true,
  619.             'message' => $translator->trans(
  620.                 'auth.sending_to_phone_succeed',
  621.                 ['%phone%' => $this->getSecurePhone($phone)],
  622.                 'loyality'
  623.             ),
  624.         ]);
  625.     }
  626.     public function referralRegisterConfirm(Request $requestAuthService $authService): JsonResponse
  627.     {
  628.         $code $request->get('code');
  629.         $phone $request->get('phone');
  630.         $em $this->em;
  631.         /** @var User $user */
  632.         if (!($user $this->em->getRepository(User::class)->findByPhoneOrCardNum($phone))) {
  633.             //TODO translate this
  634.             return new JsonResponse(
  635.                 [
  636.                     'success' => false,
  637.                     'error' => 'Користувача не знайдено, зверніться до адміністратора'
  638.                 ]
  639.             );
  640.         }
  641.         $ReferralUser $this->em->getRepository(UserReferral::class)
  642.             ->findOneBy(['user_id' => $user->getId(), 'promo_code' => $user->getReferrer()]);
  643.         if (!$ReferralUser) {
  644.             //TODO translate this
  645.             return new JsonResponse(
  646.                 [
  647.                     'success' => false,
  648.                     'error' => 'Користувача не знайдено, зверніться до адміністратора'
  649.                 ]
  650.             );
  651.         }
  652.         $ReferralUser->setStatus(UserReferral::STATUS_REGISTERED);
  653.         $em->persist($ReferralUser);
  654.         $em->flush();
  655.         if ($user->getOtp() == $code && $user->getOtpExpDate() > (new DateTime)) {
  656.             $user->setIsLoyalty(1);
  657.             $user->setEnabled(1);
  658.             $user->setRegistrationConfirm(1);
  659.             $user->setConfirmedPhone(1);
  660.             //TODO move to some config
  661.             if (!$user->hasRole('ROLE_LOYALTY_USER')) {
  662.                 $user->addRole('ROLE_LOYALTY_USER');
  663.             }
  664.             if (!$user->getPhone()) {
  665.                 $user->setPhone($phone);
  666.             }
  667.             $em->persist($user);
  668.             $em->flush();
  669.             $this->userModel->pushReferrer($request$userUser::UTM_REGISTRATION);
  670.             return $authService->loginUser($user);
  671.         }
  672.         return new JsonResponse(['success' => false'error' => 'Не вірний код']);
  673.     }
  674.     public function recoveryConfirmCode(Request $request): JsonResponse
  675.     {
  676.         $codeId $request->get('code');
  677.         $userCode $request->get('userCode');
  678.         $user null;
  679.         $login $request->get('email');
  680.         if ($request->get('loginPhone') === 'true') {
  681.             $login $this->preparePhone($login);
  682.             $user $this->em
  683.                 ->getRepository(User::class)
  684.                 ->findByPhoneOrCardNum($loginnullnull);
  685.         } else {
  686.             $user $this->em
  687.                 ->getRepository(User::class)
  688.                 ->findByPhoneOrCardNum(nullnull$login);
  689.         }
  690.         $userData null;
  691.         //TODO translate this
  692.         if (!$user) {
  693.             return new JsonResponse([
  694.                 'success' => false,
  695.                 'error' => 'Користувача з таким email та паролем не знайдено',
  696.             ]);
  697.         } else {
  698.             $userData $this->em->getRepository(User::class)->find($user);
  699.         }
  700.         $em $this->em;
  701.         $code $em->getRepository(Otp::class)->find($codeId);
  702.         if (!$code || $code->getUser() != $user) {
  703.             //TODO translate this
  704.             return new JsonResponse([
  705.                 'success' => false,
  706.                 'error' => 'Ваш код прострочений, будь ласка, отримаєте новий код'
  707.             ]);
  708.         }
  709.         if ($userCode != $code->getCode() || $userCode != $userData->getOtp()) {
  710.             //TODO translate this
  711.             return new JsonResponse([
  712.                 'success' => false,
  713.                 'error' => 'Невірний код'
  714.             ]);
  715.         }
  716.         if ($userData->getOtpExpDate() < (new DateTime)) {
  717.             //TODO translate this
  718.             return new JsonResponse([
  719.                 'success' => false,
  720.                 'error' => 'Термін дії коду закінчився. Вам необхідно запросити новий код відновлення',
  721.             ]);
  722.         }
  723.         return new JsonResponse(['success' => true]);
  724.     }
  725.     public function codeLogin(Request $requestTranslatorInterface $translatorAuthService $authService): JsonResponse
  726.     {
  727.         $translator->setLocale($request->getLocale());
  728.         if ($request->request->has('locale')) {
  729.             $translator->setLocale($request->get('locale'));
  730.         }
  731.         $user $this->getUser();
  732.         if ($user) {
  733.             $authService->logoutUser($user);
  734.         }
  735.         return $authService->verifyAuthUser();
  736.     }
  737.     public function codeLoginNewPhone(Request $requestTranslatorInterface $translatorAuthService $authService): JsonResponse
  738.     {
  739.         $translator->setLocale($request->getLocale());
  740.         if ($request->request->has('locale')) {
  741.             $translator->setLocale($request->get('locale'));
  742.         }
  743.         $user $this->getUser();
  744.         if ($user) {
  745.             $authService->logoutUser($user);
  746.         }
  747.         return $authService->verifyAuthNewPhoneUser();
  748.     }
  749.     public function getCodeRecovery(Request $requestTranslatorInterface $translatorInfobipSmsSender $infobipSmsSender): JsonResponse
  750.     {
  751.         $translator->setLocale($request->getLocale());
  752.         if ($request->request->has('locale')) {
  753.             $translator->setLocale($request->get('locale'));
  754.         }
  755.         $user null;
  756.         $login $request->get('email');
  757.         if ($request->get('loginPhone') === 'true') {
  758.             $login $this->preparePhone($login);
  759.             $user $this->em
  760.                 ->getRepository(User::class)
  761.                 ->findByPhoneOrCardNum($loginnullnull);
  762.         } else {
  763.             $user $this->em
  764.                 ->getRepository(User::class)
  765.                 ->findByPhoneOrCardNum(nullnull$login);
  766.         }
  767.         $userData null;
  768.         if (!$user) {
  769.             return new JsonResponse([
  770.                 'success' => false,
  771.                 'error' => $translator->trans('recovery.user_not_found', [], 'loyality')
  772.             ]);
  773.         } else {
  774.             //WTF??
  775.             $userData $this->em->getRepository(User::class)->find($user);
  776.         }
  777.         $em $this->em;
  778.         $codes =
  779.             $em->getRepository(Otp::class)
  780.                 ->findBy(['user' => $user'state' => RegistrationStatusEnums::CREATED_STATE]);
  781.         foreach ($codes as $code) {
  782.             $now = new DateTime();
  783.             if ($code->getDateCreate()->modify('+15 minutes') <= $now) {
  784. //                $code->setState(3);
  785.                 $code->setState(RegistrationStatusEnums::OUTDATED_STATE);
  786.                 $em->persist($code);
  787.                 continue;
  788.             }
  789. //            $code->setState(4);
  790.             $code->setState(RegistrationStatusEnums::USED_STATE);
  791.             $em->persist($code);
  792.         }
  793.         $em->flush();
  794.         $resendCount 0;
  795.         foreach ($codes as $code) {
  796.             $now = new DateTime();
  797.             //TODO move to some config
  798.             if ($code->getDateCreate()->modify('+30 minutes') >= $now) {
  799.                 $resendCount++;
  800.             }
  801.         }
  802.         //TODO move to some config
  803.         if ($resendCount RegistrationStatusEnums::MAX_AUTH_ATTEMPT) {
  804.             //TODO translate this
  805.             return new JsonResponse([
  806.                 'success' => false,
  807.                 'field' => 'other',
  808.                 'error' => $translator->trans('auth.try_again_later', [], 'loyality')
  809.             ]);
  810.         }
  811.         //TODO move to some config or use service
  812.         $otpRandCode random_int(111111999999);
  813.         $userData->setOtp($otpRandCode);
  814.         $userData->setOtpExpDate((new DateTime())->modify('+1 hour'));
  815.         $em->persist($userData);
  816.         $em->flush();
  817.         $otpEntity = new Otp();
  818.         $otpEntity->setCode($otpRandCode);
  819.         $otpEntity->setState(RegistrationStatusEnums::CREATED_STATE);
  820.         $otpEntity->setDateCreate(new DateTime());
  821.         $otpEntity->setUser($user);
  822.         $otpEntity->setPhone($userData->getPhone());
  823.         $em->persist($otpEntity);
  824.         $em->flush();
  825.         //TODO translate this
  826.         $infobipSmsSender->sendSms($userData->getPhone(), 'Ваш код для відновлення: ' $otpEntity->getCode());
  827.         //TODO translate this
  828.         $message =
  829.             'Ми відправили вам за номером телефону ' .
  830.             $this->getSecurePhone($userData->getPhone()) .
  831.             ' або в viber тимчасовий пароль';
  832.         return new JsonResponse([
  833.             'success' => true,
  834.             'message' => $message,
  835.             'code' => $otpEntity->getId()
  836.         ]);
  837.     }
  838.     public function setRecoveryPassword(Request                     $requestTranslatorInterface $translator,
  839.                                         UserPasswordHasherInterface $encoderAuthService $authService): JsonResponse
  840.     {
  841.         $recoveryPassword $request->get('recoveryPassword');
  842.         $codeId $request->get('code');
  843.         $userCode $request->get('userCode');
  844.         $user null;
  845.         $login $request->get('email');
  846.         if ($request->get('loginPhone') === 'true') {
  847.             $login $this->preparePhone($login);
  848.             $user $this->em
  849.                 ->getRepository(User::class)
  850.                 ->findByPhoneOrCardNum($loginnullnull);
  851.         } else {
  852.             $user $this->em
  853.                 ->getRepository(User::class)
  854.                 ->findByPhoneOrCardNum(nullnull$login);
  855.         }
  856.         if (!$user) {
  857.             return new JsonResponse(['success' => false'error' => 'Виникла помилка']);
  858.         }
  859.         $userData $this->em->getRepository(User::class)->find($user);
  860.         $em $this->em;
  861.         $code $em->getRepository(Otp::class)->find($codeId);
  862.         if (!$code || $code->getUser() != $user) {
  863.             return new JsonResponse([
  864.                 'success' => false,
  865.                 'error' => $translator->trans('auth.error_old_code', [], 'loyality'),
  866.             ]);
  867.         }
  868.         if ($userCode != $code->getCode() || $userCode != $userData->getOtp()) {
  869.             return new JsonResponse([
  870.                 'success' => false,
  871.                 'error' => $translator->trans('auth.error_code', [], 'loyality'),
  872.             ]);
  873.         }
  874.         if ($userData->getOtpExpDate() < (new DateTime)) {
  875.             return new JsonResponse([
  876.                 'success' => false,
  877.                 'error' => $translator->trans('auth.error_old_code', [], 'loyality'),
  878.             ]);
  879.         }
  880.         $userData->setPassword($encoder->hashPassword($user$recoveryPassword));
  881.         $em->persist($userData);
  882.         $em->flush();
  883.         return $authService->loginUser($user);
  884.     }
  885.     public function sendRecoverEmail(Request $requestRouterInterface $router): JsonResponse
  886.     {
  887.         $email $request->request->get('email');
  888.         $userModel $this->userModel;
  889.         if (!$userModel->initByEmail($email)) {
  890.             $regUrl $router->generate('my_register_page');
  891.             return $this->errorResponce('Користувача з таким E-mail не знайдено. <br>' .
  892.                 'Перевірте адресу або <a href="' $regUrl '" class="upper-reg">зареєструйтесь</a>.');
  893.         }
  894.         $userModel->sendRestoreEmail();
  895.         return new JsonResponse(['success' => true]);
  896.     }
  897.     public function checkUser()
  898.     {
  899.         return $this->baseMyRender('@My/Auth/aith-iframe.html.twig');
  900.     }
  901.     public function crossDomainAuth(): JsonResponse
  902.     {
  903.         $User $this->getUser();
  904.         if (
  905.             !$User ||
  906.             !(
  907.                 //TODO remove to som config path
  908.                 $User->hasRole('ROLE_LOYALTY_USER') ||
  909.                 $User->hasRole('ROLE_SUPER_ADMIN') ||
  910.                 $User->hasRole('ROLE_DC_MANAGER') ||
  911.                 $User->hasRole('ROLE_CONTENT_MANAGER')
  912.             )
  913.         ) {
  914.             $Response = new JsonResponse([
  915.                 'token' => false
  916.             ]);
  917.             return $Response;
  918.         }
  919.         //TODO remove to som config path
  920.         $token md5(time() . 'myvidisaltD@##@$GFQSF' $User->getId());
  921.         $AuthToken = new CrossDomainAuthToken();
  922.         $AuthToken->setDateCreate(new DateTime());
  923.         $AuthToken->setToken($token);
  924.         $AuthToken->setUser($User);
  925.         $this->em->persist($AuthToken);
  926.         $this->em->flush();
  927.         $Response = new JsonResponse([
  928.             'token' => $token
  929.         ]);
  930.         return $Response;
  931.     }
  932.     public function getCodeChangePhone(Request             $requestOtpEntityFactory $otpEntityFactory,
  933.                                        TranslatorInterface $translatorMailerInterface $mailer): JsonResponse
  934.     {
  935.         $translator->setLocale($request->getLocale());
  936.         if ($request->request->has('locale')) {
  937.             $translator->setLocale($request->get('locale'));
  938.         }
  939.         $email $request->get('email');
  940.         $user $this->em
  941.             ->getRepository(User::class)
  942.             ->findByPhoneOrCardNum(nullnull$email);
  943.         if (!$user) {
  944.             return new JsonResponse([
  945.                 'success' => false,
  946.                 'field' => 'email',
  947.                 'error' => $translator->trans('change_phone.user_not_found', [], 'loyality')
  948.             ]);
  949.         }
  950.         $codes $this->em->getRepository(Otp::class)
  951.             ->findBy(['user' => $user'state' => RegistrationStatusEnums::CREATED_STATE]);
  952.         foreach ($codes as $code) {
  953.             $now = new DateTime();
  954.             if ($code->getDateCreate()->modify('+15 minutes') <= $now) {
  955.                 $code->setState(RegistrationStatusEnums::OUTDATED_STATE);
  956.                 $this->em->persist($code);
  957.                 continue;
  958.             }
  959.             $code->setState(RegistrationStatusEnums::USED_STATE);
  960.             $this->em->persist($code);
  961.         }
  962.         $this->em->flush();
  963.         $resendCount 0;
  964.         foreach ($codes as $code) {
  965.             $now = new DateTime();
  966.             if ($code->getDateCreate()->modify('+30 minutes') >= $now) {
  967.                 $resendCount++;
  968.             }
  969.         }
  970.         if ($resendCount RegistrationStatusEnums::MAX_AUTH_ATTEMPT) {
  971.             return new JsonResponse([
  972.                 'success' => false,
  973.                 'field' => 'other',
  974.                 'error' => $translator->trans('auth.try_again_later', [], 'loyality')
  975.             ]);
  976.         }
  977.         $otpEntity $otpEntityFactory->createOtp($user);
  978.         $user->setOtp($otpEntity->getCode());
  979.         $user->setOtpExpDate((new DateTime())->modify('+1 hour'));
  980.         $this->em->persist($otpEntity);
  981.         $this->em->persist($user);
  982.         $this->em->flush();
  983.         $mailMessage $translator->trans('change_phone.mail_message', [], 'loyality');
  984.         $mailBody $this->twig->render('@My/Mail/change_phone_email.html.twig', [
  985.             'user' => $user,
  986.             'message' => $mailMessage
  987.         ]);
  988.         $message = (new Email())
  989.             ->subject($translator->trans('change_phone.mail_subject', [], 'loyality'))
  990.             ->from(new Address('info@vidi.ua'$translator->trans('change_phone.mail_name_from', [], 'loyality')))
  991.             ->html($mailBody)
  992.             ->to($email);
  993.         $mailer->send($message);
  994.         return new JsonResponse([
  995.             'success' => true,
  996.             'message' => $translator->trans(
  997.                 'change_phone.email_sending_to',
  998.                 ['%email%' => $user->getEmail()],
  999.                 'loyality'
  1000.             ),
  1001.             'code' => $otpEntity->getId()
  1002.         ]);
  1003.     }
  1004.     public function setNewPhone(
  1005.         Request             $request,
  1006.         OtpEntityFactory    $otpEntityFactory,
  1007.         AuthDataValidator   $validator,
  1008.         LoggerInterface     $logger,
  1009.         AuthCodeDTOFactory  $DTOFactory,
  1010.         TranslatorInterface $translator,
  1011.         InfobipSmsSender    $infobipSmsSender
  1012.     ): JsonResponse
  1013.     {
  1014.         $translator->setLocale($request->getLocale());
  1015.         if ($request->request->has('locale')) {
  1016.             $translator->setLocale($request->get('locale'));
  1017.         }
  1018.         $code $request->get('userCode');
  1019.         $data $request->request->all();
  1020.         try {
  1021.             $validator->validateForSetNewPhone($data);
  1022.             $authDTO $DTOFactory->createWithEmailAndPhoneProperties($data);
  1023.         } catch (DataNotValidException|UserNotFoundException $e) {
  1024.             $logger->error('auth.error'$data);
  1025.             return new JsonResponse([
  1026.                 'success' => false,
  1027.                 'error' => $translator->trans('auth.error', [], 'loyality')
  1028.             ]);
  1029.         }
  1030.         if ($authDTO->user->getOtp() != $code || $authDTO->user->getOtpExpDate() < (new DateTime)) {
  1031.             return new JsonResponse([
  1032.                 'success' => false,
  1033.                 'field' => 'code',
  1034.                 'error' => $translator->trans('auth.error_code', [], 'loyality'),
  1035.             ]);
  1036.         }
  1037.         if (
  1038.             $this->em
  1039.                 ->getRepository(User::class)
  1040.                 ->findByPhoneOrCardNum($authDTO->phonenullnull)
  1041.         ) {
  1042.             return new JsonResponse([
  1043.                 'success' => false,
  1044.                 'field' => 'phone',
  1045.                 'error' => $translator->trans('change_phone.not_unique_phone', [], 'loyality'),
  1046.             ]);
  1047.         }
  1048.         //set new phone to user
  1049.         $authDTO->user->setPhoneNew($authDTO->phone);
  1050.         $em $this->em;
  1051.         $usedOtp $em->getRepository(Otp::class)->findOneBy(['user' => $authDTO->user], ['id' => 'DESC']);
  1052.         //outdated current otp to avoid user block
  1053.         $usedOtp->setState(RegistrationStatusEnums::OUTDATED_STATE);
  1054.         //new OTP for sending to new user phone
  1055.         $otpEntity $otpEntityFactory->createOtpPhoneNew($authDTO->user);
  1056.         $authDTO->user->setOtp($otpEntity->getCode());
  1057.         $authDTO->user->setOtpExpDate((new DateTime())->modify('+1 hour'));
  1058.         $em->persist($usedOtp);
  1059.         $em->persist($authDTO->user);
  1060.         $em->persist($otpEntity);
  1061.         $em->flush();
  1062.         $infobipSmsSender->sendSms(
  1063.             $authDTO->user->getPhoneNew(),
  1064.             $translator->trans('auth.your_auth_code', ['%code%' => $otpEntity->getCode()], 'loyality')
  1065.         );
  1066.         return new JsonResponse([
  1067.             'success' => true,
  1068.             'code' => $otpEntity->getId(),
  1069.             'email' => $authDTO->user->getEmail(),
  1070.         ]);
  1071.     }
  1072.     private function preparePhone($phone)
  1073.     {
  1074.         return substr(preg_replace('~[^0-9]+~'''$phone), -10);
  1075.     }
  1076.     private function checkAttemptLogin(User $userEntityManagerInterface $em$loginAuthService $authService): bool
  1077.     {
  1078.         $lastAttempt $em->getRepository(AttemptLogin::class)
  1079.             ->findOneBy(['user' => $user], ['id' => 'DESC']);
  1080.         if ($lastAttempt && $lastAttempt->getState()) {
  1081.             $dateBlocked $lastAttempt->getCreatedAt()->modify('5 minutes');
  1082.             if ($dateBlocked->getTimestamp() < (new DateTime)->getTimestamp()) {
  1083.                 $authService->clearHistoryAttemptLogin($user);
  1084.             }
  1085.         }
  1086.         $attempts $em->getRepository(AttemptLogin::class)
  1087.             ->findBy(['user' => $user]);
  1088.         if (count($attempts) < RegistrationStatusEnums::MAX_AUTH_ATTEMPT_BEFORE_BLOCK) {
  1089.             $attemptLogin = new AttemptLogin();
  1090.             $attemptLogin->setCreatedAt(new DateTime());
  1091.             $attemptLogin->setLogin($login);
  1092.             $attemptLogin->setState(RegistrationStatusEnums::CREATED_STATE);
  1093.             $attemptLogin->setUser($user);
  1094.             $em->persist($attemptLogin);
  1095.             $em->flush();
  1096.             return true;
  1097.         }
  1098.         $lastAttempt->setState(RegistrationStatusEnums::ACTIVE_STATE);
  1099.         $em->persist($lastAttempt);
  1100.         $em->flush();
  1101.         return false;
  1102.     }
  1103.     private function errorResponce($errors): JsonResponse
  1104.     {
  1105.         return new JsonResponse(['success' => false'errors' => $errors]);
  1106.     }
  1107.     private function getSecurePhone($phone): string
  1108.     {
  1109.         //TODO move to config or service
  1110.         return '+380...' mb_substr($phone, -46);
  1111.     }
  1112. }