86756c41da
Le pseudo temporaire fixe "Nouveau membre" entrait en collision (contrainte unique) dès qu'une 2e personne était invitée avant que la 1re ait fini son inscription ; il inclut maintenant un suffixe d'uuid. Le token d'invitation pouvait aussi s'établir sur n'importe quelle page (pas seulement /signup), laissant certains comptes connectés sans jamais voir le formulaire de mot de passe — /signup affiche désormais un état de chargement au lieu d'un écran vide, et le proxy renvoie systématiquement vers /signup tant que le compte n'est pas finalisé. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
86 lines
2.6 KiB
TypeScript
86 lines
2.6 KiB
TypeScript
import { createServerClient } from "@supabase/ssr";
|
|
import { NextResponse, type NextRequest } from "next/server";
|
|
|
|
const PROTECTED_PATHS = [
|
|
"/leaderboard",
|
|
"/profile",
|
|
"/admin",
|
|
"/journal",
|
|
"/calendrier",
|
|
"/icare",
|
|
"/char",
|
|
"/mur",
|
|
"/urne",
|
|
];
|
|
// /signup n'est PAS dans AUTH_PATHS : un compte fraîchement invité a déjà une
|
|
// session (établie par le lien d'invitation) mais doit pouvoir rester sur
|
|
// /signup pour finaliser mot de passe/pseudo/photo sans être renvoyé au
|
|
// leaderboard par ce redirect avant d'avoir terminé.
|
|
const AUTH_PATHS = ["/login"];
|
|
|
|
export async function updateSession(request: NextRequest) {
|
|
let response = NextResponse.next({ request });
|
|
|
|
const supabase = createServerClient(
|
|
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
{
|
|
cookies: {
|
|
getAll() {
|
|
return request.cookies.getAll();
|
|
},
|
|
setAll(cookiesToSet) {
|
|
cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value));
|
|
response = NextResponse.next({ request });
|
|
cookiesToSet.forEach(({ name, value, options }) =>
|
|
response.cookies.set(name, value, options),
|
|
);
|
|
},
|
|
},
|
|
},
|
|
);
|
|
|
|
const {
|
|
data: { user },
|
|
} = await supabase.auth.getUser();
|
|
|
|
const { pathname } = request.nextUrl;
|
|
const isProtected = PROTECTED_PATHS.some((path) => pathname.startsWith(path));
|
|
const isAuthPath = AUTH_PATHS.some((path) => pathname.startsWith(path));
|
|
const isSignup = pathname.startsWith("/signup");
|
|
|
|
if (!user && isProtected) {
|
|
const url = request.nextUrl.clone();
|
|
url.pathname = "/login";
|
|
return NextResponse.redirect(url);
|
|
}
|
|
|
|
// Le token d'un lien d'invitation Supabase s'établit dès qu'il touche le
|
|
// navigateur (detectSessionInUrl du SDK), sur N'IMPORTE QUELLE page, pas
|
|
// seulement /signup. Si le compte n'a pas encore fini son inscription
|
|
// (pseudo toujours au placeholder du trigger handle_new_user), on le
|
|
// renvoie systématiquement vers /signup pour ne jamais le laisser bloqué
|
|
// connecté mais sans mot de passe choisi.
|
|
if (user && !isSignup) {
|
|
const { data: profile } = await supabase
|
|
.from("profiles")
|
|
.select("pseudo")
|
|
.eq("id", user.id)
|
|
.single();
|
|
|
|
if (profile?.pseudo.startsWith("Nouveau membre")) {
|
|
const url = request.nextUrl.clone();
|
|
url.pathname = "/signup";
|
|
return NextResponse.redirect(url);
|
|
}
|
|
}
|
|
|
|
if (user && isAuthPath) {
|
|
const url = request.nextUrl.clone();
|
|
url.pathname = "/leaderboard";
|
|
return NextResponse.redirect(url);
|
|
}
|
|
|
|
return response;
|
|
}
|