✨ feat(ReserverController): Implémente la fonctionnalité de réinitialisation de mot de passe.
This commit is contained in:
@@ -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')]
|
||||
|
||||
33
templates/mails/code_password.twig
Normal file
33
templates/mails/code_password.twig
Normal 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 %}
|
||||
70
templates/reservation/password.twig
Normal file
70
templates/reservation/password.twig
Normal 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 %}
|
||||
Reference in New Issue
Block a user