Implémentation complète du flux de réinitialisation de mot de passe (Story 1.5): Backend: - Aggregate PasswordResetToken avec TTL 1h, UUID v7, usage unique - Endpoint POST /api/password/forgot avec rate limiting (3/h par email, 10/h par IP) - Endpoint POST /api/password/reset avec validation token - Templates email (demande + confirmation) - Repository Redis avec TTL 2h pour distinguer expiré/invalide Frontend: - Page /mot-de-passe-oublie avec message générique (anti-énumération) - Page /reset-password/[token] avec validation temps réel des critères - Gestion erreurs: token invalide, expiré, déjà utilisé Tests: - 14 tests unitaires PasswordResetToken - 7 tests unitaires RequestPasswordResetHandler - 7 tests unitaires ResetPasswordHandler - Tests E2E Playwright pour le flux complet
48 lines
1.6 KiB
YAML
48 lines
1.6 KiB
YAML
framework:
|
|
messenger:
|
|
# Uncomment this (and the failed transport below) to send failed messages to this transport for later handling.
|
|
failure_transport: failed
|
|
|
|
# Three buses: Command, Query, Event (CQRS + Event-driven)
|
|
default_bus: command.bus
|
|
|
|
buses:
|
|
command.bus:
|
|
default_middleware: true
|
|
middleware:
|
|
- doctrine_transaction
|
|
|
|
query.bus:
|
|
default_middleware: true
|
|
|
|
event.bus:
|
|
default_middleware:
|
|
allow_no_handlers: true
|
|
|
|
transports:
|
|
# https://symfony.com/doc/current/messenger.html#transport-configuration
|
|
async:
|
|
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
|
|
options:
|
|
exchange:
|
|
name: classeo_messages
|
|
type: topic
|
|
queues:
|
|
messages:
|
|
binding_keys: ['#']
|
|
retry_strategy:
|
|
max_retries: 3
|
|
delay: 1000
|
|
multiplier: 2
|
|
max_delay: 60000
|
|
|
|
failed:
|
|
dsn: 'doctrine://default?queue_name=failed'
|
|
|
|
routing:
|
|
# Route your messages to the transports
|
|
# Password reset events are async to prevent timing attacks (email enumeration)
|
|
# and to improve API response time
|
|
'App\Administration\Domain\Event\PasswordResetTokenGenerated': async
|
|
'App\Administration\Domain\Event\MotDePasseChange': async
|