feat: add cookie sessions and backend role authorization

This commit is contained in:
2026-10-16 07:51:59 +08:00
parent 411eadb431
commit 3f25ffab83
28 changed files with 1186 additions and 31 deletions
+28
View File
@@ -0,0 +1,28 @@
let csrfToken: string | null = null
export class ApiError extends Error {
constructor(public readonly status: number, message: string) { super(message) }
}
export function clearSessionToken() { csrfToken = null }
export async function apiRequest<T>(path: string, init: RequestInit = {}, protect = false): Promise<T> {
if (protect && !csrfToken) await apiRequest('/api/auth/me')
const headers = new Headers(init.headers)
headers.set('Accept', 'application/json')
if (init.body) headers.set('Content-Type', 'application/json')
if (protect && csrfToken) headers.set('X-CSRF-Token', csrfToken)
const response = await fetch(path, { ...init, credentials: 'include', headers })
if (!response.ok) {
if (response.status === 401) clearSessionToken()
const body: unknown = await response.json().catch(() => null)
const detail = body && typeof body === 'object' && 'detail' in body ? body.detail : null
throw new ApiError(response.status, typeof detail === 'string' ? detail : `请求失败(${response.status}),请检查登录状态或填写内容。`)
}
if (response.status === 204) return undefined as T
const data = await response.json()
if (path === '/api/auth/login' || path === '/api/auth/me') {
csrfToken = typeof data.csrf_token === 'string' ? data.csrf_token : null
}
return data as T
}