feat: ajout changement de mot de passe + bind mounts persistants + credentials en variables d'env

This commit is contained in:
Claude
2026-05-01 08:55:23 +02:00
parent 6741f9fa75
commit 1c62d6b325
4 changed files with 176 additions and 53 deletions
+41
View File
@@ -31,6 +31,15 @@ const loginSchema = z.object({
password: z.string().min(1, 'Mot de passe requis'),
});
const changePasswordSchema = z.object({
currentPassword: z.string().min(1, 'Mot de passe actuel requis'),
newPassword: z.string().min(8, 'Le nouveau mot de passe doit faire au moins 8 caractères'),
confirmPassword: z.string().min(1, 'Confirmation requise'),
}).refine(data => data.newPassword === data.confirmPassword, {
message: 'Les mots de passe ne correspondent pas',
path: ['confirmPassword'],
});
// ─── Routes ─────────────────────────────────────────────────
/**
@@ -131,4 +140,36 @@ router.get('/me', requireAuth, async (req: AuthRequest, res: Response, next: exp
} catch (err) { next(err); }
});
/**
* PATCH /api/auth/password
* Body: { currentPassword, newPassword, confirmPassword }
* Permet à l'utilisateur connecté de changer son mot de passe.
*/
router.patch('/password', requireAuth, validate(changePasswordSchema), async (req: AuthRequest, res: Response, next: express.NextFunction): Promise<void> => {
try {
const { currentPassword, newPassword } = req.body;
// Récupérer le hash actuel
const result = await db.query('SELECT password_hash FROM users WHERE id = $1', [req.user!.id]);
const user = result.rows[0];
if (!user || !(await bcrypt.compare(currentPassword, user.password_hash))) {
res.status(401).json({ error: 'Mot de passe actuel incorrect' });
return;
}
// Hacher et sauvegarder le nouveau mot de passe
const newHash = await bcrypt.hash(newPassword, 12);
await db.query(
'UPDATE users SET password_hash = $1, updated_at = NOW() WHERE id = $2',
[newHash, req.user!.id]
);
// Révoquer tous les refresh tokens (force reconnexion sur les autres appareils)
await db.query('DELETE FROM refresh_tokens WHERE user_id = $1', [req.user!.id]);
res.json({ success: true });
} catch (err) { next(err); }
});
export default router;