docs(admin): add README documentation for admin and auth features
- add comprehensive README for admin feature covering structure, API, registry, and extension points - add comprehensive README for auth feature covering structure, API, and usage examples
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
# Auth
|
||||
|
||||
Ce répertoire gère l'authentification : inscription, connexion, sessions, réinitialisation de mot de passe, vérification d'adresse courriel et gestion du profil. Il expose des server actions Next.js, des routes API REST et des composants de pages prêts à l'emploi.
|
||||
|
||||
---
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
src/features/auth/
|
||||
├── index.js barrel serveur
|
||||
├── actions.js server actions Next.js ('use server')
|
||||
├── api.js routes API REST (users, roles)
|
||||
├── auth.js register, login, resetPassword, updateUser
|
||||
├── session.js createSession, validateSession, deleteSession
|
||||
├── email.js tokens de vérification + envoi des e-mails
|
||||
├── password.js hashPassword, verifyPassword, generateToken
|
||||
├── db.js createTables, dropTables
|
||||
├── storage-policies.js politiques d'accès au stockage
|
||||
├── AuthPage.server.js page RSC racine (route catch-all)
|
||||
├── AuthPage.client.js shell client
|
||||
├── GUIDE-custom-login.md guide pour les pages personnalisées
|
||||
├── components/
|
||||
│ └── AuthPageHeader.js
|
||||
├── pages/
|
||||
│ ├── index.js re-export
|
||||
│ ├── LoginPage.client.js
|
||||
│ ├── RegisterPage.client.js
|
||||
│ ├── ForgotPasswordPage.client.js
|
||||
│ ├── ResetPasswordPage.client.js
|
||||
│ ├── ConfirmEmailPage.client.js
|
||||
│ └── LogoutPage.client.js
|
||||
└── templates/
|
||||
├── VerificationEmail.js
|
||||
├── PasswordResetEmail.js
|
||||
├── PasswordChangedEmail.js
|
||||
├── EmailChangeConfirmEmail.js
|
||||
└── EmailChangeNotifyEmail.js
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Import
|
||||
|
||||
```js
|
||||
import { getSession, loginAction, logoutAction } from '@zen/core/features/auth/actions';
|
||||
import { LoginPage, RegisterPage } from '@zen/core/features/auth/pages';
|
||||
import { validateSession, createSession } from '@zen/core/features/auth';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pages intégrées
|
||||
|
||||
La route catch-all `app/auth/[...auth]/page.js` suffit pour exposer toutes les pages sans configuration supplémentaire.
|
||||
|
||||
```js
|
||||
// app/auth/[...auth]/page.js
|
||||
export { default } from '@zen/core/features/auth/server';
|
||||
```
|
||||
|
||||
| Route | Page |
|
||||
|-------|------|
|
||||
| `/auth/login` | Connexion |
|
||||
| `/auth/register` | Inscription |
|
||||
| `/auth/forgot` | Mot de passe oublié |
|
||||
| `/auth/reset` | Réinitialisation du mot de passe |
|
||||
| `/auth/confirm` | Vérification de l'adresse courriel |
|
||||
| `/auth/logout` | Déconnexion |
|
||||
|
||||
---
|
||||
|
||||
## Server actions
|
||||
|
||||
Toutes les actions sont dans `@zen/core/features/auth/actions`. Elles attendent un `FormData` sauf `getSession`, `setSessionCookie` et `refreshSessionCookie`.
|
||||
|
||||
### `getSession()`
|
||||
|
||||
Lit le cookie de session et retourne la session courante, ou `null` si l'utilisateur n'est pas connecté. Renouvelle automatiquement le cookie si la session a été rafraîchie.
|
||||
|
||||
```js
|
||||
const session = await getSession();
|
||||
if (!session?.user) redirect('/auth/login');
|
||||
// session.user, session.session disponibles
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `loginAction(formData)`
|
||||
|
||||
Authentifie l'utilisateur et pose un cookie `HttpOnly`. Applique le rate limiting par IP et les vérifications anti-bot.
|
||||
|
||||
```js
|
||||
const result = await loginAction(formData);
|
||||
// { success: true, user } ou { success: false, error }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `registerAction(formData)`
|
||||
|
||||
Crée un compte et envoie l'e-mail de vérification.
|
||||
|
||||
| Champ | Description |
|
||||
|-------|-------------|
|
||||
| `email` | Adresse courriel |
|
||||
| `password` | Mot de passe |
|
||||
| `name` | Nom d'affichage |
|
||||
|
||||
---
|
||||
|
||||
### `logoutAction()`
|
||||
|
||||
Invalide la session en base et supprime le cookie.
|
||||
|
||||
---
|
||||
|
||||
### `forgotPasswordAction(formData)`
|
||||
|
||||
Envoie un lien de réinitialisation si un compte existe pour l'adresse fournie. La réponse ne révèle pas si le compte existe.
|
||||
|
||||
---
|
||||
|
||||
### `resetPasswordAction(formData)`
|
||||
|
||||
Vérifie le token puis met à jour le mot de passe.
|
||||
|
||||
| Champ | Description |
|
||||
|-------|-------------|
|
||||
| `email` | Adresse courriel |
|
||||
| `token` | Token reçu par e-mail |
|
||||
| `newPassword` | Nouveau mot de passe |
|
||||
|
||||
---
|
||||
|
||||
### `verifyEmailAction(formData)`
|
||||
|
||||
Vérifie le token de confirmation et marque l'adresse comme vérifiée.
|
||||
|
||||
| Champ | Description |
|
||||
|-------|-------------|
|
||||
| `email` | Adresse courriel |
|
||||
| `token` | Token reçu par e-mail |
|
||||
|
||||
---
|
||||
|
||||
### `setSessionCookie(token)`
|
||||
|
||||
Valide le token contre la base avant de l'écrire dans le cookie `HttpOnly`. À utiliser après une authentification externe ou OAuth.
|
||||
|
||||
---
|
||||
|
||||
### `refreshSessionCookie(token)`
|
||||
|
||||
Revalide le token et prolonge la durée de vie du cookie (30 jours).
|
||||
|
||||
---
|
||||
|
||||
## Routes API REST
|
||||
|
||||
Les routes sont enregistrées automatiquement sous le préfixe `/zen/api`. L'authentification est appliquée par le routeur avant chaque handler.
|
||||
|
||||
### Utilisateurs
|
||||
|
||||
| Méthode | Route | Auth | Description |
|
||||
|---------|-------|------|-------------|
|
||||
| `GET` | `/zen/api/users` | admin | Liste paginée des utilisateurs |
|
||||
| `GET` | `/zen/api/users/:id` | admin | Détail d'un utilisateur |
|
||||
| `PUT` | `/zen/api/users/:id` | admin | Modifier `name`, `role`, `email_verified` |
|
||||
| `PUT` | `/zen/api/users/:id/email` | admin | Changer l'adresse courriel |
|
||||
| `PUT` | `/zen/api/users/:id/password` | admin | Définir un mot de passe |
|
||||
| `POST` | `/zen/api/users/:id/send-password-reset` | admin | Envoyer un lien de réinitialisation |
|
||||
| `GET` | `/zen/api/users/:id/roles` | admin | Lister les rôles de l'utilisateur |
|
||||
| `POST` | `/zen/api/users/:id/roles` | admin | Assigner un rôle |
|
||||
| `DELETE` | `/zen/api/users/:id/roles/:roleId` | admin | Révoquer un rôle |
|
||||
|
||||
### Profil (utilisateur connecté)
|
||||
|
||||
| Méthode | Route | Description |
|
||||
|---------|-------|-------------|
|
||||
| `PUT` | `/zen/api/users/profile` | Modifier le nom |
|
||||
| `POST` | `/zen/api/users/profile/email` | Initier un changement d'adresse courriel |
|
||||
| `GET` | `/zen/api/users/email/confirm` | Confirmer le changement d'adresse |
|
||||
| `POST` | `/zen/api/users/profile/password` | Changer le mot de passe |
|
||||
| `POST` | `/zen/api/users/profile/picture` | Téléverser une photo de profil |
|
||||
| `DELETE` | `/zen/api/users/profile/picture` | Supprimer la photo de profil |
|
||||
| `GET` | `/zen/api/users/profile/sessions` | Lister les sessions actives |
|
||||
| `DELETE` | `/zen/api/users/profile/sessions` | Révoquer toutes les sessions |
|
||||
| `DELETE` | `/zen/api/users/profile/sessions/:sessionId` | Révoquer une session |
|
||||
|
||||
### Rôles
|
||||
|
||||
| Méthode | Route | Description |
|
||||
|---------|-------|-------------|
|
||||
| `GET` | `/zen/api/roles` | Lister les rôles |
|
||||
| `POST` | `/zen/api/roles` | Créer un rôle |
|
||||
| `GET` | `/zen/api/roles/:id` | Détail d'un rôle |
|
||||
| `PUT` | `/zen/api/roles/:id` | Modifier un rôle |
|
||||
| `DELETE` | `/zen/api/roles/:id` | Supprimer un rôle |
|
||||
|
||||
---
|
||||
|
||||
## Sécurité
|
||||
|
||||
**Rate limiting par IP.** Les actions `register`, `login`, `forgot_password`, `reset_password` et `verify_email` sont limitées par adresse IP. Quand l'IP est inconnue (pas de proxy configuré), le rate limiting est suspendu et un avertissement opérateur est émis une seule fois. Activer avec `ZEN_TRUST_PROXY=true` derrière un reverse proxy vérifié.
|
||||
|
||||
**Champs anti-bot.** Chaque formulaire embarque un champ honeypot (`_hp`) et un timestamp de chargement (`_t`). Une soumission trop rapide (moins de 1,5 s), trop ancienne (plus de 10 min) ou avec un honeypot rempli est rejetée.
|
||||
|
||||
**Cookie HttpOnly.** Le token de session n'est jamais exposé à JavaScript. `setSessionCookie` et `refreshSessionCookie` valident le token en base avant d'écrire le cookie pour éviter qu'un token arbitraire soit accepté.
|
||||
|
||||
**Erreurs opaques.** Les erreurs internes sont loguées côté serveur et remplacées par un message générique côté client. Seules les `UserFacingError` (token expiré, etc.) remontent verbatim.
|
||||
|
||||
---
|
||||
|
||||
## Base de données
|
||||
|
||||
`db.js` expose `createTables()` et `dropTables()`, appelés par `initializeZen()`.
|
||||
|
||||
| Table | Contenu |
|
||||
|-------|---------|
|
||||
| `zen_auth_users` | Utilisateurs (`id`, `email`, `name`, `role`, `email_verified`, `image`) |
|
||||
| `zen_auth_sessions` | Sessions actives avec IP et user-agent |
|
||||
| `zen_auth_accounts` | Comptes liés à un provider (credential, OAuth) |
|
||||
| `zen_auth_verifications` | Tokens de vérification d'e-mail et de réinitialisation |
|
||||
|
||||
---
|
||||
|
||||
## Pages personnalisées
|
||||
|
||||
Pour envelopper les pages auth dans un layout existant, voir [GUIDE-custom-login.md](./GUIDE-custom-login.md). Le guide couvre le pattern serveur/client, les props de chaque composant et la protection de route.
|
||||
Reference in New Issue
Block a user