src/Controller/SecurityController.php line 35

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\User;
  4. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  5. use Symfony\Component\HttpFoundation\Request;
  6. use Symfony\Component\HttpFoundation\Response;
  7. use Symfony\Component\Routing\Annotation\Route;
  8. use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
  9. use Symfony\Component\Security\Core\User\UserInterface;
  10. use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  11. use Symfony\Component\Mime\Email;
  12. use Symfony\Component\Mailer\MailerInterface;
  13. use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
  14. use Psr\Log\LoggerInterface;
  15. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  16. use Symfony\Component\Form\Extension\Core\Type\PasswordType;
  17. use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
  18. use Symfony\Component\Validator\Constraints\Length;
  19. use Symfony\Component\Validator\Constraints\NotBlank;
  20. class SecurityController extends AbstractController
  21. {
  22.     private $logger;
  23.     public function __construct(LoggerInterface $logger)
  24.     {
  25.         $this->logger $logger;
  26.     }
  27.     /**
  28.      * @Route("/login", name="app_login")
  29.      */
  30.     public function login(AuthenticationUtils $authenticationUtilsRequest $request): Response
  31.     {
  32.         $this->logger->info('Login attempt', ['method' => $request->getMethod()]);
  33.         if ($this->getUser()) {
  34.             $this->logger->info('User already logged in, redirecting to home');
  35.             return $this->redirectToRoute('app_home');
  36.         }
  37.         // get the login error if there is one
  38.         $error $authenticationUtils->getLastAuthenticationError();
  39.         // last username entered by the user
  40.         $lastUsername $authenticationUtils->getLastUsername();
  41.         if ($error) {
  42.             $this->logger->warning('Login error', ['error' => $error->getMessage()]);
  43.         }
  44.         return $this->render('security/login.html.twig', ['last_username' => $lastUsername'error' => $error]);
  45.     }
  46.     /**
  47.      * @Route("/logout", name="app_logout")
  48.      */
  49.     public function logout(): void
  50.     {
  51.         throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
  52.     }
  53.     /**
  54.      * @Route("/password-reset", name="app_password_reset")
  55.      */
  56.     public function resetPassword(Request $requestMailerInterface $mailer)
  57.     {
  58.         $email $request->query->get('email');
  59.         $user $this->getDoctrine()->getRepository(User::class)->findOneBy(['email' => $email]);
  60.         
  61.         if (!$user) {
  62.             $this->logger->info('Password reset attempt for unknown email', ['email' => $email]);
  63.             return $this->redirectToRoute('app_login', ['error' => 'Email inconnu']);
  64.         }
  65.         $token bin2hex(random_bytes(32));
  66.         $user->setResetToken($token);
  67.         $user->setResetTokenExpiresAt(new \DateTime('+1 hour'));
  68.         $entityManager $this->getDoctrine()->getManager();
  69.         $entityManager->persist($user);
  70.         $entityManager->flush();
  71.         $resetUrl $this->generateUrl('app_reset_password', ['token' => $token], UrlGeneratorInterface::ABSOLUTE_URL);
  72.         $mail = (new Email())
  73.             ->from('contact@flexenergie.fr')
  74.             ->to($email)
  75.             ->subject('Réinitialisation de mot de passe')
  76.             ->html($this->renderView(
  77.                 'email/reset_password.html.twig',
  78.                 ['resetUrl' => $resetUrl]
  79.             ));
  80.         try {
  81.             $mailer->send($mail);
  82.             $this->logger->info('Password reset email sent', ['email' => $email]);
  83.             $this->addFlash('success''Un e-mail de réinitialisation a été envoyé à votre adresse.');
  84.         } catch (TransportExceptionInterface $e) {
  85.             $this->logger->error('Failed to send password reset email', ['email' => $email'error' => $e->getMessage()]);
  86.             $this->addFlash('error''Une erreur est survenue lors de l\'envoi de l\'e-mail. Veuillez réessayer plus tard.');
  87.         }
  88.         return $this->redirectToRoute('app_login');
  89.     }
  90.     /**
  91.      * @Route("/reset-password/{token}", name="app_reset_password")
  92.      */
  93.     public function resetPasswordForm(Request $requeststring $tokenUserPasswordEncoderInterface $passwordEncoder)
  94.     {
  95.         $user $this->getDoctrine()->getRepository(User::class)->findOneBy(['resetToken' => $token]);
  96.         if (!$user || $user->getResetTokenExpiresAt() < new \DateTime()) {
  97.             $this->addFlash('reset_password_error''Le lien de réinitialisation est invalide ou a expiré.');
  98.             return $this->redirectToRoute('app_login');
  99.         }
  100.         $form $this->createFormBuilder()
  101.             ->add('plainPassword'RepeatedType::class, [
  102.                 'type' => PasswordType::class,
  103.                 'first_options' => [
  104.                     'constraints' => [
  105.                         new NotBlank([
  106.                             'message' => 'Veuillez entrer un mot de passe',
  107.                         ]),
  108.                         new Length([
  109.                             'min' => 6,
  110.                             'minMessage' => 'Votre mot de passe doit comporter au moins {{ limit }} caractères',
  111.                             'max' => 4096,
  112.                         ]),
  113.                     ],
  114.                     'label' => 'Nouveau mot de passe',
  115.                 ],
  116.                 'second_options' => [
  117.                     'label' => 'Répéter le mot de passe',
  118.                 ],
  119.                 'invalid_message' => 'Les champs du mot de passe doivent correspondre.',
  120.                 'mapped' => false,
  121.             ])
  122.             ->getForm();
  123.         $form->handleRequest($request);
  124.         if ($form->isSubmitted() && $form->isValid()) {
  125.             $newPassword $form->get('plainPassword')->getData();
  126.             $user->setPassword($passwordEncoder->encodePassword($user$newPassword));
  127.             $user->setResetToken(null);
  128.             $user->setResetTokenExpiresAt(null);
  129.             $entityManager $this->getDoctrine()->getManager();
  130.             $entityManager->persist($user);
  131.             $entityManager->flush();
  132.             $this->addFlash('success''Votre mot de passe a été mis à jour avec succès.');
  133.             return $this->redirectToRoute('app_login');
  134.         }
  135.         return $this->render('security/reset_password.html.twig', [
  136.             'resetForm' => $form->createView(),
  137.         ]);
  138.     }
  139.     /**
  140.      * @Route("/password-change", name="app_password_change")
  141.      */
  142.     public function changePassword()
  143.     {
  144.         return $this->render('security/change_password.html.twig');
  145.     }
  146.     /**
  147.      * @Route("/password-update", name="app_password_update")
  148.      */
  149.     public function updatePassword(Request $requestUserPasswordEncoderInterface $passwordEncoderUserInterface $user)
  150.     {
  151.         $new_password $request->request->get('new_password');
  152.         $user->setPassword($passwordEncoder->encodePassword($user$new_password));
  153.         $entityManager $this->getDoctrine()->getManager();
  154.         $entityManager->persist($user);
  155.         $entityManager->flush();
  156.         $this->addFlash('success''Mot de passe mis à jour avec succès.');
  157.         return $this->redirectToRoute('app_login');
  158.     }
  159. }