src/Controller/ResetPasswordController.php line 49

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\User;
  4. use App\Form\ChangePasswordFormType;
  5. use App\Form\ResetPasswordRequestFormType;
  6. use Doctrine\ORM\EntityManagerInterface;
  7. use Symfony\Bridge\Twig\Mime\TemplatedEmail;
  8. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  9. use Symfony\Component\HttpFoundation\RedirectResponse;
  10. use Symfony\Component\HttpFoundation\Request;
  11. use Symfony\Component\HttpFoundation\Response;
  12. use Symfony\Component\Mailer\MailerInterface;
  13. use Symfony\Component\Mime\Address;
  14. use Symfony\Component\Mime\Email;
  15. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
  16. use Symfony\Component\Routing\Annotation\Route;
  17. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  18. use Symfony\Contracts\Translation\TranslatorInterface;
  19. use SymfonyCasts\Bundle\ResetPassword\Controller\ResetPasswordControllerTrait;
  20. use SymfonyCasts\Bundle\ResetPassword\Exception\ResetPasswordExceptionInterface;
  21. use SymfonyCasts\Bundle\ResetPassword\ResetPasswordHelperInterface;
  22. use Psr\Log\LoggerInterface;
  23. #[Route('/reset-password')]
  24. class ResetPasswordController extends AbstractController
  25. {
  26.     use ResetPasswordControllerTrait;
  27.     private ResetPasswordHelperInterface $resetPasswordHelper;
  28.     private EntityManagerInterface $entityManager;
  29.     private UrlGeneratorInterface $urlGenerator;
  30.     private LoggerInterface $logger;
  31.     public function __construct(
  32.         ResetPasswordHelperInterface $resetPasswordHelper,
  33.         EntityManagerInterface $entityManager,
  34.         UrlGeneratorInterface $urlGenerator,
  35.         LoggerInterface $logger
  36.     ) {
  37.         $this->resetPasswordHelper $resetPasswordHelper;
  38.         $this->entityManager $entityManager;
  39.         $this->urlGenerator $urlGenerator;
  40.         $this->logger $logger;
  41.     }
  42.     #[Route(''name'app_forgot_password_request')]
  43.     public function request(Request $requestMailerInterface $mailerTranslatorInterface $translator): Response
  44.     {
  45.         $this->logger->info('Demande de réinitialisation de mot de passe');
  46.         // Vérifier si le formulaire a été soumis (méthode POST)
  47.         if ($request->isMethod('POST')) {
  48.             // Vérifier le reCAPTCHA
  49.             $recaptchaResponse $request->request->get('g-recaptcha-response');
  50.             $url 'https://www.google.com/recaptcha/api/siteverify';
  51.             $data = [
  52.                 'secret' => '6LdsZb4qAAAAAI7xvU1kTognYncJkUCY35WpymUS'
  53.                 'response' => $recaptchaResponse
  54.             ];
  55.             
  56.             $options = [
  57.                 'http' => [
  58.                     'header' => "Content-type: application/x-www-form-urlencoded\r\n",
  59.                     'method' => 'POST',
  60.                     'content' => http_build_query($data)
  61.                 ]
  62.             ];
  63.             
  64.             $context stream_context_create($options);
  65.             $result file_get_contents($urlfalse$context);
  66.             $responseData json_decode($result);
  67.             
  68.             if ($responseData->success) {
  69.                 // Le reCAPTCHA est valide, continuer avec l'envoi de l'email
  70.                 $form $this->createForm(ResetPasswordRequestFormType::class);
  71.                 $form->handleRequest($request);
  72.                 if ($form->isSubmitted() && $form->isValid()) {
  73.                     $this->logger->info('Formulaire de réinitialisation soumis');
  74.                     return $this->processSendingPasswordResetEmail(
  75.                         $form->get('email')->getData(),
  76.                         $mailer,
  77.                         $translator
  78.                     );
  79.                 }
  80.             } else {
  81.                 // Le reCAPTCHA a échoué, affichez un message d'erreur
  82.                 $this->addFlash('error''La vérification reCAPTCHA a échoué. Veuillez réessayer.');
  83.                 return $this->redirectToRoute('app_check_email');
  84.             }
  85.         }
  86.         $form $this->createForm(ResetPasswordRequestFormType::class);
  87.         return $this->render('reset_password/request.html.twig', [
  88.             'requestForm' => $form->createView(),
  89.         ]);
  90.     }
  91.     #[Route('/check-email'name'app_check_email')]
  92.     public function checkEmail(): Response
  93.     {
  94.         $this->logger->info('Vérification de l\'email');
  95.         $resetToken $this->getTokenObjectFromSession();
  96.         if (!$resetToken) {
  97.             $resetToken $this->resetPasswordHelper->generateFakeResetToken();
  98.         }
  99.         return $this->render('reset_password/check_email.html.twig', [
  100.             'resetToken' => $resetToken,
  101.         ]);
  102.     }
  103.     #[Route('/reset/{token}'name'app_reset_password')]
  104.     public function reset(Request $requestUserPasswordHasherInterface $userPasswordHasherTranslatorInterface $translatorstring $token null): Response
  105.     {
  106.         $this->logger->info('Réinitialisation du mot de passe');
  107.         // Si un token est passé dans l'URL, stockez-le dans la session.
  108.         if ($token) {
  109.             $this->storeTokenInSession($token);
  110.             return $this->redirectToRoute('app_reset_password');
  111.         }
  112.         // Sinon, récupérez le token de la session.
  113.         $token $this->getTokenFromSession();
  114.         if (null === $token) {
  115.             $this->logger->error('Aucun token de réinitialisation de mot de passe trouvé dans l\'URL ou dans la session.');
  116.             throw $this->createNotFoundException('Aucun token de réinitialisation de mot de passe trouvé dans l\'URL ou dans la session.');
  117.         }
  118.         // Validez le token et récupérez l'utilisateur associé.
  119.         try {
  120.             $user $this->resetPasswordHelper->validateTokenAndFetchUser($token);
  121.             $this->logger->info('Token validé avec succès');
  122.         } catch (ResetPasswordExceptionInterface $e) {
  123.             $this->logger->error('Erreur lors de la validation du token: ' $e->getMessage());
  124.             $this->addFlash('reset_password_error'sprintf(
  125.                 '%s - %s',
  126.                 $translator->trans(ResetPasswordExceptionInterface::MESSAGE_PROBLEM_VALIDATE, [], 'ResetPasswordBundle'),
  127.                 $translator->trans($e->getReason(), [], 'ResetPasswordBundle')
  128.             ));
  129.             return $this->redirectToRoute('app_forgot_password_request');
  130.         }
  131.         // Créez et gérez le formulaire de réinitialisation du mot de passe.
  132.         $form $this->createForm(ChangePasswordFormType::class);
  133.         $form->handleRequest($request);
  134.         if ($form->isSubmitted() && $form->isValid()) {
  135.             $this->logger->info('Formulaire de réinitialisation soumis');
  136.             // Ne supprimez le token que si la réinitialisation du mot de passe est réussie.
  137.             $this->resetPasswordHelper->removeResetRequest($token);
  138.             // Hash le mot de passe et mettez à jour l'utilisateur.
  139.             $encodedPassword $userPasswordHasher->hashPassword(
  140.                 $user,
  141.                 $form->get('plainPassword')->getData()
  142.             );
  143.             $user->setPassword($encodedPassword);
  144.             $this->entityManager->flush();
  145.             $this->logger->info('Mot de passe réinitialisé avec succès');
  146.             // Nettoyez la session après la réinitialisation.
  147.             $this->cleanSessionAfterReset();
  148.             return $this->redirectToRoute('app_login');
  149.         }
  150.         return $this->render('reset_password/reset.html.twig', [
  151.             'resetForm' => $form->createView(),
  152.         ]);
  153.     }
  154.     private function processSendingPasswordResetEmail(string $emailFormDataMailerInterface $mailerTranslatorInterface $translator): RedirectResponse
  155.     {
  156.         try {
  157.             $this->logger->info('Début du processus de réinitialisation pour: ' $emailFormData);
  158.             $user $this->entityManager->getRepository(User::class)->findOneBy([
  159.                 'email' => $emailFormData,
  160.             ]);
  161.             if (!$user) {
  162.                 $this->logger->warning('Utilisateur non trouvé: ' $emailFormData);
  163.                 return $this->redirectToRoute('app_check_email');
  164.             }
  165.             $this->logger->info('Utilisateur trouvé avec ID: ' $user->getId());
  166.             try {
  167.                 $resetToken $this->resetPasswordHelper->generateResetToken($user);
  168.                 $this->logger->info('Token généré avec succès: ' $resetToken->getToken());
  169.             } catch (ResetPasswordExceptionInterface $e) {
  170.                 $this->logger->error('Erreur lors de la génération du token: ' $e->getMessage(), [
  171.                     'exception' => $e,
  172.                     'trace' => $e->getTraceAsString()
  173.                 ]);
  174.                 return $this->redirectToRoute('app_check_email');
  175.             }
  176.             $resetUrl $this->urlGenerator->generate('app_reset_password', [
  177.                 'token' => $resetToken->getToken()
  178.             ], UrlGeneratorInterface::ABSOLUTE_URL);
  179.             $this->logger->info('URL de réinitialisation générée: ' $resetUrl);
  180.             try {
  181.                 $email = (new TemplatedEmail())
  182.                     ->from(new Address('no-reply@dimawork.fr''Dimawork'))
  183.                     ->to($user->getEmail())
  184.                     ->subject('Votre demande de réinitialisation de mot de passe')
  185.                     ->htmlTemplate('reset_password/email.html.twig')
  186.                     ->context([
  187.                         'resetUrl' => $resetUrl,
  188.                         'tokenLifetime' => $this->resetPasswordHelper->getTokenLifetime(),
  189.                         'username' => $user->getPrenom(),
  190.                     ]);
  191.                 $this->logger->info('Email préparé avec les paramètres suivants:', [
  192.                     'from' => 'no-reply@dimawork.fr',
  193.                     'to' => $user->getEmail(),
  194.                     'resetUrl' => $resetUrl,
  195.                     'tokenLifetime' => $this->resetPasswordHelper->getTokenLifetime()
  196.                 ]);
  197.                 $mailer->send($email);
  198.                 $this->logger->info('Email envoyé avec succès');
  199.             } catch (\Exception $e) {
  200.                 $this->logger->error('Erreur lors de l\'envoi de l\'email: ' $e->getMessage(), [
  201.                     'exception' => $e,
  202.                     'trace' => $e->getTraceAsString()
  203.                 ]);
  204.                 throw $e;
  205.             }
  206.             $this->setTokenObjectInSession($resetToken);
  207.             return $this->redirectToRoute('app_check_email');
  208.         } catch (\Exception $e) {
  209.             $this->logger->error('Erreur générale dans processSendingPasswordResetEmail: ' $e->getMessage(), [
  210.                 'exception' => $e,
  211.                 'trace' => $e->getTraceAsString()
  212.             ]);
  213.             throw $e;
  214.         }
  215.     }
  216. }