feat(auth): 登出留痕审计
- 原登出为纯前端清 token,不发请求,故无记录 - 新增 POST /api/auth/logout 端点(无状态,仅供审计留痕),deriveActionLabel 加「登出」标签 - 前端 logout 先带 token 通知后端再清本地,失败不阻塞 - 审计中间件经 authMiddleware 解析操作人,记录谁/何时登出
This commit is contained in:
@@ -150,6 +150,7 @@ function deriveActionLabel(method: string, path: string): string {
|
||||
const p = path.replace(/\/+$/, '');
|
||||
const rules: ReadonlyArray<[RegExp, string]> = [
|
||||
[/^\/api\/auth\/login$/, '登录'],
|
||||
[/^\/api\/auth\/logout$/, '登出'],
|
||||
[/^\/api\/assessments\/run$/, '运行评估(创建/重评)'],
|
||||
[/^\/api\/assessments\/[^/]+\/submit$/, '申报报送风控'],
|
||||
[/^\/api\/assessments\/[^/]+\/resubmit$/, '驳回后重新提交'],
|
||||
@@ -319,6 +320,15 @@ app.post('/api/auth/login', async (c) => {
|
||||
return c.json({ token, username, role });
|
||||
});
|
||||
|
||||
/**
|
||||
* POST /api/auth/logout
|
||||
* 登出:无状态 JWT 由客户端丢弃 token 即可,本端点仅用于留痕审计(记录谁/何时登出)。
|
||||
* 需携带有效 token,审计中间件据此解析操作人。
|
||||
*/
|
||||
app.post('/api/auth/logout', (c) => {
|
||||
return c.json({ ok: true });
|
||||
});
|
||||
|
||||
/** LLM 启用状态(不泄露密钥),供前端/调试查询。 */
|
||||
app.get('/api/llm/status', (c) => {
|
||||
const cfg = getLlmConfig();
|
||||
|
||||
@@ -95,6 +95,14 @@ export const useAuthStore = create<AuthState>((set) => ({
|
||||
},
|
||||
|
||||
logout: () => {
|
||||
// 先通知后端留痕(登出审计),再清除本地令牌;失败不阻塞登出。
|
||||
try {
|
||||
const token = localStorage.getItem('risk-agent-token');
|
||||
void fetch(`${API_BASE}/api/auth/logout`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}) },
|
||||
}).catch(() => undefined);
|
||||
} catch { /* ignore */ }
|
||||
saveToStorage(null);
|
||||
try { localStorage.removeItem('risk-agent-token'); localStorage.removeItem('risk-agent-uid'); } catch { /* ignore */ }
|
||||
set({ isAuthenticated: false, user: null, error: null });
|
||||
|
||||
Reference in New Issue
Block a user