diff --git a/frontend/src/new-hooks.ts b/frontend/src/new-hooks.ts new file mode 100644 index 0000000..707a7da --- /dev/null +++ b/frontend/src/new-hooks.ts @@ -0,0 +1,59 @@ +import type { Handle } from '@sveltejs/kit'; +import { redirect } from '@sveltejs/kit'; +import { createPbClient } from '$lib/server/pocketbase'; +import { SESSION_COOKIE, setSessionCookie, clearSessionCookie } from '$lib/server/session'; +import type { SessionUser } from '$lib/server/types'; + +const PUBLIC_PATHS = ['/login', '/signup', '/pair']; +const ADMIN_ONLY_PREFIXES = ['/admin']; + +export const handle: Handle = async ({ event, resolve }) => { + event.locals.user = null; + event.locals.pbToken = null; + + const token = event.cookies.get(SESSION_COOKIE); + + if (token) { + const pb = createPbClient(token); + try { + // authRefresh() does two jobs in one call: + // 1. Verifies the token. PocketBase JWTs can't be checked + // offline (the signing secret is per-record and never + // leaves PB), so this round trip IS the verification step. + // 2. Returns the current record — which is the only way to get + // username/role/famId, since PB deliberately doesn't embed + // custom fields in the token itself. + const { record, token: freshToken } = await pb.collection('users').authRefresh(); + + event.locals.user = { + id: record.id, + name: record.name, + role: record.role, + famId: record.famId + } satisfies SessionUser; + event.locals.pbToken = freshToken; + + if (freshToken !== token) { + setSessionCookie(event.cookies, freshToken); + } + } catch { + // Expired, malformed, or revoked (password/deviceToken changed + // since this token was issued) — drop it and treat as logged out. + clearSessionCookie(event.cookies); + } + } + + const path = event.url.pathname; + const isPublic = PUBLIC_PATHS.some((p) => path.startsWith(p)); + + if (!isPublic && !event.locals.user) { + throw redirect(303, '/login'); + } + + if (ADMIN_ONLY_PREFIXES.some((p) => path.startsWith(p)) && !event.locals.user) { + console.log("rejecting",event.locals.user); + throw redirect(303, '/'); + } + + return resolve(event); +};