feature: RBAC + Clinical Audit Logging

This commit is contained in:
voltsrage
2026-06-21 15:46:55 +08:00
parent a43db52813
commit 5af6ab490e
83 changed files with 4281 additions and 70 deletions
+22 -4
View File
@@ -1,10 +1,25 @@
const BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:5270'
let authToken = null
export function setAuthToken(token) {
authToken = token
}
function authHeaders(extra = {}) {
const headers = { 'Content-Type': 'application/json', ...extra }
if (authToken) headers['Authorization'] = `Bearer ${authToken}`
return headers
}
async function request(path, options = {}) {
const res = await fetch(`${BASE_URL}${path}`, {
headers: { 'Content-Type': 'application/json', ...options.headers },
headers: authHeaders(options.headers),
...options,
})
if (res.status === 401) {
throw new Error('Session expired — please log in again.')
}
const envelope = await res.json()
if (!res.ok || !envelope.success) {
const msg = envelope.error?.message ?? `API ${res.status}: ${path}`
@@ -16,10 +31,13 @@ async function request(path, options = {}) {
/** Returns null when the resource does not exist yet (HTTP 404 or empty optional payload). */
async function requestOptional(path) {
const res = await fetch(`${BASE_URL}${path}`, {
headers: { 'Content-Type': 'application/json' },
headers: authHeaders(),
})
const envelope = await res.json()
if (res.status === 404) return null
if (res.status === 401) {
throw new Error('Session expired — please log in again.')
}
const envelope = await res.json()
if (!res.ok || !envelope.success) {
const msg = envelope.error?.message ?? `API ${res.status}: ${path}`
throw new Error(msg)
@@ -34,4 +52,4 @@ export const api = {
method: 'POST',
body: body !== undefined ? JSON.stringify(body) : undefined,
}),
}
}