- <?php
- namespace MyBundle\Controller;
- use CoreBundle\Entity\User;
- use CoreBundle\Repository\UserRepository;
- use DateTime;
- use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
- use Doctrine\ORM\EntityManagerInterface;
- use MyBundle\Component\InfobipSmsSender;
- use MyBundle\Entity\AttemptLogin;
- use MyBundle\Entity\CrossDomainAuthToken;
- use MyBundle\Entity\Otp;
- use MyBundle\Entity\RegisterRequest;
- use MyBundle\Entity\UserReferral;
- use MyBundle\Enum\AuthDataKeys;
- use MyBundle\Enum\RegistrationStatusEnums;
- use MyBundle\Exception\DataNotValidException;
- use MyBundle\Exception\UserNotFoundException;
- use MyBundle\Factory\AuthCodeDTOFactory;
- use MyBundle\Factory\OtpCodeGenerator;
- use MyBundle\Factory\OtpEntityFactory;
- use MyBundle\Factory\RegUserDTOFactory;
- use MyBundle\Factory\StringGenerator;
- use MyBundle\Factory\UserEntityFactory;
- use MyBundle\Messages;
- use MyBundle\Service\AuthDataValidator;
- use MyBundle\Service\AuthService;
- use Psr\Log\LoggerInterface;
- use Symfony\Component\HttpFoundation\JsonResponse;
- use Symfony\Component\HttpFoundation\RedirectResponse;
- use Symfony\Component\HttpFoundation\Request;
- use Symfony\Component\HttpFoundation\RequestStack;
- use Symfony\Component\HttpFoundation\Response;
- use Symfony\Component\HttpFoundation\Session\SessionInterface;
- use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
- use Symfony\Component\Mailer\MailerInterface;
- use Symfony\Component\Mime\Address;
- use Symfony\Component\Mime\Email;
- use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
- use Symfony\Component\Routing\RouterInterface;
- use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
- use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
- use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
- use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
- use Symfony\Component\Security\Http\Util\TargetPathTrait;
- use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
- use Symfony\Contracts\Translation\TranslatorInterface;
- use Twig\Environment;
- class AuthController extends MyBaseController
- {
-     use TargetPathTrait;
-     private SessionInterface $session;
-     private TokenStorageInterface $tokenStorage;
-     public function __construct(EntityManagerInterface $em, RequestStack $requestStack, Messages $messages,
-                                 \CoreBundle\Model\User $userModel, SessionInterface $session,
-                                 TokenStorageInterface  $tokenStorage, Environment $twig)
-     {
-         parent::__construct($em, $requestStack, $messages, $userModel, $twig);
-         $this->session = $session;
-         $this->tokenStorage = $tokenStorage;
-     }
-     public function logout(AuthService $authService): RedirectResponse
-     {
-         if ($this->getUser()) {
-             $authService->logoutUser($this->getUser());
-         }
-         return $this->redirectToRoute('my_login_page');
-     }
-     public function resendSms(Request $request): JsonResponse
-     {
-         $hash = $request->get('hash');
-         if (!$this->userModel->initByHash($hash)) {
-             return $this->errorResponce(['total' => 'Виникла помилка, будь ласка, спробуйте ще раз пізніше']);
-         }
-         if ($this->userModel->sendConfirmSms()) {
-             return new JsonResponse(['success' => true, 'phone' => $this->userModel->getPhone()]);
-         }
-         return $this->errorResponce(['total' => 'Ви використали всі спроби доставки sms']);
-     }
-     public function confirmPhone(Request $request)
-     {
-         $hash = $request->request->get('hash');
-         if (!$this->userModel->initByHash($hash)) {
-             return new JsonResponse(['success' => false]);
-         }
-         $code = $request->request->get('code');
-         if (!$this->userModel->checkConfirmPhone($code)) {
-             return new JsonResponse(['success' => false]);
-         }
-         $this->userModel->senConfirmEmail();
-         return new JsonResponse(['success' => true, 'hash' => $hash]);
-     }
-     public function reSendEmail(Request $request): JsonResponse
-     {
-         $hash = $request->get('hash');
-         if (!$this->userModel->initByHash($hash)) {
-             return new JsonResponse(['success' => false]);
-         }
-         $this->userModel->senConfirmEmail();
-         return new JsonResponse(['success' => true]);
-     }
-     public function confirmEmail(Request $request): ?Response
-     {
-         if (!$this->userModel->initByHash($request->get('hash'))) {
-             throw new NotFoundHttpException();
-         }
-         return $this->baseMyRender('@My/Auth/confirm_email.html.twig', [
-             'user' => $this->userModel->getUser()
-         ]);
-     }
-     public function finish($userHash, $hash): ?Response
-     {
-         $success = false;
-         if ($this->userModel->initByHash($userHash)) {
-             $success = $this->userModel->confirmEmail($hash);
-         }
-         return $this->baseMyRender(
-             '@My/Auth/finish_register.html.twig',
-             ['success' => $success, 'ehash' => $this->userModel->getUser()->getEmailHash(), 'hash' => $this->userModel->getHash()]
-         );
-     }
-     public function setPassword(Request $request, EventDispatcherInterface $eventDispatcher): JsonResponse
-     {
-         $hash = $request->get('userHash');
-         if (!$this->userModel->initByHash($hash)) {
-             return new JsonResponse(['success' => false]);
-         }
-         $emailHash = $request->request->get('ehash');
-         if ($emailHash != $this->userModel->getUser()->getEmailHash()) {
-             return new JsonResponse(['success' => false]);
-         }
-         $password = $request->request->get('password');
-         $this->userModel->setPassword($password);
-         $token = new UsernamePasswordToken($this->userModel->getUser(), null, 'prifile', $this->userModel->getUser()->getRoles());
-         $this->tokenStorage->setToken($token);
-         $this->session->set('_security_prifile', serialize($token));
-         $event = new InteractiveLoginEvent($request, $token);
-         //TODO refactor this to correct dispatcher
-         $eventDispatcher->dispatch($event, "security.interactive_login");
-         return new JsonResponse(['success' => true]);
-     }
-     public function recover($hash, $ehash)
-     {
-         if (!$this->userModel->initByHash($hash)) {
-             throw $this->createAccessDeniedException();
-         }
-         if ($ehash != $this->userModel->getUser()->getEmailHash()) {
-             throw $this->createAccessDeniedException();
-         }
-         return $this->baseMyRender('@My/Auth/recover_pass.html.twig', [
-             'hash' => $hash,
-             'ehash' => $ehash,
-         ]);
-     }
-     public function loginCheck(Request $request, AuthService $authService, EncoderFactoryInterface $factory): JsonResponse
-     {
-         $phone = $request->request->get('phone');
-         $phone = substr(preg_replace('~[^0-9]+~', '', $phone), -10);
-         $_password = $request->get('password');
-         $cardNumber = $request->request->get('card');
-         $cardNumber = preg_replace('~[^0-9]+~', '', $cardNumber);
-         $login = $request->get('login');
-         if ($login) {
-             $user = $this->em->getRepository(User::class)->findOneBy(['username' => $login]);
-         } else {
-             $user = $this->em->getRepository(User::class)->findByPhoneOrCardNum($phone, $cardNumber);
-         }
-         if (!$user) {
-             return new JsonResponse(['success' => false, 'error' => 'account is not found']);
-         }
-         $encoder = $factory->getEncoder($user);
-         $salt = $user->getSalt();
-         if (!$encoder->isPasswordValid($user->getPassword(), $_password, $salt)) {
-             return new JsonResponse(['success' => false, 'error' => 'password wrong']);
-         }
-         $this->userModel->pushReferrer($request, $user, User::UTM_LOGIN);
-         return $authService->loginUser($user);
-     }
-     public function login(Request $request, EventDispatcherInterface $eventDispatcher, RouterInterface $router, AuthService $authService): RedirectResponse|Response|null
-     {
-         if ($this->getUser()) {
-             $referer = $authService->getRefererUser($request, $this->getUser());
-             if ($referer) {
-                 return $this->redirect($referer);
-             }
-         }
-         $url = $this->getTargetPath($request->getSession(), 'main');
-         if ($this->getUser() && !$referer) {
-             return $this->redirect($router->generate('my_about_car_page'));
-         }
-         $tokenStr = $request->query->get('token');
-         if ($tokenStr) {
-             $AuthToken =
-                 $this->em
-                     ->getRepository(CrossDomainAuthToken::class)
-                     ->findOneBy(['token' => $tokenStr]);
-             if (!$AuthToken) {
-                 return $this->baseMyRender('@My/Auth/login.html.twig');
-             }
-             $now = new DateTime();
-             $tokenCreateDate = $AuthToken->getDateCreate();
-             //TODO remove to some config
-             if ($tokenCreateDate < $now->modify('-30 min')) {
-                 return $this->baseMyRender('@My/Auth/login.html.twig');
-             }
-             $user = $AuthToken->getUser();
-             $token = new UsernamePasswordToken($user, null, 'profile', $user->getRoles());
-             $this->tokenStorage->setToken($token);
-             $this->session->set('_security_profile', serialize($token));
-             $event = new InteractiveLoginEvent($request, $token);
-             //TODO refactor this to correct dispatcher
-             $eventDispatcher->dispatch($event, "security.interactive_login");
-             $this->em->remove($AuthToken);
-             $this->em->flush();
-             return $this->redirect($request->headers->get('referer'));
-         }
-         return $this->baseMyRender('@My/Auth/login.html.twig', [
-             'backLoginUrl' => $url
-         ]);
-     }
-     public function register(
-         Request             $request,
-         AuthDataValidator   $validator,
-         LoggerInterface     $logger,
-         UserEntityFactory   $userEntityFactory,
-         RegUserDTOFactory   $userDTOFactory,
-         OtpCodeGenerator    $codeGenerator,
-         TranslatorInterface $translator
-     ): JsonResponse
-     {
-         $translator->setLocale($request->getLocale());
-         if ($request->request->has('locale')) {
-             $translator->setLocale($request->get('locale'));
-         }
-         $data = $request->request->all();
-         try {
-             $validator->validateForRegisterUser($data);
-         } catch (DataNotValidException $e) {
-             $logger->error($e->getMessage(), $data);
-             return new JsonResponse([
-                 'success' => false,
-                 'message' => $translator->trans('auth.error', [], 'loyality'),
-             ]);
-         }
-         $userRegDTO = $userDTOFactory->createDefaultAuthDTO($data);
-         /** @var UserRepository $users */
-         $users = $this->em->getRepository(User::class);
-         $userCount = $users->checkRegisteredUsersByParams(
-             [
-                 'phone' => $userRegDTO->phone,
-                 'email' => $userRegDTO->email
-             ]
-         );
-         if ($userCount) {
-             return new JsonResponse([
-                 'success' => false,
-                 'message' => $translator->trans('auth.duplicate_email_or_phone', [], 'loyality'),
-             ]);
-         }
-         $registerRequest = new RegisterRequest();
-         $registerRequest->setDateCreate(new DateTime());
-         $registerRequest->setPhone($userRegDTO->phone);
-         $registerRequest->setRequest(json_encode($data));
-         $registerRequest->setIsComplete(false);
-         $this->em->persist($registerRequest);
-         $this->em->flush();
-         $otp = $codeGenerator->generate();
-         $registerRequest->setOtp($otp);
-         $registerRequest->setOtpExpDate((new DateTime())->modify('+1 hour'));
-         try {
-             $em = $this->em;
-             $em->persist($registerRequest);
-             $em->flush();
-         } catch (UniqueConstraintViolationException $ex) {
-             return new JsonResponse([
-                 'success' => false,
-                 'message' => $translator->trans('auth.duplicate_email', [], 'loyality'),
-             ]);
-         }
-         return new JsonResponse([
-             'success' => true,
-             'requestId' => $registerRequest->getId(),
-             'message' => $translator->trans(
-                 'auth.sending_to_phone_succeed',
-                 ['%phone%' => $this->getSecurePhone($registerRequest->getPhone())],
-                 'loyality'
-             ),
-         ]);
-     }
-     public function getCode(
-         Request             $request,
-         AuthDataValidator   $validator,
-         LoggerInterface     $logger,
-         AuthCodeDTOFactory  $DTOFactory,
-         OtpEntityFactory    $otpEntityFactory,
-         UserEntityFactory   $userEntityFactory,
-         RegUserDTOFactory   $userDTOFactory,
-         TranslatorInterface $translator,
-         InfobipSmsSender    $infobipSmsSender,
-         AuthService $authService
-     ): JsonResponse
-     {
-         $data = $request->request->all();
-         $phone = substr(preg_replace('~[^0-9]+~', '', $data[AuthDataKeys::EMAIL]), -10);
-         if ($request->request->get('loginPhone') == 'false') {
-             $email = $request->request->get('email');
-             $userAuth = $DTOFactory->getUserByEmail($email);
-         } else {
-             $userAuth = $DTOFactory->getUserByPhone($phone);
-         }
-         $requestId = $request->get('requestId');
-         if (!$userAuth && $requestId) {
-             $RegisterRequest = $this->em->getRepository(RegisterRequest::class)->find($requestId);
-             if (!$RegisterRequest) {
-                 return new JsonResponse(['success' => false, 'error' => $translator->trans('auth.error', [], 'loyality')]);
-             }
-             $requestData = json_decode($RegisterRequest->getRequest());
-             $requestEmail = $requestData->email;
-             if (($phone != '' && $RegisterRequest->getPhone() != $phone) || ($email && $requestEmail != $email)) {
-                 return new JsonResponse(['success' => false, 'error' => $translator->trans('auth.error', [], 'loyality')]);
-             }
-             $em = $this->em;
-             $dataRegister = json_decode($RegisterRequest->getRequest(), true);
-             $userRegDTO = $userDTOFactory->createDefaultAuthDTO($dataRegister);
-             $user = $userEntityFactory->createUser($userRegDTO);
-             $user->setIsLoyalty(UserEntityFactory::LOYALTY_STATUS_DEFAULT);
-             $user->setEnabled(UserEntityFactory::ENABLED_STATUS);
-             $user->setRegistrationConfirm(UserEntityFactory::REGISTRATION_STATUS_CONFIRMED);
-             $user->setConfirmedPhone(UserEntityFactory::REGISTRATION_STATUS_CONFIRMED);
-             //TODO move to some config
-             if (!$user->hasRole('ROLE_LOYALTY_USER')) {
-                 $user->addRole('ROLE_LOYALTY_USER');
-             }
-             if (!$user->getPhone()) {
-                 $user->setPhone($phone);
-             }
-             $RegisterRequest->setIsComplete(1);
-             $RegisterRequest->setUser($user);
-             $em->persist($user);
-             $em->persist($RegisterRequest);
-             $em->flush();
-             $this->userModel->pushReferrer($request, $user, User::UTM_REGISTRATION);
-         }
-         $translator->setLocale($request->getLocale());
-         if ($request->request->has('locale')) {
-             $translator->setLocale($request->get('locale'));
-         }
-         try {
-             $validator->validateGetCodeData($data);
-             $authDTO = $DTOFactory->createWithLoginPropertyOnly($data);
-         } catch (DataNotValidException $e) {
-             $logger->error($e->getMessage(), $data);
-             return new JsonResponse([
-                 'success' => false,
-                 'field' => 'other',
-                 'error' => $translator->trans('auth.error', [], 'loyality'),
-             ]);
-         } catch (UserNotFoundException $e) {
-             $logger->critical($e->getMessage(), $data);
-             return new JsonResponse([
-                 'success' => false,
-                 'field' => 'other',
-                 'error' => $translator->trans('auth.user_not_found', [], 'loyality'),
-             ]);
-         }
-         $em = $this->em;
-         if (!$this->checkAttemptLogin($authDTO->user, $em, $authDTO->login, $authService)) {
-             return new JsonResponse([
-                 'success' => false,
-                 'field' => 'other',
-                 'error' => $translator->trans('auth.access_denied', [], 'loyality'),
-             ]);
-         }
-         $codes = $em->getRepository(Otp::class)
-             ->findBy(['user' => $authDTO->user, 'state' => RegistrationStatusEnums::CREATED_STATE]);
- // todo remove when realise what this number are
-         $now = new DateTime();
-         foreach ($codes as $code) {
-             //TODO move to config
-             if ($code->getDateCreate()->modify('+15 minutes') <= $now) {
-                 /** @var Otp $code */
-                 $code->setState(RegistrationStatusEnums::OUTDATED_STATE);
- //$code->setState(3); todo remove when realise what this number are
-                 $em->persist($code);
-                 $em->flush();
-                 continue;
-             }
-             $code->setState(RegistrationStatusEnums::USED_STATE);
- //$code->setState(4); todo remove when realise what this number are
-             $em->persist($code);
-             $em->flush();
-         }
-         $resendCount = 0;
-         foreach ($codes as $code) {
-             if ($code->getDateCreate()->modify('+30 minutes') >= $now) {
-                 $resendCount++;
-             }
-         }
-         if ($resendCount > RegistrationStatusEnums::MAX_AUTH_ATTEMPT) {
-             return new JsonResponse([
-                 'success' => false,
-                 'field' => 'other',
-                 'error' => $translator->trans('auth.try_again_later', [], 'loyality')
-             ]);
-         }
-         $otpEntity = $otpEntityFactory->createOtp($authDTO->user);
-         $authDTO->user->setOtp($otpEntity->getCode());
-         $authDTO->user->setOtpExpDate((new DateTime())->modify('+1 hour'));
-         $em->persist($otpEntity);
-         $em->persist($authDTO->user);
-         $em->flush();
-         if ($authDTO->user->getPhone() == null || strlen($authDTO->user->getPhone()) < User::MIN_LENGTH_PHONE) {
-             $message = $translator->trans(
-                 'auth.phone_send_error',
-                 ['%phone%' => $this->getSecurePhone($authDTO->user->getPhone())],
-                 'loyality'
-             );
-             return new JsonResponse([
-                 'success' => false,
-                 'field' => 'brokenPhone',
-                 'error' => $message,
-             ]);
-         }
-         $infobipSmsSender->sendSms(
-             $authDTO->user->getPhone(),
-             $translator->trans('auth.your_auth_code', ['%code%' => $otpEntity->getCode()], 'loyality')
-         );
-         return new JsonResponse([
-             'success' => true,
-             'phone' => $authDTO->user->getPhone(),
-             'message' => $translator->trans(
-                 'auth.sending_to_phone_succeed',
-                 ['%phone%' => $this->getSecurePhone($authDTO->user->getPhone())],
-                 'loyality'
-             ),
-             'code' => $otpEntity->getId(),
-         ]);
-     }
-     public function resendRegistrationCode(Request             $request, OtpEntityFactory $otpEntityFactory,
-                                            TranslatorInterface $translator, InfobipSmsSender $infobipSmsSender): JsonResponse
-     {
-         $translator->setLocale($request->getLocale());
-         if ($request->request->has('locale')) {
-             $translator->setLocale($request->get('locale'));
-         }
-         $data = $request->request->all();
-         $requestId = $data['requestId'];
-         $RegisterRequest = $this->em->getRepository(RegisterRequest::class)->find($requestId);
-         //TODO move to config or service
-         $phone = substr(preg_replace('~[^0-9]+~', '', $data['phone']), -10);
-         if (!$RegisterRequest || $RegisterRequest->getPhone() != $phone) {
-             return new JsonResponse([
-                 'success' => false,
-                 'field' => 'other',
-                 'error' => $translator->trans('auth.error', [], 'loyality'),
-             ]);
-         }
-         $em = $this->em;
-         $codes = $em->getRepository(Otp::class)
-             ->findBy(['request' => $RegisterRequest, 'state' => RegistrationStatusEnums::CREATED_STATE]);
-         $now = new DateTime();
-         foreach ($codes as $code) {
-             /** @var Otp $code */
-             //TODO move to config
-             if ($code->getDateCreate()->modify('+15 minutes') <= $now) {
-                 $code->setState(RegistrationStatusEnums::OUTDATED_STATE);
-                 $em->persist($code);
-                 $em->flush();
-                 continue;
-             }
-             $code->setState(RegistrationStatusEnums::USED_STATE);
-             $em->persist($code);
-             $em->flush();
-         }
-         $resendCount = 0;
-         foreach ($codes as $code) {
-             if ($code->getDateCreate()->modify('+30 minutes') >= $now) {
-                 $resendCount++;
-             }
-         }
-         if ($resendCount > RegistrationStatusEnums::MAX_AUTH_ATTEMPT) {
-             return new JsonResponse([
-                 'success' => false,
-                 'field' => 'other',
-                 'error' => $translator->trans('auth.try_again_later', [], 'loyality')
-             ]);
-         }
-         $otpEntity = $otpEntityFactory->createOtpByRequest($RegisterRequest);
-         $RegisterRequest->setOtp($otpEntity->getCode());
-         $RegisterRequest->setOtpExpDate((new DateTime())->modify('+1 hour'));
-         $em->persist($otpEntity);
-         $em->persist($RegisterRequest);
-         $em->flush();
-         $infobipSmsSender->sendSms(
-             $RegisterRequest->getPhone(),
-             $translator->trans('auth.your_auth_code', ['%code%' => $otpEntity->getCode()], 'loyality')
-         );
-         return new JsonResponse([
-             'success' => true,
-             'phone' => $RegisterRequest->getPhone(),
-             'message' => $translator->trans(
-                 'auth.sending_to_phone_succeed',
-                 ['%phone%' => $this->getSecurePhone($RegisterRequest->getPhone())],
-                 'loyality'
-             ),
-             'code' => $otpEntity->getId(),
-         ]);
-     }
-     public function confirmRegistration(
-         Request             $request,
-         UserEntityFactory   $userEntityFactory,
-         RegUserDTOFactory   $userDTOFactory,
-         TranslatorInterface $translator,
-         AuthService $authService
-     ): JsonResponse
-     {
-         $requestId = $request->get('requestId');
-         $code = $request->get('code');
-         $phone = $request->get('phone');
-         //TODO move to config or service
-         $phone = substr(preg_replace('~[^0-9]+~', '', $phone), -10);
-         $RegisterRequest = $this->em->getRepository(RegisterRequest::class)->find($requestId);
-         if (!$RegisterRequest || $RegisterRequest->getPhone() != $phone) {
-             return new JsonResponse(['success' => false, 'error' => $translator->trans('auth.error', [], 'loyality')]);
-         }
-         $em = $this->em;
-         if ($RegisterRequest->getOtp() == $code && $RegisterRequest->getOtpExpDate() > (new DateTime)) {
-             $data = json_decode($RegisterRequest->getRequest(), true);
-             $userRegDTO = $userDTOFactory->createDefaultAuthDTO($data);
-             $user = $userEntityFactory->createUser($userRegDTO);
-             $user->setIsLoyalty(UserEntityFactory::LOYALTY_STATUS_DEFAULT);
-             $user->setEnabled(UserEntityFactory::ENABLED_STATUS);
-             $user->setRegistrationConfirm(UserEntityFactory::REGISTRATION_STATUS_CONFIRMED);
-             $user->setConfirmedPhone(UserEntityFactory::REGISTRATION_STATUS_CONFIRMED);
-             //TODO move to some config
-             if (!$user->hasRole('ROLE_LOYALTY_USER')) {
-                 $user->addRole('ROLE_LOYALTY_USER');
-             }
-             if (!$user->getPhone()) {
-                 $user->setPhone($phone);
-             }
-             $RegisterRequest->setIsComplete(1);
-             $RegisterRequest->setUser($user);
-             $em->persist($user);
-             $em->persist($RegisterRequest);
-             $em->flush();
-             $this->userModel->pushReferrer($request, $user, User::UTM_REGISTRATION);
-             return $authService->loginUser($user);
-         }
-         return new JsonResponse(['success' => false, 'error' => 'Не вiрний код']);
-     }
-     public function referralRegister(
-         Request                     $request,
-         OtpCodeGenerator            $codeGenerator,
-         StringGenerator             $stringGenerator,
-         TranslatorInterface         $translator,
-         UserPasswordHasherInterface $encoder,
-         InfobipSmsSender            $infobipSmsSender
-     ): JsonResponse
-     {
-         $translator->setLocale($request->getLocale());
-         if ($request->request->has('locale')) {
-             $translator->setLocale($request->get('locale'));
-         }
-         $email = $request->get('email');
-         $password = $stringGenerator->generateUpperCaseAndNumbers();
-         $phone = $request->get('phone');
-         $users = $this->em->getRepository(User::class);
-         if ($users->checkRegisteredUsersByParams(['email' => $email])) {
-             return new JsonResponse([
-                 'success' => false,
-                 'error' => $translator->trans('register.email_already_in_use', [], 'loyality'),
-             ]);
-         }
-         $user = $users->findByPhoneOrCardNum($phone);
-         if (!$user) {
-             return new JsonResponse([
-                 'success' => false,
-                 'error' => $translator->trans('register.user_register_problem', [], 'loyality'),
-             ]);
-         }
-         /** @var User $user */
-         $referrerUser = $this->em
-             ->getRepository(UserReferral::class)->findOneBy(['user_id' => $user->getId()]);
-         $em = $this->em;
-         if ($user && $user->getRegistrationConfirm()) {
-             return new JsonResponse([
-                 'success' => false,
-                 'error' => $translator->trans('register.user_already_register', [], 'loyality'),
-             ]);
-         }
-         $otp = $codeGenerator->generate();
-         $user->setRegistrationConfirm(UserEntityFactory::REGISTRATION_STATUS_DEFAULT);
-         $user->setEmail($email);
-         $user->setEnabled(UserEntityFactory::ENABLED_STATUS);
-         $user->setIsLoyalty(UserEntityFactory::LOYALTY_STATUS_DEFAULT);
-         $user->setUsername($email);
-         $user->setEmailCanonical($email);
-         $user->setPassword($encoder->hashPassword($user, $password));
-         $user->setOtp($otp);
-         //TODO move to some config
-         $user->setOtpExpDate((new DateTime())->modify('+1 hour'));
-         $user->setReferrer($referrerUser->getPromoCode());
-         $user->setConfirmPhoneCod($otp);
-         $em->persist($user);
-         try {
-             $em->flush();
-         } catch (UniqueConstraintViolationException $ex) {
-             return new JsonResponse([
-                 'success' => false,
-                 'error' => $translator->trans('register.main_problem', [], 'loyality'),
-             ]);
-         }
-         $infobipSmsSender->sendSms(
-             $phone,
-             $translator->trans('register.your_code_for_registration', ['%code%' => $otp], 'loyality')
-         );
-         return new JsonResponse([
-             'success' => true,
-             'message' => $translator->trans(
-                 'auth.sending_to_phone_succeed',
-                 ['%phone%' => $this->getSecurePhone($phone)],
-                 'loyality'
-             ),
-         ]);
-     }
-     public function referralRegisterConfirm(Request $request, AuthService $authService): JsonResponse
-     {
-         $code = $request->get('code');
-         $phone = $request->get('phone');
-         $em = $this->em;
-         /** @var User $user */
-         if (!($user = $this->em->getRepository(User::class)->findByPhoneOrCardNum($phone))) {
-             //TODO translate this
-             return new JsonResponse(
-                 [
-                     'success' => false,
-                     'error' => 'Користувача не знайдено, зверніться до адміністратора'
-                 ]
-             );
-         }
-         $ReferralUser = $this->em->getRepository(UserReferral::class)
-             ->findOneBy(['user_id' => $user->getId(), 'promo_code' => $user->getReferrer()]);
-         if (!$ReferralUser) {
-             //TODO translate this
-             return new JsonResponse(
-                 [
-                     'success' => false,
-                     'error' => 'Користувача не знайдено, зверніться до адміністратора'
-                 ]
-             );
-         }
-         $ReferralUser->setStatus(UserReferral::STATUS_REGISTERED);
-         $em->persist($ReferralUser);
-         $em->flush();
-         if ($user->getOtp() == $code && $user->getOtpExpDate() > (new DateTime)) {
-             $user->setIsLoyalty(1);
-             $user->setEnabled(1);
-             $user->setRegistrationConfirm(1);
-             $user->setConfirmedPhone(1);
-             //TODO move to some config
-             if (!$user->hasRole('ROLE_LOYALTY_USER')) {
-                 $user->addRole('ROLE_LOYALTY_USER');
-             }
-             if (!$user->getPhone()) {
-                 $user->setPhone($phone);
-             }
-             $em->persist($user);
-             $em->flush();
-             $this->userModel->pushReferrer($request, $user, User::UTM_REGISTRATION);
-             return $authService->loginUser($user);
-         }
-         return new JsonResponse(['success' => false, 'error' => 'Не вірний код']);
-     }
-     public function recoveryConfirmCode(Request $request): JsonResponse
-     {
-         $codeId = $request->get('code');
-         $userCode = $request->get('userCode');
-         $user = null;
-         $login = $request->get('email');
-         if ($request->get('loginPhone') === 'true') {
-             $login = $this->preparePhone($login);
-             $user = $this->em
-                 ->getRepository(User::class)
-                 ->findByPhoneOrCardNum($login, null, null);
-         } else {
-             $user = $this->em
-                 ->getRepository(User::class)
-                 ->findByPhoneOrCardNum(null, null, $login);
-         }
-         $userData = null;
-         //TODO translate this
-         if (!$user) {
-             return new JsonResponse([
-                 'success' => false,
-                 'error' => 'Користувача з таким email та паролем не знайдено',
-             ]);
-         } else {
-             $userData = $this->em->getRepository(User::class)->find($user);
-         }
-         $em = $this->em;
-         $code = $em->getRepository(Otp::class)->find($codeId);
-         if (!$code || $code->getUser() != $user) {
-             //TODO translate this
-             return new JsonResponse([
-                 'success' => false,
-                 'error' => 'Ваш код прострочений, будь ласка, отримаєте новий код'
-             ]);
-         }
-         if ($userCode != $code->getCode() || $userCode != $userData->getOtp()) {
-             //TODO translate this
-             return new JsonResponse([
-                 'success' => false,
-                 'error' => 'Невірний код'
-             ]);
-         }
-         if ($userData->getOtpExpDate() < (new DateTime)) {
-             //TODO translate this
-             return new JsonResponse([
-                 'success' => false,
-                 'error' => 'Термін дії коду закінчився. Вам необхідно запросити новий код відновлення',
-             ]);
-         }
-         return new JsonResponse(['success' => true]);
-     }
-     public function codeLogin(Request $request, TranslatorInterface $translator, AuthService $authService): JsonResponse
-     {
-         $translator->setLocale($request->getLocale());
-         if ($request->request->has('locale')) {
-             $translator->setLocale($request->get('locale'));
-         }
-         $user = $this->getUser();
-         if ($user) {
-             $authService->logoutUser($user);
-         }
-         return $authService->verifyAuthUser();
-     }
-     public function codeLoginNewPhone(Request $request, TranslatorInterface $translator, AuthService $authService): JsonResponse
-     {
-         $translator->setLocale($request->getLocale());
-         if ($request->request->has('locale')) {
-             $translator->setLocale($request->get('locale'));
-         }
-         $user = $this->getUser();
-         if ($user) {
-             $authService->logoutUser($user);
-         }
-         return $authService->verifyAuthNewPhoneUser();
-     }
-     public function getCodeRecovery(Request $request, TranslatorInterface $translator, InfobipSmsSender $infobipSmsSender): JsonResponse
-     {
-         $translator->setLocale($request->getLocale());
-         if ($request->request->has('locale')) {
-             $translator->setLocale($request->get('locale'));
-         }
-         $user = null;
-         $login = $request->get('email');
-         if ($request->get('loginPhone') === 'true') {
-             $login = $this->preparePhone($login);
-             $user = $this->em
-                 ->getRepository(User::class)
-                 ->findByPhoneOrCardNum($login, null, null);
-         } else {
-             $user = $this->em
-                 ->getRepository(User::class)
-                 ->findByPhoneOrCardNum(null, null, $login);
-         }
-         $userData = null;
-         if (!$user) {
-             return new JsonResponse([
-                 'success' => false,
-                 'error' => $translator->trans('recovery.user_not_found', [], 'loyality')
-             ]);
-         } else {
-             //WTF??
-             $userData = $this->em->getRepository(User::class)->find($user);
-         }
-         $em = $this->em;
-         $codes =
-             $em->getRepository(Otp::class)
-                 ->findBy(['user' => $user, 'state' => RegistrationStatusEnums::CREATED_STATE]);
-         foreach ($codes as $code) {
-             $now = new DateTime();
-             if ($code->getDateCreate()->modify('+15 minutes') <= $now) {
- //                $code->setState(3);
-                 $code->setState(RegistrationStatusEnums::OUTDATED_STATE);
-                 $em->persist($code);
-                 continue;
-             }
- //            $code->setState(4);
-             $code->setState(RegistrationStatusEnums::USED_STATE);
-             $em->persist($code);
-         }
-         $em->flush();
-         $resendCount = 0;
-         foreach ($codes as $code) {
-             $now = new DateTime();
-             //TODO move to some config
-             if ($code->getDateCreate()->modify('+30 minutes') >= $now) {
-                 $resendCount++;
-             }
-         }
-         //TODO move to some config
-         if ($resendCount > RegistrationStatusEnums::MAX_AUTH_ATTEMPT) {
-             //TODO translate this
-             return new JsonResponse([
-                 'success' => false,
-                 'field' => 'other',
-                 'error' => $translator->trans('auth.try_again_later', [], 'loyality')
-             ]);
-         }
-         //TODO move to some config or use service
-         $otpRandCode = random_int(111111, 999999);
-         $userData->setOtp($otpRandCode);
-         $userData->setOtpExpDate((new DateTime())->modify('+1 hour'));
-         $em->persist($userData);
-         $em->flush();
-         $otpEntity = new Otp();
-         $otpEntity->setCode($otpRandCode);
-         $otpEntity->setState(RegistrationStatusEnums::CREATED_STATE);
-         $otpEntity->setDateCreate(new DateTime());
-         $otpEntity->setUser($user);
-         $otpEntity->setPhone($userData->getPhone());
-         $em->persist($otpEntity);
-         $em->flush();
-         //TODO translate this
-         $infobipSmsSender->sendSms($userData->getPhone(), 'Ваш код для відновлення: ' . $otpEntity->getCode());
-         //TODO translate this
-         $message =
-             'Ми відправили вам за номером телефону ' .
-             $this->getSecurePhone($userData->getPhone()) .
-             ' або в viber тимчасовий пароль';
-         return new JsonResponse([
-             'success' => true,
-             'message' => $message,
-             'code' => $otpEntity->getId()
-         ]);
-     }
-     public function setRecoveryPassword(Request                     $request, TranslatorInterface $translator,
-                                         UserPasswordHasherInterface $encoder, AuthService $authService): JsonResponse
-     {
-         $recoveryPassword = $request->get('recoveryPassword');
-         $codeId = $request->get('code');
-         $userCode = $request->get('userCode');
-         $user = null;
-         $login = $request->get('email');
-         if ($request->get('loginPhone') === 'true') {
-             $login = $this->preparePhone($login);
-             $user = $this->em
-                 ->getRepository(User::class)
-                 ->findByPhoneOrCardNum($login, null, null);
-         } else {
-             $user = $this->em
-                 ->getRepository(User::class)
-                 ->findByPhoneOrCardNum(null, null, $login);
-         }
-         if (!$user) {
-             return new JsonResponse(['success' => false, 'error' => 'Виникла помилка']);
-         }
-         $userData = $this->em->getRepository(User::class)->find($user);
-         $em = $this->em;
-         $code = $em->getRepository(Otp::class)->find($codeId);
-         if (!$code || $code->getUser() != $user) {
-             return new JsonResponse([
-                 'success' => false,
-                 'error' => $translator->trans('auth.error_old_code', [], 'loyality'),
-             ]);
-         }
-         if ($userCode != $code->getCode() || $userCode != $userData->getOtp()) {
-             return new JsonResponse([
-                 'success' => false,
-                 'error' => $translator->trans('auth.error_code', [], 'loyality'),
-             ]);
-         }
-         if ($userData->getOtpExpDate() < (new DateTime)) {
-             return new JsonResponse([
-                 'success' => false,
-                 'error' => $translator->trans('auth.error_old_code', [], 'loyality'),
-             ]);
-         }
-         $userData->setPassword($encoder->hashPassword($user, $recoveryPassword));
-         $em->persist($userData);
-         $em->flush();
-         return $authService->loginUser($user);
-     }
-     public function sendRecoverEmail(Request $request, RouterInterface $router): JsonResponse
-     {
-         $email = $request->request->get('email');
-         $userModel = $this->userModel;
-         if (!$userModel->initByEmail($email)) {
-             $regUrl = $router->generate('my_register_page');
-             return $this->errorResponce('Користувача з таким E-mail не знайдено. <br>' .
-                 'Перевірте адресу або <a href="' . $regUrl . '" class="upper-reg">зареєструйтесь</a>.');
-         }
-         $userModel->sendRestoreEmail();
-         return new JsonResponse(['success' => true]);
-     }
-     public function checkUser()
-     {
-         return $this->baseMyRender('@My/Auth/aith-iframe.html.twig');
-     }
-     public function crossDomainAuth(): JsonResponse
-     {
-         $User = $this->getUser();
-         if (
-             !$User ||
-             !(
-                 //TODO remove to som config path
-                 $User->hasRole('ROLE_LOYALTY_USER') ||
-                 $User->hasRole('ROLE_SUPER_ADMIN') ||
-                 $User->hasRole('ROLE_DC_MANAGER') ||
-                 $User->hasRole('ROLE_CONTENT_MANAGER')
-             )
-         ) {
-             $Response = new JsonResponse([
-                 'token' => false
-             ]);
-             return $Response;
-         }
-         //TODO remove to som config path
-         $token = md5(time() . 'myvidisaltD@##@$GFQSF' . $User->getId());
-         $AuthToken = new CrossDomainAuthToken();
-         $AuthToken->setDateCreate(new DateTime());
-         $AuthToken->setToken($token);
-         $AuthToken->setUser($User);
-         $this->em->persist($AuthToken);
-         $this->em->flush();
-         $Response = new JsonResponse([
-             'token' => $token
-         ]);
-         return $Response;
-     }
-     public function getCodeChangePhone(Request             $request, OtpEntityFactory $otpEntityFactory,
-                                        TranslatorInterface $translator, MailerInterface $mailer): JsonResponse
-     {
-         $translator->setLocale($request->getLocale());
-         if ($request->request->has('locale')) {
-             $translator->setLocale($request->get('locale'));
-         }
-         $email = $request->get('email');
-         $user = $this->em
-             ->getRepository(User::class)
-             ->findByPhoneOrCardNum(null, null, $email);
-         if (!$user) {
-             return new JsonResponse([
-                 'success' => false,
-                 'field' => 'email',
-                 'error' => $translator->trans('change_phone.user_not_found', [], 'loyality')
-             ]);
-         }
-         $codes = $this->em->getRepository(Otp::class)
-             ->findBy(['user' => $user, 'state' => RegistrationStatusEnums::CREATED_STATE]);
-         foreach ($codes as $code) {
-             $now = new DateTime();
-             if ($code->getDateCreate()->modify('+15 minutes') <= $now) {
-                 $code->setState(RegistrationStatusEnums::OUTDATED_STATE);
-                 $this->em->persist($code);
-                 continue;
-             }
-             $code->setState(RegistrationStatusEnums::USED_STATE);
-             $this->em->persist($code);
-         }
-         $this->em->flush();
-         $resendCount = 0;
-         foreach ($codes as $code) {
-             $now = new DateTime();
-             if ($code->getDateCreate()->modify('+30 minutes') >= $now) {
-                 $resendCount++;
-             }
-         }
-         if ($resendCount > RegistrationStatusEnums::MAX_AUTH_ATTEMPT) {
-             return new JsonResponse([
-                 'success' => false,
-                 'field' => 'other',
-                 'error' => $translator->trans('auth.try_again_later', [], 'loyality')
-             ]);
-         }
-         $otpEntity = $otpEntityFactory->createOtp($user);
-         $user->setOtp($otpEntity->getCode());
-         $user->setOtpExpDate((new DateTime())->modify('+1 hour'));
-         $this->em->persist($otpEntity);
-         $this->em->persist($user);
-         $this->em->flush();
-         $mailMessage = $translator->trans('change_phone.mail_message', [], 'loyality');
-         $mailBody = $this->twig->render('@My/Mail/change_phone_email.html.twig', [
-             'user' => $user,
-             'message' => $mailMessage
-         ]);
-         $message = (new Email())
-             ->subject($translator->trans('change_phone.mail_subject', [], 'loyality'))
-             ->from(new Address('info@vidi.ua', $translator->trans('change_phone.mail_name_from', [], 'loyality')))
-             ->html($mailBody)
-             ->to($email);
-         $mailer->send($message);
-         return new JsonResponse([
-             'success' => true,
-             'message' => $translator->trans(
-                 'change_phone.email_sending_to',
-                 ['%email%' => $user->getEmail()],
-                 'loyality'
-             ),
-             'code' => $otpEntity->getId()
-         ]);
-     }
-     public function setNewPhone(
-         Request             $request,
-         OtpEntityFactory    $otpEntityFactory,
-         AuthDataValidator   $validator,
-         LoggerInterface     $logger,
-         AuthCodeDTOFactory  $DTOFactory,
-         TranslatorInterface $translator,
-         InfobipSmsSender    $infobipSmsSender
-     ): JsonResponse
-     {
-         $translator->setLocale($request->getLocale());
-         if ($request->request->has('locale')) {
-             $translator->setLocale($request->get('locale'));
-         }
-         $code = $request->get('userCode');
-         $data = $request->request->all();
-         try {
-             $validator->validateForSetNewPhone($data);
-             $authDTO = $DTOFactory->createWithEmailAndPhoneProperties($data);
-         } catch (DataNotValidException|UserNotFoundException $e) {
-             $logger->error('auth.error', $data);
-             return new JsonResponse([
-                 'success' => false,
-                 'error' => $translator->trans('auth.error', [], 'loyality')
-             ]);
-         }
-         if ($authDTO->user->getOtp() != $code || $authDTO->user->getOtpExpDate() < (new DateTime)) {
-             return new JsonResponse([
-                 'success' => false,
-                 'field' => 'code',
-                 'error' => $translator->trans('auth.error_code', [], 'loyality'),
-             ]);
-         }
-         if (
-             $this->em
-                 ->getRepository(User::class)
-                 ->findByPhoneOrCardNum($authDTO->phone, null, null)
-         ) {
-             return new JsonResponse([
-                 'success' => false,
-                 'field' => 'phone',
-                 'error' => $translator->trans('change_phone.not_unique_phone', [], 'loyality'),
-             ]);
-         }
-         //set new phone to user
-         $authDTO->user->setPhoneNew($authDTO->phone);
-         $em = $this->em;
-         $usedOtp = $em->getRepository(Otp::class)->findOneBy(['user' => $authDTO->user], ['id' => 'DESC']);
-         //outdated current otp to avoid user block
-         $usedOtp->setState(RegistrationStatusEnums::OUTDATED_STATE);
-         //new OTP for sending to new user phone
-         $otpEntity = $otpEntityFactory->createOtpPhoneNew($authDTO->user);
-         $authDTO->user->setOtp($otpEntity->getCode());
-         $authDTO->user->setOtpExpDate((new DateTime())->modify('+1 hour'));
-         $em->persist($usedOtp);
-         $em->persist($authDTO->user);
-         $em->persist($otpEntity);
-         $em->flush();
-         $infobipSmsSender->sendSms(
-             $authDTO->user->getPhoneNew(),
-             $translator->trans('auth.your_auth_code', ['%code%' => $otpEntity->getCode()], 'loyality')
-         );
-         return new JsonResponse([
-             'success' => true,
-             'code' => $otpEntity->getId(),
-             'email' => $authDTO->user->getEmail(),
-         ]);
-     }
-     private function preparePhone($phone)
-     {
-         return substr(preg_replace('~[^0-9]+~', '', $phone), -10);
-     }
-     private function checkAttemptLogin(User $user, EntityManagerInterface $em, $login, AuthService $authService): bool
-     {
-         $lastAttempt = $em->getRepository(AttemptLogin::class)
-             ->findOneBy(['user' => $user], ['id' => 'DESC']);
-         if ($lastAttempt && $lastAttempt->getState()) {
-             $dateBlocked = $lastAttempt->getCreatedAt()->modify('5 minutes');
-             if ($dateBlocked->getTimestamp() < (new DateTime)->getTimestamp()) {
-                 $authService->clearHistoryAttemptLogin($user);
-             }
-         }
-         $attempts = $em->getRepository(AttemptLogin::class)
-             ->findBy(['user' => $user]);
-         if (count($attempts) < RegistrationStatusEnums::MAX_AUTH_ATTEMPT_BEFORE_BLOCK) {
-             $attemptLogin = new AttemptLogin();
-             $attemptLogin->setCreatedAt(new DateTime());
-             $attemptLogin->setLogin($login);
-             $attemptLogin->setState(RegistrationStatusEnums::CREATED_STATE);
-             $attemptLogin->setUser($user);
-             $em->persist($attemptLogin);
-             $em->flush();
-             return true;
-         }
-         $lastAttempt->setState(RegistrationStatusEnums::ACTIVE_STATE);
-         $em->persist($lastAttempt);
-         $em->flush();
-         return false;
-     }
-     private function errorResponce($errors): JsonResponse
-     {
-         return new JsonResponse(['success' => false, 'errors' => $errors]);
-     }
-     private function getSecurePhone($phone): string
-     {
-         //TODO move to config or service
-         return '+380...' . mb_substr($phone, -4, 6);
-     }
- }
-