// Universal root load. Surfaces /auth/config to every page so the // navbar + layout can render without an extra round-trip, and — when // the backend reports PRIVATE_MODE=true — bounces anonymous visitors // to /login before any page-specific load fires. The backend // middleware is still the source of truth for the gate; this just // matches the UX so users don't see a page full of failed fetches. import type { LayoutLoad } from './$types'; import { redirect } from '@sveltejs/kit'; import { getAuthConfig, me, type AuthConfig } from '$lib/api/auth'; // Paths reachable anonymously even when private_mode is on. /login is // the entry point of the auth flow; everything else (including // /register, which is force-blocked in private mode) bounces. const PRIVATE_MODE_BYPASS = new Set(['/login']); const PUBLIC_DEFAULTS: AuthConfig = { self_register_enabled: true, private_mode: false }; export const load: LayoutLoad = async ({ url }) => { let authConfig: AuthConfig = PUBLIC_DEFAULTS; try { authConfig = await getAuthConfig(); } catch { // Fail-soft: keep the optimistic public-mode defaults so a // backend hiccup doesn't lock anyone out of the login page. // No private data can leak through here — the backend // middleware is still authoritative for the gate. } if (authConfig.private_mode && !PRIVATE_MODE_BYPASS.has(url.pathname)) { const user = await me().catch(() => null); if (!user) { const next = url.pathname + url.search; redirect(302, `/login?next=${encodeURIComponent(next)}`); } } return { authConfig }; };