src/Controller/ResetPasswordController.php line 64

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * docustack
  5.  *
  6.  * @copyright  Copyright (c) 2014-2022, 47GradNord - Agentur für Internetlösungen
  7.  * @author     Holger Neuner <neuner@47gradnord.de>
  8.  */
  9. namespace App\Controller;
  10. use App\Entity\StaticSendmail;
  11. use App\Entity\User;
  12. use App\Form\ChangePasswordFormType;
  13. use App\Form\ResetPasswordRequestFormType;
  14. use App\Service\SendmailManager;
  15. use http\Exception;
  16. use Symfony\Component\HttpFoundation\RedirectResponse;
  17. use Symfony\Component\HttpFoundation\Request;
  18. use Symfony\Component\HttpFoundation\Response;
  19. use Symfony\Component\Mailer\MailerInterface;
  20. use Symfony\Component\Routing\Annotation\Route;
  21. use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
  22. use SymfonyCasts\Bundle\ResetPassword\Controller\ResetPasswordControllerTrait;
  23. use SymfonyCasts\Bundle\ResetPassword\Exception\ResetPasswordExceptionInterface;
  24. use SymfonyCasts\Bundle\ResetPassword\ResetPasswordHelperInterface;
  25. class ResetPasswordController extends AbstractAppController
  26. {
  27.     use ResetPasswordControllerTrait;
  28.     private $resetPasswordHelper;
  29.     /**
  30.      * @var SendmailManager
  31.      */
  32.     private $sendmailManager;
  33.     public function __construct(ResetPasswordHelperInterface $resetPasswordHelperSendmailManager $sendmailManager)
  34.     {
  35.         $this->resetPasswordHelper $resetPasswordHelper;
  36.         $this->sendmailManager $sendmailManager;
  37.     }
  38.     /**
  39.      * Display & process form to request a password reset.
  40.      *
  41.      * @Route("reset-password", name="app_forgot_password_request")
  42.      */
  43.     public function request(Request $requestMailerInterface $mailer): Response
  44.     {
  45.         $form $this->createForm(ResetPasswordRequestFormType::class);
  46.         $form->handleRequest($request);
  47.         if ($form->isSubmitted() && $form->isValid()) {
  48.             return $this->processSendingPasswordResetEmail(
  49.                 $form->get('email')->getData(),
  50.                 $mailer
  51.             );
  52.         }
  53.         return $this->render('reset_password/request.html.twig', [
  54.             'requestForm' => $form->createView(),
  55.         ]);
  56.     }
  57.     /**
  58.      * Confirmation page after a user has requested a password reset.
  59.      *
  60.      * @Route("/check-email", name="app_check_email")
  61.      */
  62.     public function checkEmail(): Response
  63.     {
  64.         // We prevent users from directly accessing this page
  65.         if (null === ($resetToken $this->getTokenObjectFromSession())) {
  66.             return $this->redirectToRoute('app_forgot_password_request');
  67.         }
  68.         return $this->render('reset_password/check_email.html.twig', [
  69.             'resetToken' => $resetToken,
  70.         ]);
  71.     }
  72.     /**
  73.      * Validates and process the reset URL that the user clicked in their email.
  74.      *
  75.      * @Route("/reset/{token}", name="app_reset_password")
  76.      */
  77.     public function reset(Request $requestUserPasswordEncoderInterface $passwordEncoderstring $token null): Response
  78.     {
  79.         if ($token) {
  80.             // We store the token in session and remove it from the URL, to avoid the URL being
  81.             // loaded in a browser and potentially leaking the token to 3rd party JavaScript.
  82.             $this->storeTokenInSession($token);
  83.             return $this->redirectToRoute('app_reset_password');
  84.         }
  85.         $token $this->getTokenFromSession();
  86.         if (null === $token) {
  87.             throw $this->createNotFoundException('No reset password token found in the URL or in the session.');
  88.         }
  89.         try {
  90.             $user $this->resetPasswordHelper->validateTokenAndFetchUser($token);
  91.         } catch (ResetPasswordExceptionInterface $e) {
  92.             $this->addFlash('reset_password_error'sprintf(
  93.                 'There was a problem validating your reset request - %s',
  94.                 $e->getReason()
  95.             ));
  96.             return $this->redirectToRoute('app_forgot_password_request');
  97.         }
  98.         // The token is valid; allow the user to change their password.
  99.         $form $this->createForm(ChangePasswordFormType::class);
  100.         $form->handleRequest($request);
  101.         if ($form->isSubmitted() && $form->isValid()) {
  102.             // A password reset token should be used only once, remove it.
  103.             $this->resetPasswordHelper->removeResetRequest($token);
  104.             // Encode the plain password, and set it.
  105.             $encodedPassword $passwordEncoder->encodePassword(
  106.                 $user,
  107.                 $form->get('plainPassword')->getData()
  108.             );
  109.             $user->setPassword($encodedPassword);
  110.             $this->getDoctrine()->getManager()->flush();
  111.             // The session is cleaned up after the password has been changed.
  112.             $this->cleanSessionAfterReset();
  113.             $this->addFlash('success''Passwort erfolgreich neu gespeichert!');
  114.             return $this->redirectToRoute('app_login');
  115.         }
  116.         return $this->render('reset_password/reset.html.twig', [
  117.             'resetForm' => $form->createView(),
  118.         ]);
  119.     }
  120.     /**
  121.      * @Route("/changepassword-forced", name="app_changepassword_forced")
  122.      */
  123.     public function changePasswordForced(Request $requestUserPasswordEncoderInterface $encoder): Response
  124.     {
  125.         /** @var User $user */
  126.         $user $this->getAppUser();
  127.         if (null === $user) {
  128.             throw $this->createAccessDeniedException('Diese Seite ist nicht aufrufbar');
  129.         }
  130.         $form $this->createForm(ChangePasswordFormType::class, $user);
  131.         $form->handleRequest($request);
  132.         if ($form->isSubmitted() && $form->isValid()) {
  133.             try {
  134.                 $changePassword $request->request->get('change_password_form');
  135.                 $password $changePassword['plainPassword']['first'];
  136.                 $pass $encoder->encodePassword($user$password);
  137.                 $user->setPassword($pass);
  138.                 $user->setForceChangePassword(false);
  139.                 $this->getDoctrine()->getManager()->flush();
  140.                 $this->addFlash('success''Password erfolgreich geändert!');
  141.             } catch (Exception $e) {
  142.                 $this->addFlash('danger''Fehler, bitte versuchen Sie es erneut.');
  143.                 return $this->redirectToRoute('app_changepassword_forced');
  144.             }
  145.             return $this->redirectToRoute('app_logout');
  146.         }
  147.         return $this->render('default/reset-password.html.twig', [
  148.             'form' => $form->createView(),
  149.             'user' => $this->getAppUser(),
  150.         ]);
  151.     }
  152.     private function processSendingPasswordResetEmail(string $emailFormDataMailerInterface $mailer): RedirectResponse
  153.     {
  154.         $user $this->getDoctrine()->getRepository(User::class)->findOneBy([
  155.             'email' => $emailFormData,
  156.         ]);
  157.         // Do not reveal whether a user account was found or not.
  158.         if (!$user) {
  159.             return $this->redirectToRoute('app_check_email');
  160.         }
  161.         try {
  162.             $resetToken $this->resetPasswordHelper->generateResetToken($user);
  163.         } catch (ResetPasswordExceptionInterface $e) {
  164.             // If you want to tell the user why a reset email was not sent, uncomment
  165.             // the lines below and change the redirect to 'app_forgot_password_request'.
  166.             // Caution: This may reveal if a user is registered or not.
  167.             //
  168.             $this->addFlash('danger'sprintf(
  169.                 'Es gibt ein Problem mit dem Zurücksetzen des Passwortes - %s',
  170.                 $e->getReason()
  171.             ));
  172.             return $this->redirectToRoute('app_forgot_password_request');
  173.         }
  174.         $this->sendmailManager->sendPasswortResetRequest(
  175.             StaticSendmail::create($user->getEmail(), '''Passwort zurücksetzen'),
  176.             $user,
  177.             $resetToken
  178.         );
  179.         // Store the token object in session for retrieval in check-email route.
  180.         $this->setTokenObjectInSession($resetToken);
  181.         return $this->redirectToRoute('app_check_email');
  182.     }
  183. }