Project

General

Profile

Actions

Feature #1144

open
RA

Feature #1133: Implémenter une page de profil utilisateur avec gestion des crédits et des tiers d'abonnement

Fullstack — Changement de mot de passe sécurisé (vérif ancien + email de confirmation)

Feature #1144: Fullstack — Changement de mot de passe sécurisé (vérif ancien + email de confirmation)

Added by Redmine Admin about 2 months ago. Updated about 2 months ago.

Status:
QA
Priority:
Normal
Assignee:
-
Start date:
06/18/2026
Due date:
% Done:

0%

Estimated time:
spec_ref:

issue:1133 — spec in epic + ticket description

build_status:
build_number:
ci_run_url:
scan_status:
scan_report_url:
deploy_status:
preprod_url:
deployed_at:
branch:
feat/1144-password-change
pr_url:
https://github.com/omdev-tech/PipeLiner-Client/pull/71
security_key:
severity:
paused:

Description

## Objectif
Flux complet et sécurisé de changement de mot de passe : endpoint backend (vérification de l'ancien mot de passe + déclenchement de l'email de confirmation) et formulaire frontend dans la page profil.

## Dépendances
Dépend du backend modèle/permissions (#1141) et des notifications email (#1142, pour l'email de confirmation).

## Portée — Backend (`api/`)
- Endpoint authentifié de changement de mot de passe : exige l'ancien mot de passe, le vérifie, applique les règles de robustesse, hashe et persiste le nouveau.
- Émet l'événement « mot de passe changé » consommé par les notifications (#1142) pour l'email de confirmation.
- Rejet 400/401 si l'ancien mot de passe est incorrect; rate-limiting raisonnable.

## Portée — Frontend (`src/`)
- Formulaire sécurisé dans la page « Mon compte » : champs ancien mot de passe, nouveau, confirmation; validation côté client + affichage des erreurs serveur.
- États succès/erreur clairs; clés i18n dans `en.ts` ET `fr.ts`.

## Acceptance criteria
- [ ] Le changement échoue si l'ancien mot de passe est incorrect (erreur explicite).
- [ ] Un mot de passe valide est hashé et persisté; les règles de robustesse sont appliquées.
- [ ] Un email de confirmation est envoyé après un changement réussi (via #1142).
- [ ] Le formulaire valide la confirmation et affiche les erreurs serveur.
- [ ] Clés i18n cohérentes `en.ts`/`fr.ts`.
- [ ] Backend : pytest verts, `ruff check .`, `mypy src` propres. Frontend : `vitest`, `tsc`, `eslint`, `build` verts.


Files

design-1144-before.png (211 KB) design-1144-before.png Redmine Admin, 06/18/2026 01:09 PM
design-1144-after.png (467 KB) design-1144-after.png Redmine Admin, 06/18/2026 01:09 PM
design-1144-mockup.html (6.98 KB) design-1144-mockup.html Redmine Admin, 06/18/2026 01:09 PM
design-1144-before.png
design-1144-after.png

RA Updated by Redmine Admin about 2 months ago Actions #1

  • Status changed from Submitted to Spec
  • spec_ref updated (diff)

RA Updated by Redmine Admin about 2 months ago Actions #5

## Design — Changement de mot de passe sécurisé (#1144)

**Le design visuel est régi par §MC.4 `PasswordChangeForm`** de `docs/design/design-system.md` (déjà spécifié lors du ticket frère #1143, où le formulaire vit dans la page « Mon compte »). Aucune nouvelle section, aucun nouveau token, aucun nouvel atome. Ce ticket ne fait que **valider la couverture des états** et fournir une preuve focalisée.

### Méthodologie Atomic Design
- **Molecule** : `PasswordChangeForm` (§MC.4), composée de 3 atomes `TextInput type="password"` (§7b.2) + 1 atome `Button primary` (§7b.1) + bandeaux feedback (§7b.3). À placer dans l'**organism** page « Mon compte » (§MC.1), colonne gauche. Réutilisation stricte — rien d'inventé.

### États couverts (cf. maquette `design-1144-after.png`)
1. **Repos** — champs vides, bouton `primary` actif.
2. **Saisie + validation côté client** — helper de force sur le nouveau mdp (`text-success-fg` ✓ quand 12+ / majuscule / chiffre / symbole), non-correspondance confirme ≠ nouveau → `border-danger-fg` + helper `text-danger-fg` (`account.pwMismatch`).
3. **Erreur serveur** (ancien mot de passe faux) — bandeau `bg-danger-bg text-danger-fg` `role="alert"` (`account.pwError`), champ actuel en `border-danger-fg`.
4. **Succès + email de confirmation** — bandeau `bg-success-bg text-success-fg` `role="status"` (`account.pwSuccess`) mentionnant **l'email de confirmation envoyé**, champs réinitialisés ; bouton en état `loading` pendant la mutation.

### Ajout (additif, minimal) à §MC.4
Une seule précision ajoutée à MC.4 : le bandeau de succès **mentionne explicitement l'email de confirmation** (conformément au critère d'acceptation #1144). Pas de nouveau token/atome — même bandeau `bg-success-bg text-success-fg`, texte porté par `account.pwSuccess`.

### Clés i18n (déjà définies en §MC.7 — `en.ts` ET `fr.ts`, espace `account`)
`pwHeading`, `pwHint`, `pwCurrent`, `pwNew`, `pwConfirm`, `pwRule`, `pwMismatch`, `pwSubmit`, `pwSuccess`, `pwError`. Aucune nouvelle clé requise (le wording succès « email de confirmation » entre dans `pwSuccess`).

### Preuve avant/après
- `design-1144-after.png` — maquette des 4 états.
- `design-1144-before.png` — **reconstruction** (pas une capture live) : « Mon compte » est un écran neuf ; il n'existe aujourd'hui que le menu Admin / Se déconnecter, aucun self-service de mot de passe.
- `design-1144-mockup.html` — source HTML autonome de la maquette.

Référence visuelle : **§MC.4** (+ tokens §2 / atomes §7b). → Transition **Spec → Design**.

RA Updated by Redmine Admin about 2 months ago Actions #6

  • Status changed from Spec to Design

RA Updated by Redmine Admin about 2 months ago Actions #7

  • Status changed from Design to In development

RA Updated by Redmine Admin about 2 months ago Actions #8

  • Status changed from In development to QA
  • branch set to feat/1144-password-change
  • pr_url set to https://github.com/omdev-tech/PipeLiner-Client/pull/71

PR ouverte vers `dev` : https://github.com/omdev-tech/PipeLiner-Client/pull/71

## Livré
**Backend (`api/`, hexagonal)**
- Endpoint authentifié `POST /auth/me/password` : vérifie l'ancien mot de passe avec le **même hasher Argon2 utilisé au login** (`Argon2Hasher.verify`), applique la politique de robustesse (≥12 caractères + majuscule + chiffre + symbole), hashe et persiste le nouveau. Ancien mot de passe incorrect → **400** ; nouveau trop faible → **422** (règles non remplies). Aucune migration (la colonne `password_hash` existe déjà).
- Nouvel événement de domaine `PasswordChanged`, émis **après le commit** (seam publish-after-commit de #1141), best-effort : un échec de notification ne fait jamais échouer la mutation.
- `NotificationDispatcher` : **une ligne de registre** `PasswordChanged → render_password_changed` (gabarit FR de #1142) → l'email de confirmation est envoyé.

**Frontend (`src/`)**
- Organism `PasswordChangeForm` (§MC.4) monté dans `/account` à l'emplacement `TODO(#1144)` de #1143 : champs ancien / nouveau / confirmation, validation côté client (force + non-correspondance), mutation TanStack Query, bandeau de succès **mentionnant l'email de confirmation**, bandeau d'erreur serveur.
- Hook `useChangePassword`.
- Clés i18n `pw*` ajoutées dans `en.ts` ET `fr.ts`.

## Critères d'acceptation
- [x] Échec si l'ancien mot de passe est incorrect (erreur explicite, 400).
- [x] Mot de passe valide hashé + persisté ; règles de robustesse appliquées.
- [x] Email de confirmation envoyé après un changement réussi (via #1142).
- [x] Le formulaire valide la confirmation et affiche les erreurs serveur.
- [x] Clés i18n cohérentes `en.ts`/`fr.ts`.

## Gates (verts)
- Backend : `pytest` (600 passés, 2× sur une même base) · `ruff check .` · `mypy src`.
- Frontend : `vitest` (603 passés) · `tsc --noEmit` · `eslint .` · `npm run build`.

Branche : `feat/1144-password-change`. Passage **In development → QA**.

Actions

Also available in: PDF Atom