src/Controller/SecurityController.php line 104

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\Mime\Address;
  13. use Symfony\Component\Mailer\Transport;
  14. use Symfony\Component\Mailer\Mailer;
  15. use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
  16. use Psr\Log\LoggerInterface;
  17. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  18. use Symfony\Component\Form\Extension\Core\Type\PasswordType;
  19. use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
  20. use Symfony\Component\Validator\Constraints\Length;
  21. use Symfony\Component\Validator\Constraints\NotBlank;
  22. class SecurityController extends AbstractController
  23. {
  24.     private $logger;
  25.     public function __construct(LoggerInterface $logger)
  26.     {
  27.         $this->logger $logger;
  28.     }
  29.     /**
  30.      * @Route("/login", name="app_login")
  31.      */
  32.     public function login(AuthenticationUtils $authenticationUtilsRequest $request): Response
  33.     {
  34.         $this->logger->info('Login page accessed', [
  35.             'method' => $request->getMethod(),
  36.             'host' => $request->getHost()
  37.         ]);
  38.         // Si l'utilisateur est déjà connecté
  39.         if ($this->getUser()) {
  40.             $this->logger->info('User already logged in', [
  41.                 'user' => $this->getUser()->getUserIdentifier(),
  42.                 'roles' => $this->getUser()->getRoles()
  43.             ]);
  44.             // Si on est sur flexenergie.pro et que l'utilisateur a le rôle ROLE_CLIENT_PRO
  45.             if (str_contains($request->getHost(), 'flexenergie.pro') && 
  46.                 in_array('ROLE_CLIENT_PRO'$this->getUser()->getRoles())) {
  47.                 return $this->redirectToRoute('pro_dashboard');
  48.             }
  49.             // Sinon, redirection par défaut
  50.             return $this->redirectToRoute('app_home');
  51.         }
  52.         // get the login error if there is one
  53.         $error $authenticationUtils->getLastAuthenticationError();
  54.         // last username entered by the user
  55.         $lastUsername $authenticationUtils->getLastUsername();
  56.         if ($error) {
  57.             $this->logger->warning('Login error', ['error' => $error->getMessage()]);
  58.         }
  59.         // Déterminer quel template utiliser selon le domaine
  60.         $template str_contains($request->getHost(), 'flexenergie.pro'
  61.             ? 'security/pro_login.html.twig'
  62.             'security/login.html.twig';
  63.         return $this->render($template, [
  64.             'last_username' => $lastUsername,
  65.             'error' => $error,
  66.             'is_pro_site' => str_contains($request->getHost(), 'flexenergie.pro')
  67.         ]);
  68.     }
  69.     /**
  70.      * @Route("/logout", name="app_logout")
  71.      */
  72.     public function logout(): void
  73.     {
  74.         throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
  75.     }
  76.     /**
  77.      * @Route("/password-reset", name="app_password_reset")
  78.      */
  79.     public function resetPassword(Request $request)
  80.     {
  81.         $this->logger->info('Password reset route called', [
  82.             'method' => $request->getMethod(),
  83.             'query' => $request->query->all(),
  84.             'headers' => $request->headers->all()
  85.         ]);
  86.         $email $request->query->get('email');
  87.         $this->logger->info('Email from request', ['email' => $email]);
  88.         $user $this->getDoctrine()->getRepository(User::class)->findOneBy(['email' => $email]);
  89.         
  90.         if (!$user) {
  91.             $this->logger->info('Password reset attempt for unknown email', ['email' => $email]);
  92.             return $this->json([
  93.                 'success' => false,
  94.                 'message' => 'Email inconnu'
  95.             ], 404);
  96.         }
  97.         $token bin2hex(random_bytes(32));
  98.         $user->setResetToken($token);
  99.         $user->setResetTokenExpiresAt(new \DateTime('+1 hour'));
  100.         $entityManager $this->getDoctrine()->getManager();
  101.         $entityManager->persist($user);
  102.         $entityManager->flush();
  103.         $resetUrl $this->generateUrl('app_reset_password', ['token' => $token], UrlGeneratorInterface::ABSOLUTE_URL);
  104.         $mail = (new Email())
  105.             ->from(new Address('contact@flexenergie.fr''FlexEnergie'))
  106.             ->to($email)
  107.             ->subject('Réinitialisation de mot de passe')
  108.             ->html($this->renderView(
  109.                 'email/reset_password.html.twig',
  110.                 ['resetUrl' => $resetUrl]
  111.             ));
  112.         $this->logger->info('Email prepared', [
  113.             'from' => 'contact@flexenergie.fr',
  114.             'to' => $email,
  115.             'resetUrl' => $resetUrl
  116.         ]);
  117.         try {
  118.             // Créer le transport et le mailer comme dans le script de test
  119.             $transport Transport::fromDsn($_ENV['MAILER_DSN']);
  120.             $mailer = new Mailer($transport);
  121.             $mailer->send($mail);
  122.             
  123.             return $this->json([
  124.                 'success' => true,
  125.                 'message' => 'Un e-mail de réinitialisation a été envoyé à votre adresse.'
  126.             ]);
  127.         } catch (\Exception $e) {
  128.             $this->logger->error('Failed to send password reset email', [
  129.                 'error' => $e->getMessage(),
  130.                 'trace' => $e->getTraceAsString()
  131.             ]);
  132.             
  133.             return $this->json([
  134.                 'success' => false,
  135.                 'message' => 'Une erreur est survenue lors de l\'envoi de l\'e-mail : ' $e->getMessage()
  136.             ], 500);
  137.         }
  138.     }
  139.     /**
  140.      * @Route("/reset-password/{token}", name="app_reset_password")
  141.      */
  142.     public function resetPasswordForm(Request $requeststring $tokenUserPasswordEncoderInterface $passwordEncoder)
  143.     {
  144.         $user $this->getDoctrine()->getRepository(User::class)->findOneBy(['resetToken' => $token]);
  145.         if (!$user || $user->getResetTokenExpiresAt() < new \DateTime()) {
  146.             $this->addFlash('reset_password_error''Le lien de réinitialisation est invalide ou a expiré.');
  147.             return $this->redirectToRoute('app_login');
  148.         }
  149.         $form $this->createFormBuilder()
  150.             ->add('plainPassword'RepeatedType::class, [
  151.                 'type' => PasswordType::class,
  152.                 'first_options' => [
  153.                     'constraints' => [
  154.                         new NotBlank([
  155.                             'message' => 'Veuillez entrer un mot de passe',
  156.                         ]),
  157.                         new Length([
  158.                             'min' => 6,
  159.                             'minMessage' => 'Votre mot de passe doit comporter au moins {{ limit }} caractères',
  160.                             'max' => 4096,
  161.                         ]),
  162.                     ],
  163.                     'label' => 'Nouveau mot de passe',
  164.                 ],
  165.                 'second_options' => [
  166.                     'label' => 'Répéter le mot de passe',
  167.                 ],
  168.                 'invalid_message' => 'Les champs du mot de passe doivent correspondre.',
  169.                 'mapped' => false,
  170.             ])
  171.             ->getForm();
  172.         $form->handleRequest($request);
  173.         if ($form->isSubmitted() && $form->isValid()) {
  174.             $newPassword $form->get('plainPassword')->getData();
  175.             $user->setPassword($passwordEncoder->encodePassword($user$newPassword));
  176.             $user->setResetToken(null);
  177.             $user->setResetTokenExpiresAt(null);
  178.             $entityManager $this->getDoctrine()->getManager();
  179.             $entityManager->persist($user);
  180.             $entityManager->flush();
  181.             $this->addFlash('success''Votre mot de passe a été mis à jour avec succès.');
  182.             return $this->redirectToRoute('app_login');
  183.         }
  184.         return $this->render('security/reset_password.html.twig', [
  185.             'resetForm' => $form->createView(),
  186.         ]);
  187.     }
  188.     /**
  189.      * @Route("/password-change", name="app_password_change")
  190.      */
  191.     public function changePassword()
  192.     {
  193.         return $this->render('security/change_password.html.twig');
  194.     }
  195.     /**
  196.      * @Route("/password-update", name="app_password_update")
  197.      */
  198.     public function updatePassword(Request $requestUserPasswordEncoderInterface $passwordEncoderUserInterface $user)
  199.     {
  200.         $new_password $request->request->get('new_password');
  201.         $user->setPassword($passwordEncoder->encodePassword($user$new_password));
  202.         $entityManager $this->getDoctrine()->getManager();
  203.         $entityManager->persist($user);
  204.         $entityManager->flush();
  205.         $this->addFlash('success''Mot de passe mis à jour avec succès.');
  206.         return $this->redirectToRoute('app_login');
  207.     }
  208. }