src/Controller/ResetPasswordController.php line 66

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Users;
  4. use App\Entity\PublisherCabinet\MafoPublisherCabinetManager;
  5. use App\Entity\AdvertiserCabinet\MafoAdvertiserCabinetManager;
  6. use App\Form\ChangePasswordFormType;
  7. use App\Form\ResetPasswordRequestFormType;
  8. use Doctrine\ORM\EntityManagerInterface;
  9. use Symfony\Bridge\Twig\Mime\TemplatedEmail;
  10. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  11. use Symfony\Component\Form\Extension\Core\Type\PasswordType;
  12. use Symfony\Component\HttpFoundation\RedirectResponse;
  13. use Symfony\Component\HttpFoundation\Request;
  14. use Symfony\Component\HttpFoundation\Response;
  15. use Symfony\Component\Mailer\MailerInterface;
  16. use Symfony\Component\Mime\Address;
  17. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
  18. use Symfony\Component\Routing\Annotation\Route;
  19. use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  20. use Symfony\Contracts\Translation\TranslatorInterface;
  21. use SymfonyCasts\Bundle\ResetPassword\Controller\ResetPasswordControllerTrait;
  22. use SymfonyCasts\Bundle\ResetPassword\Exception\ResetPasswordExceptionInterface;
  23. use SymfonyCasts\Bundle\ResetPassword\ResetPasswordHelperInterface;
  24. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  25. /**
  26. * @Route("/reset-password", name="reset_password_")
  27. */
  28. class ResetPasswordController extends AbstractController
  29. {
  30. use ResetPasswordControllerTrait;
  31. private ResetPasswordHelperInterface $userResetPasswordHelper;
  32. private ResetPasswordHelperInterface $mafoPublisherResetPasswordHelper;
  33. private ResetPasswordHelperInterface $mafoAdvertiserResetPasswordHelper;
  34. private EntityManagerInterface $entityManager;
  35. private $params;
  36. private string $publisherDomain;
  37. private string $advertiserDomain;
  38. public function __construct(
  39. ResetPasswordHelperInterface $userResetPasswordHelper,
  40. ResetPasswordHelperInterface $mafoPublisherResetPasswordHelper,
  41. ResetPasswordHelperInterface $mafoAdvertiserResetPasswordHelper,
  42. EntityManagerInterface $entityManager,
  43. ParameterBagInterface $params,
  44. ) {
  45. $this->userResetPasswordHelper = $userResetPasswordHelper;
  46. $this->mafoPublisherResetPasswordHelper = $mafoPublisherResetPasswordHelper;
  47. $this->mafoAdvertiserResetPasswordHelper = $mafoAdvertiserResetPasswordHelper;
  48. $this->entityManager = $entityManager;
  49. $this->params = $params;
  50. $this->publisherDomain = $params->get('publishers_subdomain');
  51. $this->advertiserDomain = $params->get('advertisers_subdomain');
  52. }
  53. /**
  54. * Display & process form to request a password reset.
  55. *
  56. * @Route("", name="app_forgot_password_request")
  57. */
  58. public function request(Request $request, MailerInterface $mailer, TranslatorInterface $translator): Response
  59. {
  60. $form = $this->createForm(ResetPasswordRequestFormType::class);
  61. $form->handleRequest($request);
  62. // Get the current domain from the request
  63. $domain = $request->getHost();
  64. $domainTemplates = [
  65. $this->publisherDomain => 'publisher/login/index.html.twig',
  66. $this->advertiserDomain => 'advertiser/login/index.html.twig',
  67. ];
  68. $layoutTemplate = $domainTemplates[$domain] ?? 'form_login.html.twig';
  69. if ($form->isSubmitted() && $form->isValid()) {
  70. return $this->processSendingPasswordResetEmail(
  71. $form->get('email')->getData(),
  72. $mailer,
  73. $translator,
  74. $request
  75. );
  76. }
  77. return $this->render('reset_password/request.html.twig', [
  78. 'requestForm' => $form->createView(),
  79. 'layoutTemplate' => $layoutTemplate,
  80. 'domain' => $domain,
  81. 'publisherDomain' => $this->publisherDomain,
  82. 'advertiserDomain' => $this->advertiserDomain,
  83. ]);
  84. }
  85. /**
  86. * Confirmation page after a user has requested a password reset.
  87. *
  88. * @Route("/check-email", name="app_check_email")
  89. */
  90. public function checkEmail(Request $request): Response
  91. {
  92. // Get the domain from the request
  93. $domain = $request->getHost();
  94. // Generate a fake token if the user does not exist or someone hit this page directly.
  95. // This prevents exposing whether or not a user was found with the given email address or not
  96. if (null === ($resetToken = $this->getTokenObjectFromSession())) {
  97. $resetToken = $this->userResetPasswordHelper->generateFakeResetToken();
  98. }
  99. return $this->render('reset_password/check_email.html.twig', [
  100. 'resetToken' => $resetToken,
  101. 'domain' => $domain,
  102. 'publisherDomain' => $this->publisherDomain,
  103. 'advertiserDomain' => $this->advertiserDomain,
  104. ]);
  105. }
  106. /**
  107. * Validates and process the reset URL that the user clicked in their email.
  108. *
  109. * @Route("/reset/{token}", name="app_reset_password")
  110. */
  111. public function reset(Request $request, UserPasswordHasherInterface $userPasswordHasher, TranslatorInterface $translator, string $token = null): Response
  112. {
  113. if ($token) {
  114. // We store the token in session and remove it from the URL, to avoid the URL being
  115. // loaded in a browser and potentially leaking the token to 3rd party JavaScript.
  116. $this->storeTokenInSession($token);
  117. return $this->redirectToRoute('reset_password_app_reset_password');
  118. }
  119. $token = $this->getTokenFromSession();
  120. if (null === $token) {
  121. throw $this->createNotFoundException('No reset password token found in the URL or in the session.');
  122. }
  123. $host = $request->getHost();
  124. $resetPasswordHelpers = [
  125. $this->publisherDomain => $this->mafoPublisherResetPasswordHelper,
  126. $this->advertiserDomain => $this->mafoAdvertiserResetPasswordHelper,
  127. 'default' => $this->userResetPasswordHelper,
  128. ];
  129. $resetPasswordHelper = $resetPasswordHelpers[$host] ?? $resetPasswordHelpers['default'];
  130. try {
  131. $user = $resetPasswordHelper->validateTokenAndFetchUser($token);
  132. } catch (ResetPasswordExceptionInterface $e) {
  133. $this->addFlash('reset_password_error', sprintf(
  134. '%s - %s',
  135. $translator->trans(ResetPasswordExceptionInterface::MESSAGE_PROBLEM_VALIDATE, [], 'ResetPasswordBundle'),
  136. $translator->trans($e->getReason(), [], 'ResetPasswordBundle')
  137. ));
  138. return $this->redirectToRoute('reset_password_app_forgot_password_request');
  139. }
  140. // The token is valid; allow the user to change their password.
  141. $form = $this->createForm(ChangePasswordFormType::class);
  142. $form->handleRequest($request);
  143. if ($form->isSubmitted() && $form->isValid()) {
  144. // A password reset token should be used only once, remove it.
  145. $resetPasswordHelper->removeResetRequest($token);
  146. // Encode(hash) the plain password, and set it.
  147. $encodedPassword = $userPasswordHasher->hashPassword(
  148. $user,
  149. $form->get('plainPassword')->getData()
  150. );
  151. $user->setPassword($encodedPassword);
  152. $this->entityManager->flush();
  153. // The session is cleaned up after the password has been changed.
  154. $this->cleanSessionAfterReset();
  155. return $this->redirectToRoute('homepage');
  156. }
  157. return $this->render('reset_password/reset.html.twig', [
  158. 'resetForm' => $form->createView(),
  159. ]);
  160. }
  161. private function processSendingPasswordResetEmail(string $emailFormData, MailerInterface $mailer, TranslatorInterface $translator, Request $request): RedirectResponse
  162. {
  163. // $user = $this->entityManager->getRepository(Users::class)->findOneBy([
  164. // 'email' => $emailFormData,
  165. // ]);
  166. // Get the domain of the request
  167. $domain = $request->getHost();
  168. $entityMapping = [
  169. $this->publisherDomain => MafoPublisherCabinetManager::class,
  170. $this->advertiserDomain => MafoAdvertiserCabinetManager::class,
  171. 'default' => Users::class
  172. ];
  173. $helperMapping = [
  174. $this->publisherDomain => $this->mafoPublisherResetPasswordHelper,
  175. $this->advertiserDomain => $this->mafoAdvertiserResetPasswordHelper,
  176. 'default' => $this->userResetPasswordHelper
  177. ];
  178. $entityClass = $entityMapping[$domain] ?? $entityMapping['default'];
  179. $user = $this->entityManager->getRepository($entityClass)->findOneBy([
  180. 'email' => $emailFormData,
  181. ]);
  182. // Do not reveal whether a user account was found or not.
  183. if (!$user) {
  184. return $this->redirectToRoute('reset_password_app_check_email');
  185. }
  186. try {
  187. $resetHelper = $helperMapping[$domain] ?? $helperMapping['default'];
  188. $resetToken = $resetHelper->generateResetToken($user);
  189. } catch (ResetPasswordExceptionInterface $e) {
  190. // If you want to tell the user why a reset email was not sent, uncomment
  191. // the lines below and change the redirect to 'reset_password_app_forgot_password_request'.
  192. // Caution: This may reveal if a user is registered or not.
  193. //
  194. // $this->addFlash('reset_password_error', sprintf(
  195. // '%s - %s',
  196. // $translator->trans(ResetPasswordExceptionInterface::MESSAGE_PROBLEM_HANDLE, [], 'ResetPasswordBundle'),
  197. // $translator->trans($e->getReason(), [], 'ResetPasswordBundle')
  198. // ));
  199. return $this->redirectToRoute('reset_password_app_check_email');
  200. }
  201. $host = $request->getSchemeAndHttpHost();
  202. $email = (new TemplatedEmail())
  203. ->from(new Address('mafo@mobupps.com', 'MAFO Password Reset'))
  204. ->to($user->getEmail())
  205. ->subject('Your password reset request')
  206. ->htmlTemplate('reset_password/email.html.twig')
  207. ->context([
  208. 'resetToken' => $resetToken,
  209. 'host' => $host // Pass the host dynamically to the email template
  210. ]);
  211. $mailer->send($email);
  212. // Store the token object in session for retrieval in check-email route.
  213. $this->setTokenObjectInSession($resetToken);
  214. return $this->redirectToRoute('reset_password_app_check_email');
  215. }
  216. }