import { defineMiddleware } from 'astro:middleware'; import { serverClient } from '@/lib/supabase'; const UABC_DOMAIN = '@uabc.edu.mx'; const PUBLIC_ROUTES = ['/login', '/api/auth/signin', '/api/auth/callback', '/api/auth/signout']; export const onRequest = defineMiddleware(async (context, next) => { const supabase = serverClient(context.cookies); context.locals.supabase = supabase; const { data: { user } } = await supabase.auth.getUser(); if (user && !user.email?.toLowerCase().endsWith(UABC_DOMAIN)) { await supabase.auth.signOut(); return context.redirect('/login?error=dominio'); } context.locals.user = user; context.locals.profile = null; if (user) { const select = 'id, email, nombre, matricula, rol, semestre, tutor_id, foto_path'; let { data: profile } = await supabase .from('profiles') .select(select) .eq('id', user.id) .maybeSingle(); // Self-heal: el trigger prestamos_on_auth_user_created coexiste con otro // trigger del proyecto vecino en auth.users y no siempre dispara. Si el // user existe pero no hay profile, lo creamos aquĆ­ con los datos del OAuth. if (!profile && user.email?.toLowerCase().endsWith(UABC_DOMAIN)) { const nombre = (user.user_metadata?.full_name as string | undefined) ?? (user.user_metadata?.name as string | undefined) ?? null; const { data: creado } = await supabase .from('profiles') .upsert({ id: user.id, email: user.email, nombre }, { onConflict: 'id' }) .select(select) .maybeSingle(); profile = creado ?? null; } context.locals.profile = profile ?? null; } const { pathname } = context.url; const isPublic = PUBLIC_ROUTES.includes(pathname); if (!user && !isPublic) { return context.redirect('/login'); } if (user && pathname === '/login') { return context.redirect('/'); } if (pathname.startsWith('/admin') && context.locals.profile?.rol !== 'admin') { return context.rewrite('/403'); } return next(); });