import type { NextRequest } from "next/server"; /** * Validates a browser-forwarded PocketBase auth token against PocketBase. * * Dashboard auth lives in localStorage, so Route Handlers cannot read it from * cookies. Browser callers send the current PB token in `Authorization`; this * helper asks PB to refresh/validate it instead of trusting or decoding the * token locally. */ export async function assertBrowserSession(req: NextRequest): Promise { const authorization = req.headers.get("authorization") || ""; const token = authorization.startsWith("Bearer ") ? authorization.slice(7) : authorization; if (!token) { throw Object.assign(new Error("Not authenticated."), { status: 401 }); } const pbUrl = process.env.NEXT_PUBLIC_POCKETBASE_URL || "http://127.0.0.1:8090"; const response = await fetch( `${pbUrl.replace(/\/$/, "")}/api/collections/users/auth-refresh`, { method: "POST", headers: { Authorization: token }, signal: AbortSignal.timeout(5_000), }, ); if (!response.ok) { throw Object.assign(new Error("Invalid or expired session."), { status: 401, }); } } export interface BrowserSessionUser { id: string; user_type: string[] | null; } /** * Same validation as `assertBrowserSession`, but returns the resolved * PB user record instead of discarding it — for routes that need to * scope queries to "whoever is logged in" (e.g. the rep dashboard). */ export async function getBrowserSessionUser( req: NextRequest, ): Promise { const authorization = req.headers.get("authorization") || ""; const token = authorization.startsWith("Bearer ") ? authorization.slice(7) : authorization; if (!token) { throw Object.assign(new Error("Not authenticated."), { status: 401 }); } const pbUrl = process.env.NEXT_PUBLIC_POCKETBASE_URL || "http://127.0.0.1:8090"; const response = await fetch( `${pbUrl.replace(/\/$/, "")}/api/collections/users/auth-refresh`, { method: "POST", headers: { Authorization: token }, signal: AbortSignal.timeout(5_000), }, ); if (!response.ok) { throw Object.assign(new Error("Invalid or expired session."), { status: 401, }); } const body = (await response.json()) as { record?: { id?: string; user_type?: string[] | null }; }; const id = body.record?.id; if (!id) { throw Object.assign(new Error("Invalid or expired session."), { status: 401, }); } return { id, user_type: body.record?.user_type ?? null }; }