src/Controller/Api/SecurityController.php line 131

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Api;
  3. use App\Entity\Institution;
  4. use App\Entity\PdfmenuPersonalization;
  5. use App\Entity\Profile;
  6. use App\Entity\Setting;
  7. use App\Entity\User;
  8. use App\Service\RoutingService;
  9. use App\Service\Rsa;
  10. use App\Service\Tools;
  11. use App\Service\UserService;
  12. use DateTime;
  13. use Doctrine\ORM\EntityManagerInterface;
  14. use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
  15. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  16. use Symfony\Bridge\Twig\Mime\TemplatedEmail;
  17. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  18. use Symfony\Component\Config\Definition\Exception\Exception;
  19. use Symfony\Component\HttpFoundation\JsonResponse;
  20. use Symfony\Component\HttpFoundation\RedirectResponse;
  21. use Symfony\Component\HttpFoundation\Request;
  22. use Symfony\Component\HttpFoundation\Response;
  23. use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
  24. use Symfony\Component\Mailer\MailerInterface;
  25. use Symfony\Component\Mime\Address;
  26. use Symfony\Component\Routing\Annotation\Route;
  27. use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
  28. use Symfony\Contracts\Translation\TranslatorInterface;
  29. /**
  30.  * Class AppController
  31.  * @package App\Controller\Api
  32.  * @Route(path="/api/security", name="api_security_")
  33.  */
  34. class SecurityController extends AbstractController
  35. {
  36.     private EntityManagerInterface $em;
  37.     private TranslatorInterface $translator;
  38.     private MailerInterface $mailer;
  39.     private UserPasswordEncoderInterface $passwordEncoder;
  40.     private UserService $userService;
  41.     private Tools $tools;
  42.     private RoutingService $routingService;
  43.     private Rsa $rsa;
  44.     public function __construct(
  45.         EntityManagerInterface $em,
  46.         TranslatorInterface $translator,
  47.         MailerInterface $mailer,
  48.         UserPasswordEncoderInterface $passwordEncoder,
  49.         UserService $userService,
  50.         Tools $tools,
  51.         RoutingService $routingService,
  52.         Rsa $rsa
  53.     ) {
  54.         $this->em $em;
  55.         $this->translator $translator;
  56.         $this->mailer $mailer;
  57.         $this->passwordEncoder $passwordEncoder;
  58.         $this->userService $userService;
  59.         $this->tools $tools;
  60.         $this->routingService $routingService;
  61.         $this->rsa $rsa;
  62.     }
  63.     /**
  64.      * @return Response
  65.      * @Route("/login", name="login")
  66.      */
  67.     public function login(): Response
  68.     {
  69.         return new JsonResponse([
  70.             'success' => false,
  71.         ]);
  72.     }
  73.     /**
  74.      * @throws Exception
  75.      * @Route("/logout", name="logout")
  76.      */
  77.     public function logout(): void
  78.     {
  79.         throw new Exception('This should never be reached!');
  80.     }
  81.     /**
  82.      * @param Request $request
  83.      * @return JsonResponse
  84.      * @Route("/user", name="user")
  85.      * @IsGranted("IS_AUTHENTICATED_FULLY")
  86.      */
  87.     public function user(Request $request): JsonResponse
  88.     {
  89.         if (!$this->rsa->isValidToken($request->request->get('apiKey'))) {
  90.             return new JsonResponse([
  91.                 'success' => false,
  92.                 'message' => $this->translator->trans('global.invalidToken'),
  93.             ]);
  94.         }
  95.         /** @var User $user */
  96.         $user $this->getUser();
  97.         if (!is_null($user)) {
  98.             return new JsonResponse([
  99.                 'success' => true,
  100.             ]);
  101.         }
  102.         return new JsonResponse([
  103.             'success' => false,
  104.         ]);
  105.     }
  106.     /**
  107.      * @param ClientRegistry $clientRegistry
  108.      * @return RedirectResponse
  109.      * @Route("/google/connect", name="google_connect")
  110.      */
  111.     public function googleConnect(ClientRegistry $clientRegistry): RedirectResponse
  112.     {
  113.         return $clientRegistry->getClient('google')->redirect();
  114.     }
  115.     /**
  116.      * @return RedirectResponse
  117.      * @Route("/google/check", name="google_check")
  118.      */
  119.     public function googleCheck(): RedirectResponse
  120.     {
  121.         return $this->redirectToRoute('api_security_login');
  122.     }
  123.     /**
  124.      * @param ClientRegistry $clientRegistry
  125.      * @return RedirectResponse
  126.      * @Route("/facebook/connect", name="facebook_connect")
  127.      */
  128.     public function facebookConnect(ClientRegistry $clientRegistry): RedirectResponse
  129.     {
  130.         return $clientRegistry->getClient('facebook')->redirect();
  131.     }
  132.     /**
  133.      * @return RedirectResponse
  134.      * @Route("/facebook/check", name="facebook_check")
  135.      */
  136.     public function facebookCheck(): RedirectResponse
  137.     {
  138.         return $this->redirectToRoute('api_security_login');
  139.     }
  140.     /**
  141.      * @param Request $request
  142.      * @return JsonResponse
  143.      * @throws \Exception
  144.      * @throws TransportExceptionInterface
  145.      * @Route("/password/reset", name="password_reset")
  146.      */
  147.     public function passwordReset(Request $request): JsonResponse
  148.     {
  149.         if (!$this->rsa->isValidToken($request->request->get('apiKey'))) {
  150.             return new JsonResponse([
  151.                 'success' => false,
  152.                 'message' => $this->translator->trans('global.invalidToken'),
  153.             ]);
  154.         }
  155.         $data Tools::getRequestData($request);
  156.         $recaptchaToken $data['recaptchaToken'];
  157.         $response json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=" $this->getParameter('RECAPTCHA_PRIVATE_KEY') . "&response=" $recaptchaToken "&remoteip=" $_SERVER['REMOTE_ADDR']), true);
  158.         if ($response['success']) {
  159.             $email $data['email'];
  160.             /** @var User $user */
  161.             $user $this->em->getRepository(User::class)->findOneBy(['email' => $email]);
  162.             if ($user) {
  163.                 $user->setPasswordToken($this->tools->generateRandomString(50));
  164.                 $user->setPasswordRequestAt(new DateTime());
  165.                 $this->em->flush();
  166.                 $message = (new TemplatedEmail())
  167.                     ->from(new Address($this->getParameter('MAILER_FROM'), $this->getParameter('MAILER_FROM_NAME')))
  168.                     ->to($user->getEmail())
  169.                     ->subject($this->translator->trans('passwordReset.title', [], 'email'))
  170.                     ->htmlTemplate('front/emails/password_reset.html.twig')
  171.                     ->context([
  172.                         'urlReset' => $this->routingService->generate('password_reset_token', ['token' => $user->getPasswordToken()], true)
  173.                     ]);
  174.                 $this->mailer->send($message);
  175.                 return new JsonResponse([
  176.                     'success' => true,
  177.                     'message' => $this->translator->trans('security.passwordReset', ['%email%' => $user->getEmail()], 'messages'),
  178.                 ]);
  179.             }
  180.             return new JsonResponse([
  181.                 'success' => true,
  182.                 'message' => $this->translator->trans('security.passwordReset', ['%email%' => $email], 'messages'),
  183.             ]);
  184.         }
  185.         return new JsonResponse([
  186.             'success' => false,
  187.             'message' => $this->translator->trans('global.notRobot'),
  188.         ]);
  189.     }
  190.     /**
  191.      * @param Request $request
  192.      * @return JsonResponse|RedirectResponse|Response
  193.      * @throws \Exception
  194.      * @Route("/password/reset/token", name="password_reset_token")
  195.      */
  196.     public function passwordResetToken(Request $request): RedirectResponse|JsonResponse|Response
  197.     {
  198.         if (!$this->rsa->isValidToken($request->request->get('apiKey'))) {
  199.             return new JsonResponse([
  200.                 'success' => false,
  201.                 'message' => $this->translator->trans('global.invalidToken'),
  202.             ]);
  203.         }
  204.         $data Tools::getRequestData($request);
  205.         $token $data['token'];
  206.         /** @var User $user */
  207.         $user $this->em->getRepository(User::class)->findOneBy(['passwordToken' => $token]);
  208.         if (!is_null($user)) {
  209.             $now = new DateTime();
  210.             $interval $now->diff($user->getPasswordRequestAt());
  211.             $totalMinutes = ($interval->24 60) + ($interval->60) + $interval->i;
  212.             if ($totalMinutes 60) {
  213.                 $plainPassword null;
  214.                 if (array_key_exists('password'$data)) {
  215.                     $plainPassword $data['password'];
  216.                 }
  217.                 $passwordConfirm null;
  218.                 if (array_key_exists('passwordConfirm'$data)) {
  219.                     $passwordConfirm $data['passwordConfirm'];
  220.                 }
  221.                 if ($plainPassword and $passwordConfirm) {
  222.                     $recaptchaToken $data['recaptchaToken'];
  223.                     $response json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=" $this->getParameter('RECAPTCHA_PRIVATE_KEY') . "&response=" $recaptchaToken "&remoteip=" $_SERVER['REMOTE_ADDR']), true);
  224.                     if ($response['success']) {
  225.                         if ($plainPassword === $passwordConfirm) {
  226.                             $checkPasswordStrengths $this->userService->checkPasswordStrength($plainPassword);
  227.                             if (count($checkPasswordStrengths) == 0) {
  228.                                 $password $this->passwordEncoder->encodePassword($user$plainPassword);
  229.                                 $user->setPassword($password);
  230.                                 $user->setPasswordToken(null);
  231.                                 $user->setPasswordRequestAt(null);
  232.                                 $this->em->flush();
  233.                                 return new JsonResponse([
  234.                                     'success' => true,
  235.                                     'message' => $this->translator->trans('security.passwordResetToken.success', ['%url%' => $this->routingService->generate('login')]),
  236.                                 ]);
  237.                             }
  238.                             return new JsonResponse([
  239.                                 'success' => false,
  240.                                 'message' => $checkPasswordStrengths,
  241.                             ]);
  242.                         }
  243.                         return new JsonResponse([
  244.                             'success' => false,
  245.                             'message' => $this->translator->trans('authenticator.passwordMismatch'),
  246.                         ]);
  247.                     }
  248.                     return new JsonResponse([
  249.                         'success' => false,
  250.                         'message' => $this->translator->trans('global.notRobot'),
  251.                     ]);
  252.                 }
  253.                 return new JsonResponse([
  254.                     'success' => true,
  255.                 ]);
  256.             }
  257.             return new JsonResponse([
  258.                 'success' => false,
  259.                 'message' => $this->translator->trans('security.passwordResetToken.tokenExpired', ['%url%' => $this->routingService->generate('password_reset')]),
  260.             ]);
  261.         }
  262.         return new JsonResponse([
  263.             'success' => false,
  264.             'message' => $this->translator->trans('security.passwordResetToken.tokenNotFound'),
  265.         ]);
  266.     }
  267.     /**
  268.      * @param Request $request
  269.      * @return JsonResponse
  270.      * @throws \Exception
  271.      * @throws TransportExceptionInterface
  272.      * @Route("/registration", name="registration")
  273.      */
  274.     public function registration(Request $request): JsonResponse
  275.     {
  276.         if (!$this->rsa->isValidToken($request->request->get('apiKey'))) {
  277.             return new JsonResponse([
  278.                 'success' => false,
  279.                 'message' => $this->translator->trans('global.invalidToken'),
  280.             ]);
  281.         }
  282.         $data Tools::getRequestData($request);
  283.         $email $data['email'];
  284.         $plainPassword $data['password'];
  285.         $passwordConfirm $data['passwordConfirm'];
  286.         /** @var User $user */
  287.         $user $this->em->getRepository(User::class)->findOneByEmail($email);
  288.         if (is_null($user)) {
  289.             if ($plainPassword and $passwordConfirm) {
  290.                 if ($plainPassword === $passwordConfirm) {
  291.                     $checkPasswordStrengths $this->userService->checkPasswordStrength($plainPassword);
  292.                     if (count($checkPasswordStrengths) == 0) {
  293.                         $user = new User();
  294.                         $user->setEmail($email);
  295.                         /** @var Profile $profile */
  296.                         $profile $this->em->getRepository(Profile::class)->findOneByRole(Profile::ROLE_CUSTOMER);
  297.                         /** @var Setting $setting */
  298.                         $setting $this->em->getRepository(Setting::class)->findOneBy(['name' => 'FREE_SMS_PER_MONTH']);
  299.                         $user->setProfile($profile);
  300.                         $password $this->passwordEncoder->encodePassword($user$plainPassword);
  301.                         $user->setPassword($password);
  302.                         $user->setHash($this->tools->generateRandomString(20));
  303.                         $user->setRegistrationValidationToken($this->tools->generateRandomString(50));
  304.                         $user->setRegistrationValidationRequestAt(new DateTime());
  305.                         $user->setSmsRemaining($setting->getValue());
  306.                         $institution = new Institution();
  307.                         $institution->setIsDefault(true);
  308.                         $institution->setName('Mon restaurant');
  309.                         $institution->setUser($user);
  310.                         $institution->setHash($this->tools->generateRandomString(20));
  311.                         $pdfmenuPersonalization = new PdfmenuPersonalization();
  312.                         $institution->setPdfmenuPersonalization($pdfmenuPersonalization);
  313.                         $this->userService->setDefaultDataOnRegistration($institution);
  314.                         $user->addInstitution($institution);
  315.                         $this->em->persist($user);
  316.                         $this->em->persist($pdfmenuPersonalization);
  317.                         $this->em->flush();
  318.                         $this->userService->generateQRCodeInstitution($institution);
  319.                         $message = (new TemplatedEmail())
  320.                             ->from(new Address($this->getParameter('MAILER_FROM'), $this->getParameter('MAILER_FROM_NAME')))
  321.                             ->to($user->getEmail())
  322.                             ->subject($this->translator->trans('registration.title', [], 'email'))
  323.                             ->htmlTemplate('front/emails/registration.html.twig')
  324.                             ->context([
  325.                                 'userEmail' => $user->getEmail(),
  326.                                 'urlValidation' => $this->routingService->generate('registration_validation', ['token' => $user->getRegistrationValidationToken()], true),
  327.                             ]);
  328.                         $this->mailer->send($message);
  329.                         return new JsonResponse([
  330.                             'success' => true,
  331.                             'message' => $this->translator->trans('registration.success', ['%url%' => $this->routingService->generate('login')]),
  332.                         ]);
  333.                     }
  334.                     return new JsonResponse([
  335.                         'success' => false,
  336.                         'message' => $checkPasswordStrengths,
  337.                     ]);
  338.                 }
  339.                 return new JsonResponse([
  340.                     'success' => false,
  341.                     'message' => $this->translator->trans('authenticator.passwordMismatch'),
  342.                 ]);
  343.             }
  344.             return new JsonResponse([
  345.                 'success' => false,
  346.             ]);
  347.         }
  348.         return new JsonResponse([
  349.             'success' => false,
  350.             'message' => $this->translator->trans('registration.userExist', ['%url%' => $this->routingService->generate('password_reset')]),
  351.         ]);
  352.     }
  353.     /**
  354.      * @param Request $request
  355.      * @return JsonResponse
  356.      * @throws \Exception
  357.      * @Route("/registration/validation", name="registration_validation")
  358.      */
  359.     public function registrationValidation(Request $request): JsonResponse
  360.     {
  361.         if (!$this->rsa->isValidToken($request->request->get('apiKey'))) {
  362.             return new JsonResponse([
  363.                 'success' => false,
  364.                 'message' => $this->translator->trans('global.invalidToken'),
  365.             ]);
  366.         }
  367.         $data Tools::getRequestData($request);
  368.         $token $data['token'];
  369.         /** @var User $user */
  370.         $user $this->em->getRepository(User::class)->findOneBy(['registrationValidationToken' => $token]);
  371.         if (!is_null($user)) {
  372.             $now = new DateTime();
  373.             $interval $now->diff($user->getRegistrationValidationRequestAt());
  374.             $totalMinutes = ($interval->24 60) + ($interval->60) + $interval->i;
  375.             if ($totalMinutes 120) {
  376.                 $user->setValidated(true);
  377.                 $user->setRegistrationValidationToken(null);
  378.                 $user->setRegistrationValidationRequestAt(null);
  379.                 $this->em->persist($user);
  380.                 $this->em->flush();
  381.                 return new JsonResponse([
  382.                     'success' => true,
  383.                     'message' => $this->translator->trans('registration.validation.success', ['%url%' => $this->routingService->generate('login')]),
  384.                 ]);
  385.             }
  386.             return new JsonResponse([
  387.                 'success' => false,
  388.                 'message' => $this->translator->trans('registration.validation.tokenExpired', ['%url%' => $this->routingService->generate('registration_validation_email', ['token' => $token])]),
  389.             ]);
  390.         }
  391.         return new JsonResponse([
  392.             'success' => false,
  393.             'message' => $this->translator->trans('registration.validation.tokenNotFound'),
  394.         ]);
  395.     }
  396.     /**
  397.      * @param Request $request
  398.      * @return JsonResponse
  399.      * @throws \Exception
  400.      * @throws TransportExceptionInterface
  401.      * @Route("/registration/validation/email", name="registration_validation_email")
  402.      */
  403.     public function registrationValidationEmail(Request $request): JsonResponse
  404.     {
  405.         if (!$this->rsa->isValidToken($request->request->get('apiKey'))) {
  406.             return new JsonResponse([
  407.                 'success' => false,
  408.                 'message' => $this->translator->trans('global.invalidToken'),
  409.             ]);
  410.         }
  411.         $data Tools::getRequestData($request);
  412.         $token $data['token'];
  413.         /** @var User $user */
  414.         $user $this->em->getRepository(User::class)->findOneBy(['registrationValidationToken' => $token]);
  415.         if (!is_null($user)) {
  416.             $now = new DateTime();
  417.             $interval $now->diff($user->getRegistrationValidationRequestAt());
  418.             $totalMinutes intval(($interval->24 60) + ($interval->60) + $interval->i);
  419.             if ($totalMinutes 60) {
  420.                 $user->setRegistrationValidationToken($this->tools->generateRandomString(50));
  421.                 $user->setRegistrationValidationRequestAt(new DateTime());
  422.                 $this->em->persist($user);
  423.                 $this->em->flush();
  424.                 $message = (new TemplatedEmail())
  425.                     ->from(new Address($this->getParameter('MAILER_FROM'), $this->getParameter('MAILER_FROM_NAME')))
  426.                     ->to($user->getEmail())
  427.                     ->subject($this->translator->trans('registrationEmail.title', [], 'email'))
  428.                     ->htmlTemplate('front/emails/registration_email.html.twig')
  429.                     ->context([
  430.                         'urlValidation' => $this->routingService->generate('registration_validation', ['token' => $user->getRegistrationValidationToken()], true),
  431.                     ]);
  432.                 $this->mailer->send($message);
  433.                 return new JsonResponse([
  434.                     'success' => true,
  435.                     'message' => $this->translator->trans('registration.validationEmail.success'),
  436.                 ]);
  437.             }
  438.             return new JsonResponse([
  439.                 'success' => false,
  440.                 'message' => $this->translator->trans('registration.validationEmail.tokenAlreadySent'),
  441.             ]);
  442.         }
  443.         return new JsonResponse([
  444.             'success' => false,
  445.             'message' => $this->translator->trans('registration.validationEmail.tokenNotFound'),
  446.         ]);
  447.     }
  448. }