feat(ReserverController): Implémente la fonctionnalité de réinitialisation de mot de passe.

This commit is contained in:
Serreau Jovann
2026-01-23 09:20:53 +01:00
parent 3250f6da36
commit ab3fba7a9c
3 changed files with 177 additions and 4 deletions

View File

@@ -8,6 +8,7 @@ use App\Entity\Product;
use App\Form\RequestPasswordConfirmType;
use App\Form\RequestPasswordRequestType;
use App\Logger\AppLogger;
use App\Repository\CustomerRepository;
use App\Repository\ProductRepository;
use App\Service\Mailer\Mailer;
use App\Service\ResetPassword\Event\ResetPasswordConfirmEvent;
@@ -128,11 +129,80 @@ class ReserverController extends AbstractController
]);
}
#[Route('/reservation/creation-compte', name: 'reservation_password')]
public function revervationForgot(): Response
{
return $this->render('revervation/password.twig',[
#[Route('/reservation/mot-de-passe', name: 'reservation_password')]
public function forgotPassword(
Request $request,
CustomerRepository $repository,
EntityManagerInterface $em,
Mailer $mailer,
UserPasswordHasherInterface $hasher
): Response {
$session = $request->getSession();
$step = $request->query->get('step', 'request');
if ($request->isMethod('POST')) {
$payload = $request->getPayload();
// ÉTAPE 1 : Générer le code et l'envoyer
if ($payload->has('email_request')) {
$email = $payload->getString('email_request');
$customer = $repository->findOneBy(['email' => $email]);
if ($customer) {
$code = str_pad((string)random_int(0, 999999), 6, '0', STR_PAD_LEFT);
// On stocke en session : email + code
$session->set('reset_password', [
'email' => $email,
'code' => $code,
'expires' => time() + 900 // Valable 15 minutes
]);
$mailer->send($customer->getEmail(),
$customer->getName()." ".$customer->getSurname(),
"[Ludikevent] - Code de récupération",
"mails/code_password.twig",[
'code' => $code
]);
return $this->redirectToRoute('reservation_password', ['step' => 'verify']);
}
$this->addFlash('danger', 'Email inconnu.');
}
// ÉTAPE 2 : Vérifier le code en session
if ($payload->has('code_verify')) {
$data = $session->get('reset_password');
$inputCode = $payload->getString('code_verify');
if ($data && $data['code'] === $inputCode && time() < $data['expires']) {
return $this->redirectToRoute('reservation_password', ['step' => 'reset']);
}
$this->addFlash('danger', 'Code invalide ou expiré.');
}
// ÉTAPE 3 : Changer le mot de passe
if ($payload->has('new_password')) {
$data = $session->get('reset_password');
if ($data) {
$customer = $repository->findOneBy(['email' => $data['email']]);
if ($customer) {
$newEncoded = $hasher->hashPassword($customer, $payload->getString('new_password'));
$customer->setPassword($newEncoded);
$em->flush();
$session->remove('reset_password'); // On nettoie la session
$this->addFlash('success', 'Mot de passe mis à jour !');
return $this->redirectToRoute('reservation_login');
}
}
}
}
return $this->render('reservation/password.twig', [
'step' => $step,
'email' => $session->get('reset_password')['email'] ?? null
]);
}
#[Route('/reservation/contact', name: 'reservation_contact')]

View File

@@ -0,0 +1,33 @@
{% extends 'mails/base.twig' %}
{% block content %}
<mj-section>
<mj-column background-color="#ffffff" padding="30px" border-radius="20px">
<mj-text align="center" font-size="24px" font-weight="900" color="#111827">
Réinitialisation de mot de passe
</mj-text>
<mj-text align="center">
Vous avez demandé la réinitialisation de votre mot de passe. Voici votre code de vérification unique :
</mj-text>
<mj-section css-class="code-box" padding="20px">
<mj-column>
<mj-text align="center" font-size="42px" font-weight="900" color="#2563eb" letter-spacing="10px">
{{ datas.code }}
</mj-text>
</mj-column>
</mj-section>
<mj-text align="center" font-size="13px" color="#9ca3af" padding-top="20px">
Ce code est valable pendant 15 minutes. <br/> Si vous n'êtes pas à l'origine de cette demande, ignorez cet e-mail.
</mj-text>
<mj-divider border-width="1px" border-color="#f3f4f6" padding-top="20px" />
<mj-text align="center" font-size="12px" color="#d1d5db">
Ludik Event - Location de structures gonflables et matériel festif.
</mj-text>
</mj-column>
</mj-section>
{% endblock %}

View File

@@ -0,0 +1,70 @@
{% extends 'revervation/base.twig' %}
{% block title %}Récupération de mot de passe | Ludik Event{% endblock %}
{% block body %}
<div class="max-w-md mx-auto my-20 px-4">
{# Affichage des erreurs (ex: Email inconnu, Code invalide) #}
{% for label, messages in app.flashes %}
{% for message in messages %}
<div class="mb-4 p-4 rounded-2xl bg-red-50 border border-red-100 text-red-600 text-sm font-bold text-center animate-bounce">
{{ message }}
</div>
{% endfor %}
{% endfor %}
<div class="bg-white rounded-[2.5rem] p-10 shadow-2xl shadow-blue-100 border border-gray-50">
{% if step == 'request' %}
<div class="text-center mb-8">
<h2 class="text-3xl font-black text-gray-900">Oubli ?</h2>
<p class="text-gray-400 mt-2">Entrez votre mail pour recevoir un code.</p>
</div>
<form method="POST" class="space-y-4">
<input type="email" name="email_request" placeholder="votre@email.com" required
class="w-full bg-gray-50 border-none rounded-2xl px-6 py-4 focus:ring-2 focus:ring-blue-500 outline-none">
<button type="submit" class="w-full bg-blue-600 text-white font-bold py-4 rounded-2xl shadow-lg shadow-blue-200 hover:bg-blue-700 transition-all">
Envoyer le code
</button>
</form>
{% elseif step == 'verify' %}
<div class="text-center mb-8">
<h2 class="text-3xl font-black text-gray-900">Vérification</h2>
<p class="text-gray-400 mt-2">Saisissez le code à 6 chiffres reçu par mail.</p>
</div>
<form method="POST" class="space-y-6">
<div class="flex justify-center">
<input type="text" name="code_verify" maxlength="6" placeholder="······" required autofocus
class="w-full text-center text-4xl font-black tracking-[0.3em] bg-gray-50 border-none rounded-2xl py-5 focus:ring-2 focus:ring-blue-500 outline-none">
</div>
<button type="submit" class="w-full bg-gray-900 text-white font-bold py-4 rounded-2xl shadow-lg hover:bg-black transition-all">
Valider le code
</button>
<p class="text-center">
<a href="{{ path('reservation_password', {step: 'request'}) }}" class="text-xs text-blue-500 hover:underline">Renvoyer un code</a>
</p>
</form>
{% elseif step == 'reset' %}
<div class="text-center mb-8">
<h2 class="text-3xl font-black text-gray-900">Nouveau</h2>
<p class="text-gray-400 mt-2">Choisissez votre nouveau mot de passe.</p>
</div>
<form method="POST" class="space-y-4">
<input type="password" name="new_password" placeholder="Minimum 6 caractères" required autofocus
class="w-full bg-gray-50 border-none rounded-2xl px-6 py-4 focus:ring-2 focus:ring-blue-500 outline-none">
<button type="submit" class="w-full bg-green-600 text-white font-bold py-4 rounded-2xl shadow-lg shadow-green-200 hover:bg-green-700 transition-all">
Réinitialiser
</button>
</form>
{% endif %}
<div class="mt-8 text-center border-t border-gray-50 pt-6">
<a href="{{ path('reservation_login') }}" class="text-sm font-bold text-gray-400 hover:text-blue-600 transition-colors">
← Retour à la connexion
</a>
</div>
</div>
</div>
{% endblock %}