import type { AuthMode, AuthUser } from "@/lib/auth/session"; export type BrowserCurrentSession = { authenticated: boolean; authRequired: boolean; authConfigured: boolean; authMode: AuthMode | null; user: AuthUser | null; }; export async function fetchBrowserAuthState(signal?: AbortSignal): Promise { const response = await fetch("/api/auth/me", { method: "GET", cache: "no-store", credentials: "same-origin", headers: { Accept: "application/json" }, signal }); if (!response.ok) throw new Error(`认证状态请求失败(${response.status})`); return parseCurrentSession(await response.json()); } export function safeBrowserNext(value: string | null | undefined, fallback = "/create"): string { if (!value || !value.startsWith("/") || value.startsWith("//") || value.includes("\\")) return fallback; try { const base = "http://zhinian.local"; const parsed = new URL(value, base); if (parsed.origin !== base) return fallback; const path = `${parsed.pathname}${parsed.search}${parsed.hash}`; if (parsed.pathname.startsWith("/api/auth") || parsed.pathname.startsWith("/auth/login") || parsed.pathname.startsWith("/auth/admin-login")) { return fallback; } return path; } catch { return fallback; } } export function safeBrowserLocationNext( location: Pick, fallback = "/create" ): string { return safeBrowserNext(`${location.pathname}${location.search}${location.hash}`, fallback); } function parseCurrentSession(value: unknown): BrowserCurrentSession { if (!isRecord(value) || typeof value.authenticated !== "boolean" || typeof value.authRequired !== "boolean" || typeof value.authConfigured !== "boolean") { throw new Error("认证状态响应格式无效"); } if (!value.authenticated) { if (value.authMode !== null || value.user !== null) throw new Error("认证状态响应格式无效"); return { authenticated: false, authRequired: value.authRequired, authConfigured: value.authConfigured, authMode: null, user: null }; } if (!value.authConfigured || (value.authMode !== "user" && value.authMode !== "admin") || !isAuthUser(value.user)) { throw new Error("认证用户响应格式无效"); } const expectedMode: AuthMode = value.user.role === "user" ? "user" : "admin"; if (value.authMode !== expectedMode) throw new Error("认证用户响应格式无效"); return { authenticated: true, authRequired: value.authRequired, authConfigured: value.authConfigured, authMode: value.authMode, user: value.user }; } function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null; } function isAuthUser(value: unknown): value is AuthUser { return isRecord(value) && typeof value.id === "string" && value.id.length > 0 && typeof value.subject === "string" && value.subject === value.id && typeof value.displayName === "string" && typeof value.clientId === "string" && (value.role === "user" || value.role === "organization_admin" || value.role === "super_admin") && value.status === "active" && (value.role === "super_admin" || (typeof value.organizationId === "string" && value.organizationId.length > 0)) && Array.isArray(value.authorities) && value.authorities.every((item) => typeof item === "string") && Array.isArray(value.scope) && value.scope.every((item) => typeof item === "string"); }