src/Controller/AuthController.php line 50

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Dto\Request\DtoSaveInstructorRequest;
  4. use App\Entity\Contact;
  5. use App\Entity\Prestashop\Customers;
  6. use App\Form\ContactAskPasswordResetType;
  7. use App\Form\ContactResetType;
  8. use App\Helper\StringHelper;
  9. use App\Repository\ContactRepository;
  10. use App\Security\ConnectAsAuthenticator;
  11. use App\Security\ConnectAsAuthenticatorextends;
  12. use App\Security\WebsiteFormAuthenticator;
  13. use App\Service\ContactManager;
  14. use App\Service\InstructorService;
  15. use App\Service\LanguageManager;
  16. use App\Service\NotificationManager;
  17. use App\Service\NotificationService;
  18. use Doctrine\ORM\EntityManagerInterface;
  19. use Psr\Log\LoggerInterface;
  20. use Symfony\Component\HttpFoundation\Request;
  21. use Symfony\Component\HttpFoundation\RequestStack;
  22. use Symfony\Component\HttpFoundation\Response;
  23. use Symfony\Component\Routing\RouterInterface;
  24. use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
  25. use Symfony\Component\Security\Core\Security;
  26. use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
  27. use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  28. use Symfony\Component\Security\Http\Util\TargetPathTrait;
  29. class AuthController extends EntityController
  30. {
  31.     use TargetPathTrait;
  32.     private ContactManager $contactManager;
  33.     private LoggerInterface $logger;
  34.     /**
  35.      * ApiController constructor.
  36.      * @param EntityManagerInterface $em
  37.      * @param ContactManager $contactManager
  38.      * @param NotificationManager $notificationManager
  39.      * @param RequestStack $request
  40.      * @param LanguageManager $languageManager
  41.      */
  42.     public function __construct(EntityManagerInterface $em,
  43.                                 ContactManager $contactManager,
  44.                                 NotificationManager $notificationManager,
  45.                                 RequestStack $request,
  46.                                 LanguageManager $languageManager,
  47.                                 NotificationService $notificationService,
  48.                                 LoggerInterface $logger)
  49. //<<<<<<< HEAD
  50. //                                LanguageManager $languageManager,
  51. //                                SessionInterface $session,
  52. //                                NotificationService $notificationService)
  53. //    {
  54. //        parent::__construct($em, $notificationManager, $request, $languageManager, $session, $notificationService);
  55. //=======
  56. //                                LanguageManager $languageManager)
  57.     {
  58.         parent::__construct($em, $notificationManager, $request, $languageManager, $notificationService);
  59. //>>>>>>> 92-achat-unique
  60.         $this->contactManager = $contactManager;
  61.         $this->logger = $logger;
  62.     }
  63.     /**
  64.      * This is a form for a customer to ask to change password for the email submitted.
  65.      * Route : /password-reset
  66.      * @param Request $request
  67.      * @return Response
  68.      */
  69.     public function viewAskPasswordReset(Request $request, RouterInterface $router) : Response
  70.     {
  71.         $this->getNavigationContext($request, $router);
  72.         $emptyAccount = (new Contact())
  73.             ->setPassword('12345')
  74.             ->setRepeatedPassword('12345');
  75.         // generate the form with the email
  76.         // todo : add captcha ?
  77.         $form = $this->createForm(ContactAskPasswordResetType::class, $emptyAccount);
  78.         // Get the email from the form and process like apiAskPasswordReset
  79.         if ($request->isMethod('POST')) {
  80.             $form->submit($request->request->get($form->getName()));
  81.             // If form is correct
  82.             if ($form->isSubmitted() && $form->isValid()) {
  83.                 $email = $emptyAccount->getEmail();
  84.                 $contact = $this->contactManager->getContactByMail($email);
  85.                 // get account by mail
  86.                 if(!is_null($contact)){
  87.                     // if the user has no validity date or a old validity date
  88.                     $this->contactManager->sendResetPassword($contact, $this->language, $this->viewData["context"]);
  89.                 }
  90.                 else{
  91.                     $this->notificationManager::addError('Le compte n\'existe pas');
  92.                 }
  93.             }
  94.             else{
  95.                 // Sans isValid(), un jeton CSRF rejeté armait quand même le verrou de 24 h
  96.                 // dans sendResetPassword() alors qu'aucun e-mail n'était envoyé.
  97.                 $this->logger->error('Ask password reset form rejected', [
  98.                     'email' => $emptyAccount->getEmail(),
  99.                     'errors' => (string) $form->getErrors(true, false),
  100.                 ]);
  101.             }
  102.         }
  103.         $this->createFlashs();
  104.         $this->addViewDataObject('form', $form->createView())
  105.             ->addViewDataArray('response', $this->getMessages());
  106.         return $this->render('contact/ask_account_password_reset.html.twig',
  107.             $this->viewData
  108.         );
  109.     }
  110.     /**
  111.      * The FORM to reset password with password and repeated password
  112.      * Route : ResetPassword
  113.      * @param Request $request
  114.      * @return Response
  115.      */
  116.     public function viewResetPassword(Request $request, RouterInterface $router) : Response
  117.     {
  118.         $token = $request->query->get('token', ''); // the static + the temporary token
  119.         //test data = 86ae4cbe2a4650d7fa91655948c6e5de38ba907fdd0eff7ea4085efc7a780dd3
  120.         $this->getNavigationContext($request, $router);
  121.         if(empty($token) || strlen($token) !== 128){
  122.             $this->notificationManager::addError('Utilisateur non valable');
  123. //            $this->notificationManager::addError('86ae4cbe2a4650d7fa91655948c6e5de38ba907fdd0eff7ea4085efc7a780dd3' . $this->getTemporaryAccessToken('toto@toto.com'));
  124.         }
  125.         else{
  126.             $staticToken = substr($token, 0, 64); // The account static token
  127.             $currentAccount = $this->contactManager->getContactByStaticToken($staticToken);
  128.             // Check if the email exists and the token is correct
  129.             if($currentAccount !== null
  130.                 && $currentAccount->getResetPasswordValidity() !== null
  131.                 && $currentAccount->getResetPasswordValidity() <= new \DateTime('NOW')
  132.             ){
  133.                 $this->notificationManager::addError('Utilisateur non valable ou délai dépassé : réessayez');
  134.                 $this->createFlashs();
  135.                 return $this->redirectToRoute('Index',
  136.                     $this->viewData
  137.                 );
  138.             }
  139.             else{
  140.                 // Now we add the form to change the password
  141.                 $form = $this->createForm(ContactResetType::class, $currentAccount);
  142.                 if ($request->isMethod('POST')) {
  143.                     $form->submit($request->request->get($form->getName()));
  144.                     // If form is correct
  145.                     if ($form->isSubmitted() && $form->isValid()){
  146.                         // save the account
  147.                         $clearPassword = $currentAccount->getPassword();
  148.                         if($this->contactManager->updatePasswordFromToken($currentAccount->getEmail(), $currentAccount->getPassword(), $staticToken)){
  149.                             $this->notificationManager::addInfo("Mot de passe mis à jour");
  150.                             $contact = $this->contactManager->getContactByMail($currentAccount->getEmail());
  151.                             $contact->setLastConnexion();
  152.                             $this->entityManager->flush();
  153.                         }
  154.                         else{
  155.                             $this->notificationManager::addError("Utilisateur invalide");
  156.                         }
  157.                         // if the account exists on Prestashop
  158.                         $psCustomer = Customers::getByEmail($currentAccount->getEmail(),true);
  159.                         // Insert the user if he doesn't exist
  160.                         if(!is_null($psCustomer)){
  161.                             if($psCustomer->updatePassword($clearPassword) !==0){
  162.                                 $this->notificationManager::addInfo("Mot de passe modifié sur Prestashop");
  163.                             }
  164.                         }
  165.                         $this->createFlashs();
  166.                         return $this->redirectToRoute('PreLogin', [
  167.                             "brandCode" => $_GET["brandCode"] ?? null,
  168.                             "apiKey" => $_GET["apiKey"] ?? null,
  169.                         ]);
  170.                     }
  171.                     else{
  172.                         // Sans ce else, une soumission invalide (jeton CSRF rejeté quand la
  173.                         // session est désynchronisée) était ignorée en silence : le client
  174.                         // repartait en croyant son mot de passe changé.
  175.                         $this->logger->error('Reset password form rejected', [
  176.                             'email' => $currentAccount !== null ? $currentAccount->getEmail() : null,
  177.                             'errors' => (string) $form->getErrors(true, false),
  178.                         ]);
  179.                         $this->notificationManager::addError('Votre session a expiré, rouvrez le lien reçu par e-mail puis saisissez à nouveau votre mot de passe');
  180.                     }
  181.                 }
  182.                 $this->createFlashs();
  183.                 $this->addViewDataObject('form', $form->createView())
  184.                     ->addViewDataArray('response', $this->getMessages());
  185.                 return $this->render('contact/account_password_reset.html.twig',
  186.                     $this->viewData
  187.                 );
  188.             }
  189.         }
  190.         return $this->render('home.html.twig', ['response' => $this->getMessages()]);
  191.     }
  192.     /**
  193.      * Login to the app
  194.      * Set a session with the contact and all related accounts
  195.      * Route : login
  196.      * @param Request $request
  197.      * @return Response
  198.      */
  199.     public function viewPreLogin(Request $request, RouterInterface $router): Response
  200.     {
  201. //        dd($request->getSession()->get('_security.default.target_path'));
  202.         if (isset($_GET["lang"]) && StringHelper::isNullOrEmptyWithSpace($_GET["lang"]) == false)
  203.         {
  204.             return $this->redirectToRoute('PreLogin', [
  205.                 "_locale" => $_GET["lang"],
  206.                 "brandCode" => $_GET["brandCode"]?? null,
  207.                 "apiKey" => $_GET["apiKey"]?? null
  208.             ]);
  209.         }
  210.         if($_ENV["MAINTENANCE"] === "true") {
  211.             return $this->render('maintainance.html.twig', $this->viewData);
  212.         }
  213.         $responseAction = 'pre-login';
  214.         $response = null;
  215.         $data = [];
  216.         if(isset($_COOKIE["contactDeleted"])) {
  217.             $this->notificationManager::addError('Oops, il y a un souci ! Soit il y a eu une erreur avec votre adresse email, soit nos serveurs sont pris d\'assaut par trop de monde en même temps. Veuillez vérifier votre saisie ou réessayer plus tard :)');
  218.         }
  219.         // If user is connected
  220.         /*if (!is_null($this->getUser())) {
  221.             $responseAction = 'ContactAccounts';
  222.         }*/
  223.         if (!is_null($this->getUser())) {
  224.             if(!is_null($request->getSession()->get('_security.default.target_path'))) {
  225.                 return $this->redirect($request->getSession()->get('_security.default.target_path'));
  226.             }
  227.             else {
  228.                 $responseAction = 'ContactAccounts';
  229.             }
  230.         }
  231.         else{
  232.             $this->getNavigationContext($request, $router);
  233.             $submitted = $request->request->get('submitLogin');
  234.             // if the form is submitted
  235.             if(!is_null($submitted)){
  236.                 $contactEmail = $request->request->get('email');
  237.                 // If the email address exists and is a correct email address
  238.                 if(!is_null($contactEmail) || !filter_var($contactEmail, FILTER_VALIDATE_EMAIL)){
  239.                     $contact = $this->contactManager->getContactByMail($contactEmail);
  240.                     // Si le contact n'est pas trouvé, on tente de le rechercher dans salesforce et de le synchroniser
  241.                     if (is_null($contact))
  242.                     {
  243.                         $contact = $this->contactManager->syncContactFormSF($contactEmail);
  244.                     }
  245.                     // If the contact exists
  246.                     if(!is_null($contact)){
  247.                         // If its the first connexion
  248.                         if(is_null($contact->getLastConnexion())){
  249.                             $this->contactManager->getContactByMail($contactEmail);
  250.                             // Le lien de création du mot de passe ouvre une nouvelle session : on persiste
  251.                             // la destination (achat externe, ou cours campus du lien de l'e-mail d'accès).
  252.                             $sessionTargetPath = (string) $request->getSession()->get('_security.default.target_path');
  253.                             if(strpos($sessionTargetPath, 'external_access/buy') || strpos($sessionTargetPath, '/campus')) {
  254.                                 $currentContact = $this->entityManager->getRepository(Contact::class)->findOneBy(['email' => $contactEmail]);
  255.                                 $currentContact->setInternalReturnUrl($sessionTargetPath);
  256.                                 $this->entityManager->persist($currentContact);
  257.                                 $this->entityManager->flush();
  258.                             }
  259.                             $responseAction = 'FirstConnexionResetPassword';
  260.                         }
  261.                         // if its a normal connexion
  262.                         else{
  263.                             $responseAction = 'Login';
  264.                             if($request->request->get('brandCode') != null && $request->request->get('brandCode') != "") {
  265.                                 $brandCode = $request->request->get('brandCode');
  266.                                 $data['brandCode'] = $brandCode;
  267.                             }
  268.                             if($request->request->get('apiKey') != null && $request->request->get('apiKey') != "") {
  269.                                 $apiKey = $request->request->get('apiKey');
  270.                                 $data['apiKey'] = $apiKey;
  271.                             }
  272.                         }
  273.                         $data['email'] = $contact->getEmail();
  274.                     }
  275.                     // contact not existing
  276.                     else{
  277.                         if($request->request->get('brandCode') != null && $request->request->get('brandCode') != "") {
  278.                             $brandCode = $request->request->get('brandCode');
  279.                             $data['brandCode'] = $brandCode;
  280.                         }
  281.                         $responseAction = 'Register';
  282.                         $data['email'] = $contactEmail;
  283. //                        $this->notificationManager::addError('Le compte n\'existe pas.');
  284.                     }
  285.                 }
  286.                 // Contact email not filled
  287.                 else{
  288.                     $this->notificationManager::addError('Adresse email incorrecte');
  289.                 }
  290.             }
  291.             $this->createFlashs();
  292.         }
  293.         if ($responseAction === 'ContactAccounts'){
  294.             $response = $this->redirectToRoute('ContactAccounts');
  295.         }
  296.         elseif ($responseAction === 'FirstConnexionResetPassword'){
  297.             $data["brandCode"] = $_GET["brandCode"]?? null;
  298.             $data["apiKey"] = $_GET["apiKey"]?? null;
  299.             $response = $this->redirectToRoute('FirstConnexionResetPassword', $data);
  300.         }
  301.         elseif ($responseAction === 'Login'){
  302.             $response = $this->redirectToRoute('Login', $data);
  303.         }
  304.         elseif ($responseAction === 'Register'){
  305.             $response = $this->redirectToRoute('Register', $data);
  306.         }
  307.         else{
  308.             $response = $this->render('login/pre-login.html.twig', $this->viewData);
  309.         }
  310.         return $response;
  311.     }
  312.     /**
  313.      * Login to the app
  314.      * Set a session with the contact and all related accounts
  315.      * Route : login
  316.      * @param AuthenticationUtils $authenticationUtils
  317.      * @param Request $request
  318.      * @return Response
  319.      */
  320.     public function viewLogin(AuthenticationUtils $authenticationUtils, Request $request, RouterInterface $router): Response
  321.     {
  322.         $responseRoute = 'Login';
  323.         $data = [];
  324.         if (!is_null($this->getUser())) {
  325.             $responseRoute = 'ContactAccounts';
  326.         }
  327.         else{
  328.             $this->getNavigationContext($request, $router);
  329.             $contactEmail = $request->query->get('email');
  330.             if(is_null($contactEmail)){
  331.                 $responseRoute = 'PreLogin';
  332.             }
  333.             else{
  334. //                if(is_null($contactEmail)){
  335. //                    $contactEmail = $authenticationUtils->getLastUsername();
  336. //                }
  337.                 // get the login error if there is one
  338.                 $error = $authenticationUtils->getLastAuthenticationError();
  339.                 // last username entered by the user
  340.                 $lastUsername = $authenticationUtils->getLastUsername();
  341.                 $this->addViewDataString('last_username', $lastUsername)
  342.                     ->addViewDataObject('error', $error)
  343.                     ->addViewDataBool('csrfError', $error instanceof InvalidCsrfTokenException)
  344.                     ->addViewDataString('email', $contactEmail);
  345.             }
  346.         }
  347.         $this->createFlashs();
  348.         if($responseRoute === 'ContactAccounts'){
  349.             $response = $this->redirectToRoute('ContactAccounts');
  350.         }
  351.         elseif($responseRoute === 'PreLogin'){
  352.             $response = $this->redirectToRoute('PreLogin');
  353.         }
  354.         else{
  355.             $response = $this->render('login/login.html.twig', $this->viewData);
  356.         }
  357.         return $response;
  358.     }
  359.     public function logout()
  360.     {
  361.     }
  362.     /**
  363.      * First connexion email
  364.      * @param Request $request
  365.      * @return Response
  366.      */
  367.     public function viewFirstConnexionResetPassword(Request $request, RouterInterface $router) : Response
  368.     {
  369.         $contactEmail = $request->query->get('email', '');
  370.         $contact = $this->contactManager->getContactByMail($contactEmail);
  371.         $this->getNavigationContext($request, $router);
  372.         if(!is_null($contact) && is_null($contact->getLastConnexion())){
  373.             // if the user has no validity date or a old validity date
  374.             $this->contactManager->sendResetPassword($contact, $this->language, $this->viewData['context']);
  375. //            $contact->setLastConnexion();
  376. //            $this->entityManager->flush();
  377.         }
  378.         else{
  379.             $this->notificationManager::addError('Le compte n\'existe pas ou l\'e-mail de première connexion a déjà été envoyé');
  380.         }
  381.         $this->createFlashs();
  382.         return $this->render('contact/first_connexion_ask_account_password_reset.html.twig', $this->viewData);
  383.     }
  384.     /**
  385.      * Register account
  386.      * @param Request $request
  387.      * @return Response
  388.      */
  389.     public function viewRegisterAccount(Request $request, RouterInterface $router, InstructorService $instructorService, GuardAuthenticatorHandler $guard, WebsiteFormAuthenticator $autoLoginAuthenticator) : Response
  390.     {
  391.         if (!is_null($this->getUser()) || $this->language == 'it') {
  392.             $responseRoute = $this->redirectToRoute('ContactAccounts', $this->viewData);
  393.         }
  394.         else {
  395.             $this->getNavigationContext($request, $router);
  396.             $dtoRequest = new DtoSaveInstructorRequest();
  397.             $submitted = $request->request->get('submitRegister');
  398.             // if the form is submitted
  399.             if (!is_null($submitted)) {
  400.                 $dtoRequest->email = $request->request->get('email') ?? '';
  401.                 $dtoRequest->emailCompta = $request->request->get('email') ?? '';
  402.                 $dtoRequest->lastName = $request->request->get('lastName') ?? '';
  403.                 $dtoRequest->firstName = $request->request->get('firstName') ?? '';
  404.                 $dtoRequest->phone = $request->request->get('phone') ?? '';
  405.                 $dtoRequest->address = $request->request->get('address') ?? '';
  406.                 $dtoRequest->zipCode = $request->request->get('zipCode') ?? '';
  407.                 $dtoRequest->city = $request->request->get('city') ?? '';
  408.                 $dtoRequest->siret = $request->request->get('siret') ?? '';
  409.                 $dtoRequest->tva = $request->request->get('tva') ?? '';
  410.                 $dtoRequest->password = $request->request->get('password') ?? '';
  411.                 $dtoRequest->checkPassword = $request->request->get('checkPassword') ?? '';
  412.                 $dtoRequest->billingCountryCode = $request->request->get('country') ?? '';
  413.                 $dtoRequest->isPro = $request->request->get('isPro');
  414.                 $dtoResponse = $instructorService->createInstructor($dtoRequest);
  415.                 $this->createFlashsFromDtoResponse($dtoResponse);
  416.                 if($dtoResponse->isSuccess()) {
  417.                     $referent = $this->contactManager->fillSessionContactFromContactEmail($dtoRequest->email);
  418.                     $request->getSession()->set(Security::LAST_USERNAME, $request->get('email'));
  419.                     $request->getSession()->set('contact', $referent);
  420.                     $request->getSession()->set('contactCsrfToken', $this->contactManager->getContactApiTokenByEmail($dtoRequest->email));
  421.                     // Handle user as if he just logged-in
  422.                     // after validating the user and saving it to the database
  423.                     // authenticate the user and use onAuthenticationSuccess on the authenticator
  424.                     $user = $this->contactManager->getContactByMail($dtoRequest->email);
  425.                     $guard->authenticateUserAndHandleSuccess(
  426.                         $user,
  427.                         $request,
  428.                         $autoLoginAuthenticator,
  429.                         'main'
  430.                     );
  431.                     $responseRoute = $this->redirectToRoute('PreLogin', $this->viewData);
  432.                 } else {
  433.                     $this->addViewDataObject('newInstructorAccount', $dtoRequest);
  434.                     $responseRoute = $this->render('contact/register.html.twig', $this->viewData);
  435.                 }
  436.             } else {
  437.                 $responseRoute = $this->render('contact/register.html.twig', $this->viewData);
  438.             }
  439.         }
  440.         return $responseRoute;
  441.     }
  442.     /**
  443.      * Autologin from Salesforce
  444.      * path: /{_locale}/switch
  445.      * name: SwitchUser
  446.      * @return \Symfony\Component\HttpFoundation\Response
  447.      */
  448.     public function switchUser(GuardAuthenticatorHandler $guard, Security $security, ConnectAsAuthenticator $customAuthenticator, Request $request)
  449.     {
  450.         if ($this->getUser() == null)
  451.         {
  452.             $this->saveTargetPath($request->getSession(), "default", $request->getUri());
  453.             return $this->redirectToRoute('PreLogin');
  454.         }
  455.         $user = $this->entityManager->getRepository(Contact::class)->findOneBy(["email" => $request->get("email")]);
  456.         if ($user == null || $security->isGranted('ROLE_ADMIN') == false)
  457.         {
  458.             throw $this->createNotFoundException("L'action demandée ne peut pas être exécutée.");
  459.         }
  460.         else
  461.         {
  462.             $currentUser = $security->getUser();
  463.             $customAuthenticator->setCurrentUser($currentUser);
  464.             // Handle user as if he just logged-in
  465.             // after validating the user and saving it to the database
  466.             // authenticate the user and use onAuthenticationSuccess on the authenticator
  467.             $guard->authenticateUserAndHandleSuccess(
  468.                 $user,
  469.                 $request,
  470.                 $customAuthenticator,
  471.                 'main'
  472.             );
  473.             // Redirection vers la page Home
  474.             return $this->redirectToRoute('ContactAccounts');
  475.         }
  476.     }
  477.     /**
  478.      * disconnect to previous account from Salesforce
  479.      * path: /{_locale}/exit
  480.      * name: ExitUser
  481.      * @return Response
  482.      */
  483.     public function exitUser(GuardAuthenticatorHandler $guard, Security $security, ConnectAsAuthenticator $customAuthenticator, Request $request) : Response
  484.     {
  485.         // Récupération des données de l'administrateur dans la session
  486.         $previousAdminUsername = $request->getSession()->get('previousAdminUsername');
  487.         if (StringHelper::isNullOrEmptyWithSpace($previousAdminUsername) == false)
  488.         {
  489.             $user = $this->entityManager->getRepository(Contact::class)->findOneBy(["email" => $previousAdminUsername]);
  490.             if ($user == null)
  491.             {
  492.                 throw $this->createNotFoundException("L'action demandée ne peut pas être exécutée.");
  493.             }
  494.             else
  495.             {
  496.                 $customAuthenticator->setCurrentUser(null);
  497.                 $guard->authenticateUserAndHandleSuccess(
  498.                     $user,
  499.                     $request,
  500.                     $customAuthenticator,
  501.                     'main'
  502.                 );
  503.                 // Redirection vers la page Home
  504.                 return $this->redirectToRoute('ContactAccounts');
  505.             }
  506.         }
  507.         else
  508.         {
  509.             throw $this->createNotFoundException("L'action demandée ne peut pas être exécutée.");
  510.         }
  511.     }
  512. }