espace-paie-odentas/app/api/auth/verify-code/route.ts

96 lines
No EOL
3.1 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { NextResponse } from "next/server";
import { cookies } from "next/headers";
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { createClient } from "@supabase/supabase-js";
/**
* Applique les cookies persistants si rememberMe est activé
*/
function applyRememberMeCookies(response: NextResponse, rememberMe?: boolean) {
if (rememberMe) {
// Définir un cookie remember_me pour le middleware
response.cookies.set("remember_me", "true", {
maxAge: 60 * 60 * 24 * 30, // 30 jours
path: "/",
sameSite: "lax",
httpOnly: true,
secure: process.env.NODE_ENV === "production",
});
// Prolonger la durée des cookies Supabase
const cookieStore = cookies();
const allCookies = cookieStore.getAll();
allCookies.forEach((cookie) => {
if (cookie.name.startsWith("sb-")) {
response.cookies.set(cookie.name, cookie.value, {
maxAge: 60 * 60 * 24 * 30, // 30 jours
path: "/",
sameSite: "lax",
httpOnly: true,
secure: process.env.NODE_ENV === "production",
});
}
});
console.log("✅ [verify-code] Cookies persistants activés pour 30 jours");
} else {
// Supprimer le cookie remember_me s'il existe
response.cookies.set("remember_me", "", {
maxAge: 0,
path: "/",
});
console.log(" [verify-code] Cookies de session (non persistants)");
}
}
export async function POST(req: Request) {
try {
const { email, code, rememberMe } = await req.json();
if (!email || !code) return new NextResponse("Email et code requis", { status: 400 });
const supabase = createRouteHandlerClient({ cookies });
const { data, error } = await supabase.auth.verifyOtp({ email, token: code, type: "email" });
if (error) return new NextResponse(error.message, { status: 400 });
const userId = (data?.user || data?.session?.user)?.id as string | undefined;
if (!userId) return new NextResponse("No user", { status: 400 });
const srv = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!,
{ auth: { autoRefreshToken: false, persistSession: false } }
);
// 1) Si Staff → OK direct
const { data: su } = await srv
.from("staff_users")
.select("is_staff")
.eq("user_id", userId)
.maybeSingle();
if (su?.is_staff) {
const response = NextResponse.json({ ok: true });
applyRememberMeCookies(response, rememberMe);
return response;
}
// 2) Sinon, vérifier la révocation (user à une seule org)
const { data: mem } = await srv
.from("organization_members")
.select("revoked")
.eq("user_id", userId)
.maybeSingle();
if (!mem || mem.revoked) {
await supabase.auth.signOut();
return new NextResponse("revoked", { status: 403 });
}
const response = NextResponse.json({ ok: true });
applyRememberMeCookies(response, rememberMe);
return response;
} catch (e: any) {
return new NextResponse(e?.message || "Internal Server Error", { status: 500 });
}
}