82 lines
No EOL
2.9 KiB
TypeScript
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 });
|
|
}
|
|
} |