src/Controller/ResetPasswordController.php line 45

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Repository\UserRepository;
  4. use App\Form\ChangePasswordFormType;
  5. use App\Form\ResetPasswordRequestFormType;
  6. use App\Service\EmailService;
  7. use Doctrine\ORM\EntityManagerInterface;
  8. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  9. use Symfony\Component\HttpFoundation\Request;
  10. use Symfony\Component\HttpFoundation\Response;
  11. use Symfony\Component\Routing\Annotation\Route;
  12. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  13. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
  14. use SymfonyCasts\Bundle\ResetPassword\Controller\ResetPasswordControllerTrait;
  15. use SymfonyCasts\Bundle\ResetPassword\Exception\ResetPasswordExceptionInterface;
  16. use SymfonyCasts\Bundle\ResetPassword\ResetPasswordHelperInterface;
  17. use SymfonyCasts\Bundle\ResetPassword\Exception\TooManyPasswordRequestsException;
  18. #[Route('/reset-password')]
  19. class ResetPasswordController extends AbstractController
  20. {
  21. use ResetPasswordControllerTrait;
  22. private ResetPasswordHelperInterface $resetPasswordHelper;
  23. private EntityManagerInterface $entityManager;
  24. private EmailService $emailService;
  25. public function __construct(
  26. ResetPasswordHelperInterface $resetPasswordHelper,
  27. EntityManagerInterface $entityManager,
  28. EmailService $emailService
  29. ) {
  30. $this->resetPasswordHelper = $resetPasswordHelper;
  31. $this->entityManager = $entityManager;
  32. $this->emailService = $emailService;
  33. }
  34. /**
  35. * Demande de reset password
  36. */
  37. #[Route('', name: 'app_forgot_password_request')]
  38. public function request(
  39. Request $request,
  40. UserRepository $userRepository
  41. ): Response {
  42. $form = $this->createForm(
  43. ResetPasswordRequestFormType::class
  44. );
  45. $form->handleRequest($request);
  46. if (
  47. $form->isSubmitted()
  48. && $form->isValid()
  49. ) {
  50. $email = $form
  51. ->get('email')
  52. ->getData();
  53. $user = $userRepository->findOneBy([
  54. 'email' => $email
  55. ]);
  56. // sécurité : ne jamais dire si email existe ou non
  57. // sécurité : ne jamais dire si email existe ou non
  58. if (!$user) {
  59. return $this->redirectToRoute('app_check_email');
  60. }
  61. // Générer token (AVEC PROTECTION)
  62. try {
  63. $resetToken = $this->resetPasswordHelper->generateResetToken($user);
  64. } catch (TooManyPasswordRequestsException $e) {
  65. $this->addFlash(
  66. 'error',
  67. 'Vous avez déjà demandé un lien récemment. Veuillez attendre avant de réessayer.'
  68. );
  69. return $this->redirectToRoute('app_forgot_password_request');
  70. }
  71. // Générer lien absolu
  72. $link = $this->generateUrl(
  73. 'app_reset_password',
  74. [
  75. 'token' => $resetToken->getToken()
  76. ],
  77. UrlGeneratorInterface::ABSOLUTE_URL
  78. );
  79. // Envoi email via PHPMailer
  80. $this->emailService
  81. ->EnvoiResetPassword(
  82. $user->getEmail(),
  83. $user->getPrenom().' '.$user->getNom(),
  84. $link
  85. );
  86. // stocker token en session
  87. $this->setTokenObjectInSession(
  88. $resetToken
  89. );
  90. return $this->redirectToRoute(
  91. 'app_check_email'
  92. );
  93. }
  94. return $this->render(
  95. 'reset_password/request.html.twig',
  96. [
  97. 'requestForm' => $form->createView(),
  98. ]
  99. );
  100. }
  101. /**
  102. * Message après demande
  103. */
  104. #[Route('/check-email', name: 'app_check_email')]
  105. public function checkEmail(): Response
  106. {
  107. return $this->render(
  108. 'reset_password/check_email.html.twig'
  109. );
  110. }
  111. /**
  112. * Réinitialisation mot de passe
  113. */
  114. #[Route('/reset/{token}', name: 'app_reset_password')]
  115. public function reset(
  116. Request $request,
  117. UserPasswordHasherInterface $passwordHasher,
  118. ?string $token = null
  119. ): Response {
  120. if ($token) {
  121. $this->storeTokenInSession(
  122. $token
  123. );
  124. return $this->redirectToRoute(
  125. 'app_reset_password'
  126. );
  127. }
  128. $token = $this
  129. ->getTokenFromSession();
  130. if (null === $token) {
  131. throw $this
  132. ->createNotFoundException(
  133. 'No reset token found.'
  134. );
  135. }
  136. try {
  137. $user = $this
  138. ->resetPasswordHelper
  139. ->validateTokenAndFetchUser(
  140. $token
  141. );
  142. } catch (
  143. ResetPasswordExceptionInterface $e
  144. ) {
  145. $this->addFlash(
  146. 'reset_password_error',
  147. sprintf(
  148. '%s - %s',
  149. $e->getReason(),
  150. $e->getReasonData()
  151. )
  152. );
  153. return $this->redirectToRoute(
  154. 'app_forgot_password_request'
  155. );
  156. }
  157. $form = $this->createForm(
  158. ChangePasswordFormType::class
  159. );
  160. $form->handleRequest($request);
  161. if (
  162. $form->isSubmitted()
  163. && $form->isValid()
  164. ) {
  165. // supprimer token
  166. $this
  167. ->resetPasswordHelper
  168. ->removeResetRequest(
  169. $token
  170. );
  171. $plainPassword = $form
  172. ->get('plainPassword')
  173. ->getData();
  174. // hash password
  175. $user->setPassword(
  176. $passwordHasher
  177. ->hashPassword(
  178. $user,
  179. $plainPassword
  180. )
  181. );
  182. // nettoyage ancien FOSUser
  183. /* if (
  184. method_exists(
  185. $user,
  186. 'setSalt'
  187. )
  188. ) {
  189. $user->setSalt(null);
  190. }*/
  191. $this
  192. ->entityManager
  193. ->flush();
  194. // vider session token
  195. $this
  196. ->cleanSessionAfterReset();
  197. $this->addFlash(
  198. 'success',
  199. 'Mot de passe modifié avec succès.'
  200. );
  201. return $this->redirectToRoute(
  202. 'login'
  203. );
  204. }
  205. return $this->render(
  206. 'reset_password/reset.html.twig',
  207. [
  208. 'resetForm' => $form->createView(),
  209. ]
  210. );
  211. }
  212. }