fix: onglet Securite - un seul bouton qui génère + envoie le lien au client

Remplace les 2 sections (changer mot de passe + générer temporaire) par
un seul bouton "Envoyer un lien de reinitialisation" qui :
1. Génère un mot de passe temporaire (bin2hex 16 chars)
2. Hash et stocke dans User (password + tempPassword)
3. Envoie l'email bienvenue avec le lien set_password au client

Plus de champ mot de passe à saisir manuellement — tout est automatique.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-04-04 21:19:20 +02:00
parent 42ab59ce07
commit 9316743ac6
2 changed files with 16 additions and 41 deletions

View File

@@ -351,7 +351,7 @@ class ClientsController extends AbstractController
}
#[Route('/{id}', name: 'show')]
public function show(Customer $customer, Request $request, EntityManagerInterface $em, OvhService $ovhService, CloudflareService $cloudflareService, DnsCheckService $dnsCheckService, EsyMailService $esyMailService, UserPasswordHasherInterface $passwordHasher): Response
public function show(Customer $customer, Request $request, EntityManagerInterface $em, OvhService $ovhService, CloudflareService $cloudflareService, DnsCheckService $dnsCheckService, EsyMailService $esyMailService, UserPasswordHasherInterface $passwordHasher, MailerService $mailer, Environment $twig): Response
{
$tab = $request->query->getString('tab', 'info');
@@ -373,7 +373,7 @@ class ClientsController extends AbstractController
}
if ('POST' === $request->getMethod() && 'securite' === $tab) {
return $this->handleSecurityForm($request, $customer, $em, $passwordHasher);
return $this->handleSecurityForm($request, $customer, $em, $passwordHasher, $mailer, $twig);
}
$this->ensureDefaultContact($customer, $em);
@@ -521,22 +521,19 @@ class ClientsController extends AbstractController
}
}
private function handleSecurityForm(Request $request, Customer $customer, EntityManagerInterface $em, UserPasswordHasherInterface $passwordHasher): Response
private function handleSecurityForm(Request $request, Customer $customer, EntityManagerInterface $em, UserPasswordHasherInterface $passwordHasher, MailerService $mailer, Environment $twig): Response
{
$action = $request->request->getString('security_action');
$user = $customer->getUser();
if ('reset_password' === $action) {
$newPassword = $request->request->getString('new_password');
if ('send_reset_password' === $action) {
$tempPassword = bin2hex(random_bytes(8));
$user->setPassword($passwordHasher->hashPassword($user, $tempPassword));
$user->setTempPassword($tempPassword);
$em->flush();
if (\strlen($newPassword) < 8) {
$this->addFlash('error', 'Le mot de passe doit contenir au moins 8 caracteres.');
} else {
$user->setPassword($passwordHasher->hashPassword($user, $newPassword));
$user->clearTempPassword();
$em->flush();
$this->addFlash('success', 'Mot de passe modifie.');
}
$this->sendWelcomeEmail($mailer, $twig, $user);
$this->addFlash('success', 'Un email de reinitialisation a ete envoye a '.$user->getEmail().'.');
}
if ('disable_2fa' === $action) {
@@ -548,14 +545,6 @@ class ClientsController extends AbstractController
$this->addFlash('success', 'Authentification a deux facteurs desactivee.');
}
if ('generate_temp_password' === $action) {
$tempPassword = bin2hex(random_bytes(8));
$user->setPassword($passwordHasher->hashPassword($user, $tempPassword));
$user->setTempPassword($tempPassword);
$em->flush();
$this->addFlash('success', 'Mot de passe temporaire genere : '.$tempPassword.' — Le client devra le changer a sa prochaine connexion.');
}
return $this->redirectToRoute('app_admin_clients_show', ['id' => $customer->getId(), 'tab' => 'securite']);
}

View File

@@ -494,30 +494,16 @@
</div>
</section>
{# Changer le mot de passe #}
<section class="glass p-6 mb-6">
<h2 class="text-sm font-bold uppercase tracking-wider mb-4">Changer le mot de passe</h2>
<form method="post" action="{{ path('app_admin_clients_show', {id: customer.id, tab: 'securite'}) }}" class="flex flex-wrap items-end gap-4">
<input type="hidden" name="security_action" value="reset_password">
<div class="flex-1 min-w-[250px]">
<label for="new_password" class="block text-xs font-bold uppercase tracking-wider mb-2">Nouveau mot de passe *</label>
<input type="password" id="new_password" name="new_password" required minlength="8" placeholder="Min. 8 caracteres"
class="w-full px-4 py-3 input-glass text-sm font-medium">
</div>
<button type="submit" class="px-5 py-3 btn-gold text-xs font-bold uppercase tracking-wider text-gray-900">Modifier le mot de passe</button>
</form>
</section>
{# Generer mot de passe temporaire #}
{# Reinitialiser mot de passe #}
<section class="glass p-6 mb-6">
<div class="flex items-center justify-between">
<div>
<h2 class="text-sm font-bold uppercase tracking-wider">Generer un mot de passe temporaire</h2>
<p class="text-[10px] text-gray-400 mt-1">Genere un nouveau mot de passe et l'affiche. Le client devra le changer a sa prochaine connexion. Utile pour renvoyer un email de bienvenue.</p>
<h2 class="text-sm font-bold uppercase tracking-wider">Reinitialiser le mot de passe</h2>
<p class="text-[10px] text-gray-400 mt-1">Genere un nouveau mot de passe temporaire et envoie un email au client avec un lien pour choisir son mot de passe.</p>
</div>
<form method="post" action="{{ path('app_admin_clients_show', {id: customer.id, tab: 'securite'}) }}" data-confirm="Generer un nouveau mot de passe temporaire ? L'ancien mot de passe sera invalide.">
<input type="hidden" name="security_action" value="generate_temp_password">
<button type="submit" class="px-5 py-3 glass text-indigo-600 font-bold uppercase text-xs tracking-wider hover:bg-indigo-600 hover:text-white transition-all">Generer</button>
<form method="post" action="{{ path('app_admin_clients_show', {id: customer.id, tab: 'securite'}) }}" data-confirm="Reinitialiser le mot de passe de {{ customer.fullName }} ? Un email sera envoye au client.">
<input type="hidden" name="security_action" value="send_reset_password">
<button type="submit" class="px-5 py-3 btn-gold text-xs font-bold uppercase tracking-wider text-gray-900">Envoyer un lien de reinitialisation</button>
</form>
</div>
</section>