Checkpoint: Migration complète vers l'authentification locale avec email/mot de passe

 Modifications apportées :
- Remplacement de l'authentification OAuth Manus par un système local
- Ajout des champs email, password, emailVerified dans la table users
- Implémentation du hashage des mots de passe avec bcrypt
- Création des procédures auth.login et auth.register
- Mise à jour du système de context pour utiliser JWT
- Création des pages de connexion et d'inscription
- Mise à jour de la page AdminUsers pour créer des utilisateurs avec mot de passe
- Ajout de la protection des routes d'administration (vérification du rôle admin)

 Tests effectués :
- Connexion avec email/mot de passe ✓
- Création d'utilisateurs via l'interface d'administration ✓
- Protection des routes (seuls les admins peuvent accéder au dashboard) ✓
- Redirection automatique après connexion ✓

Note : Les fichiers OAuth Manus originaux ont été conservés pour référence mais ne sont plus utilisés.
This commit is contained in:
Manus Sandbox
2025-11-19 05:35:17 -05:00
parent 934edc63cd
commit cc0bd97248
16 changed files with 212 additions and 20 deletions

View File

@@ -55,7 +55,7 @@ export const appRouter = router({
// Définir le cookie de session
const cookieOptions = getSessionCookieOptions(ctx.req);
ctx.res.cookie(COOKIE_NAME, token, cookieOptions);
ctx.res.cookie(COOKIE_NAME, token, { ...cookieOptions, maxAge: 30 * 24 * 60 * 60 * 1000 }); // 30 jours
return { success: true, userId };
}),
@@ -79,8 +79,16 @@ export const appRouter = router({
throw new TRPCError({ code: 'FORBIDDEN', message: 'Votre compte a été désactivé' });
}
// Vérifier que le mot de passe existe
if (!user.password) {
console.error('[LOGIN] User has no password:', user.email);
throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Email ou mot de passe incorrect' });
}
// Vérifier le mot de passe
console.log('[LOGIN] Verifying password for:', user.email);
const isValid = await verifyPassword(input.password, user.password);
console.log('[LOGIN] Password valid:', isValid);
if (!isValid) {
throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Email ou mot de passe incorrect' });
}
@@ -93,7 +101,7 @@ export const appRouter = router({
// Définir le cookie de session
const cookieOptions = getSessionCookieOptions(ctx.req);
ctx.res.cookie(COOKIE_NAME, token, cookieOptions);
ctx.res.cookie(COOKIE_NAME, token, { ...cookieOptions, maxAge: 30 * 24 * 60 * 60 * 1000 }); // 30 jours
return { success: true, user: { id: user.id, email: user.email, name: user.name, role: user.role } };
}),
@@ -626,13 +634,32 @@ export const appRouter = router({
}),
create: adminProcedure.input(z.object({
openId: z.string().min(1),
email: z.string().email(),
password: z.string().min(6),
name: z.string().optional(),
email: z.string().email().optional(),
role: z.enum(["user", "admin"]).default("user"),
isActive: z.boolean().default(true),
})).mutation(async ({ input }) => {
await db.createUser(input);
const { hashPassword } = await import("./_core/auth");
// Vérifier si l'utilisateur existe déjà
const existingUser = await db.getUserByEmail(input.email);
if (existingUser) {
throw new TRPCError({ code: 'CONFLICT', message: 'Un compte existe déjà avec cet email' });
}
// Hasher le mot de passe
const hashedPassword = await hashPassword(input.password);
// Créer l'utilisateur
await db.createUser({
email: input.email,
password: hashedPassword,
name: input.name,
emailVerified: false,
role: input.role,
isActive: input.isActive,
});
return { success: true };
}),