espace-paie-odentas/app/api/auth/password-update/route.ts

82 lines
No EOL
2.9 KiB
TypeScript

import { NextResponse } from "next/server";
import { cookies } from "next/headers";
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { sendPasswordChangedEmail } from "@/lib/emailMigrationHelpers";
export async function POST(req: Request) {
try {
const { newPassword } = await req.json();
// Validation stricte du mot de passe
if (!newPassword || typeof newPassword !== 'string') {
return NextResponse.json({
error: "weak_password",
message: "Mot de passe requis."
}, { status: 400 });
}
const passwordValidation = {
minLength: newPassword.length >= 12,
hasLowercase: /[a-z]/.test(newPassword),
hasUppercase: /[A-Z]/.test(newPassword),
hasNumber: /\d/.test(newPassword),
hasSpecialChar: /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(newPassword),
};
const failedCriteria = [];
if (!passwordValidation.minLength) failedCriteria.push("au moins 12 caractères");
if (!passwordValidation.hasLowercase) failedCriteria.push("une minuscule");
if (!passwordValidation.hasUppercase) failedCriteria.push("une majuscule");
if (!passwordValidation.hasNumber) failedCriteria.push("un chiffre");
if (!passwordValidation.hasSpecialChar) failedCriteria.push("un caractère spécial");
if (failedCriteria.length > 0) {
return NextResponse.json({
error: "weak_password",
message: `Le mot de passe doit contenir : ${failedCriteria.join(", ")}.`
}, { status: 400 });
}
const supabase = createRouteHandlerClient({ cookies });
const { data: { session } } = await supabase.auth.getSession();
if (!session) {
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
}
// Mettre à jour le mot de passe via updateUser() qui préserve la session active
// Note: Cette méthode n'invalide PAS la session actuelle contrairement à l'Admin API
const { error: updErr } = await supabase.auth.updateUser({
password: newPassword,
data: {
...session.user.user_metadata,
hasPassword: true
}
});
if (updErr) {
return NextResponse.json({
error: "update_failed",
message: updErr.message
}, { status: 400 });
}
// Envoyer un e-mail de confirmation (non bloquant)
try {
const userEmail = session.user.email || undefined;
const firstName = (session.user.user_metadata as any)?.first_name || undefined;
if (userEmail) {
await sendPasswordChangedEmail(userEmail, { firstName });
}
} catch (e) {
console.warn('⚠️ Envoi email mot de passe modifié échoué (non-bloquant):', (e as any)?.message || e);
}
return NextResponse.json({ ok: true, message: "Mot de passe mis à jour avec succès" });
} catch (e: any) {
return NextResponse.json({
error: "server_error",
message: e?.message || "Erreur interne"
}, { status: 500 });
}
}