src/Security/GoogleAuthenticator.php line 178

Open in your IDE?
  1. <?php
  2. namespace App\Security;
  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\Entity\UserConnection;
  9. use App\Service\RoutingService;
  10. use App\Service\Tools;
  11. use App\Service\UserService;
  12. use App\Service\UserDefaultDataService;
  13. use DateTime;
  14. use Doctrine\ORM\EntityManagerInterface;
  15. use Google\Cloud\Core\Exception\ServiceException;
  16. use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
  17. use KnpU\OAuth2ClientBundle\Client\OAuth2ClientInterface;
  18. use KnpU\OAuth2ClientBundle\Security\Authenticator\SocialAuthenticator;
  19. use League\OAuth2\Client\Provider\GoogleUser;
  20. use Stripe\Exception\ApiErrorException;
  21. use Symfony\Bridge\Twig\Mime\TemplatedEmail;
  22. use Symfony\Component\DependencyInjection\ContainerInterface;
  23. use Symfony\Component\HttpFoundation\RedirectResponse;
  24. use Symfony\Component\HttpFoundation\Request;
  25. use Symfony\Component\HttpFoundation\Response;
  26. use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
  27. use Symfony\Component\Mailer\MailerInterface;
  28. use Symfony\Component\Mime\Address;
  29. use Symfony\Component\Routing\RouterInterface;
  30. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  31. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  32. use Symfony\Component\Security\Core\Exception\BadCredentialsException;
  33. use Symfony\Component\Security\Core\User\UserProviderInterface;
  34. use Symfony\Contracts\Translation\TranslatorInterface;
  35. class GoogleAuthenticator extends SocialAuthenticator
  36. {
  37.     private ClientRegistry $clientRegistry;
  38.     private EntityManagerInterface $em;
  39.     private RouterInterface $router;
  40.     private TranslatorInterface $translator;
  41.     private Tools $tools;
  42.     private UserService $userService;
  43.     private UserDefaultDataService $userDefaultDataService;
  44.     private RoutingService $routingService;
  45.     private MailerInterface $mailer;
  46.     private ContainerInterface $container;
  47.     public function __construct(
  48.         ClientRegistry $clientRegistry,
  49.         EntityManagerInterface $em,
  50.         RouterInterface $router,
  51.         TranslatorInterface $translator,
  52.         Tools $tools,
  53.         UserService $userService,
  54.         UserDefaultDataService $userDefaultDataService,
  55.         RoutingService $routingService,
  56.         MailerInterface $mailer,
  57.         ContainerInterface $container
  58.     ) {
  59.         $this->clientRegistry $clientRegistry;
  60.         $this->em $em;
  61.         $this->router $router;
  62.         $this->translator $translator;
  63.         $this->tools $tools;
  64.         $this->userService $userService;
  65.         $this->userDefaultDataService $userDefaultDataService;
  66.         $this->routingService $routingService;
  67.         $this->mailer $mailer;
  68.         $this->container $container;
  69.     }
  70.     /**
  71.      * @param Request $request
  72.      * @return bool
  73.      */
  74.     public function supports(Request $request)
  75.     {
  76.         return 'api_security_google_check' === $request->attributes->get('_route')
  77.             && $request->isMethod('GET');
  78.     }
  79.     /**
  80.      * @param $credentials
  81.      * @param UserProviderInterface $userProvider
  82.      * @return User
  83.      * @throws TransportExceptionInterface
  84.      */
  85.     public function getUser($credentialsUserProviderInterface $userProvider): User
  86.     {
  87.         /** @var GoogleUser $googleUser */
  88.         $googleUser $this->getGoogleClient()->fetchUserFromToken($credentials);
  89.         $email $googleUser->getEmail();
  90.         /** @var User $existingUser */
  91.         $existingUser $this->em->getRepository(User::class)->findOneBy(['googleId' => $googleUser->getId()]);
  92.         if ($existingUser) {
  93.             if (!$existingUser->isActive()) {
  94.                 throw new BadCredentialsException('user_disabled');
  95.             }
  96.             if (!$existingUser->isValidated()) {
  97.                 throw new BadCredentialsException('user_not_validated');
  98.             }
  99.             if ($existingUser->getProfile()->getRole() !== Profile::ROLE_CUSTOMER) {
  100.                 throw new BadCredentialsException('bad_user');
  101.             }
  102.             return $existingUser;
  103.         }
  104.         /** @var User $user */
  105.         $user $this->em->getRepository(User::class)->findOneBy(['email' => $email]);
  106.         if (!$user) {
  107.             /** @var Profile $profile */
  108.             $profile $this->em->getRepository(Profile::class)->findOneBy(['role' => Profile::ROLE_CUSTOMER]);
  109.             /** @var Setting $setting */
  110.             $setting $this->em->getRepository(Setting::class)->findOneBy(['name' => 'FREE_SMS_PER_MONTH']);
  111.             $user = new User();
  112.             $user->setEmail($googleUser->getEmail());
  113.             $user->setUsername($googleUser->getName());
  114.             $user->setGoogleId($googleUser->getId());
  115.             $user->setProfile($profile);
  116.             $user->setHash($this->tools->generateRandomString(20));
  117.             $user->setValidated(true);
  118.             $user->setSmsRemaining($setting->getValue());
  119.             $institution = new Institution();
  120.             $institution->setIsDefault(true);
  121.             $institution->setName('Mon restaurant');
  122.             $institution->setUser($user);
  123.             $institution->setHash($this->tools->generateRandomString(20));
  124.             $pdfmenuPersonalization = new PdfmenuPersonalization();
  125.             $institution->setPdfmenuPersonalization($pdfmenuPersonalization);
  126.             $this->userService->setDefaultDataOnRegistration($institution);
  127.             $user->addInstitution($institution);
  128.             $this->em->persist($user);
  129.             $this->em->persist($pdfmenuPersonalization);
  130.             $this->em->flush();
  131.             $this->userService->generateQRCodeInstitution($institution);
  132.             $message = (new TemplatedEmail())
  133.                 ->from(new Address($this->container->getParameter('MAILER_FROM'), $this->container->getParameter('MAILER_FROM_NAME')))
  134.                 ->to($user->getEmail())
  135.                 ->subject($this->translator->trans('registrationSocial.title', [], 'email'))
  136.                 ->htmlTemplate('front/emails/registration_social.html.twig')
  137.                 ->context([
  138.                     'userEmail' => $user->getEmail(),
  139.                 ]);
  140.             $this->mailer->send($message);
  141.         } else {
  142.             $user->setGoogleId($googleUser->getId());
  143.             $user->setRegistrationValidationToken(null);
  144.             $user->setRegistrationValidationRequestAt(null);
  145.             $user->setValidated(true);
  146.             $this->em->persist($user);
  147.             $this->em->flush();
  148.         }
  149.         return $user;
  150.     }
  151.     public function getCredentials(Request $request)
  152.     {
  153.         return $this->fetchAccessToken($this->getGoogleClient());
  154.     }
  155.     /**
  156.      * @return OAuth2ClientInterface
  157.      */
  158.     private function getGoogleClient(): OAuth2ClientInterface
  159.     {
  160.         return $this->clientRegistry->getClient('google');
  161.     }
  162.     /**
  163.      * @param Request $request
  164.      * @param AuthenticationException|null $authException
  165.      * @return string|Response
  166.      */
  167.     public function start(Request $requestAuthenticationException $authException null): string|Response
  168.     {
  169.         return $this->router->generate('api_security_login');
  170.     }
  171.     /**
  172.      * @param Request $request
  173.      * @param AuthenticationException $exception
  174.      * @return RedirectResponse
  175.      */
  176.     public function onAuthenticationFailure(Request $requestAuthenticationException $exception): RedirectResponse
  177.     {
  178.         return new RedirectResponse($route $this->routingService->generate('login') . '?s=' $exception->getMessage());
  179.     }
  180.     /**
  181.      * @param Request $request
  182.      * @param TokenInterface $token
  183.      * @param $providerKey
  184.      * @return RedirectResponse
  185.      * @throws ApiErrorException
  186.      * @throws ServiceException
  187.      */
  188.     public function onAuthenticationSuccess(Request $requestTokenInterface $token$providerKey): RedirectResponse
  189.     {
  190.         /** @var User $user */
  191.         $user $token->getUser();
  192.         $this->userDefaultDataService->setDefaultCategories($user);
  193.         $user->setLastConnection(new DateTime());
  194.         $userConnection = new UserConnection();
  195.         $userConnection->setUser($user);
  196.         $userConnection->setConnectionAt(new DateTime());
  197.         $user->addUserConnection($userConnection);
  198.         $hasCookieCart $this->userService->checkHaveCookieCart($request$user);
  199.         $this->userService->checkIsValideSubscription($user);
  200.         $this->em->flush();
  201.         $response = new RedirectResponse($this->routingService->generate('login'));
  202.         if ($hasCookieCart) {
  203.             $response->headers->clearCookie('cart');
  204.         }
  205.         return $response;
  206.     }
  207. }