feat(A1/A3+C8): 客户端令牌链路打通(按人鉴权就绪)+ 快照 JSON 写入节流
A1/A3 客户端令牌链路(服务端守卫已能按 JWT 鉴权,缺口在客户端不带身份) - 前端:新增 user-token-bridge(纯逻辑,值变化才推送)+ user-token-sync(启动安装, pywebviewready/storage/60s 轮询补推),main.ts 接入;桥接口补 set_user_token - 客户端:新增 crawler_core/user_token.py(持有 + 对自家 Java 端点注入 Authorization: Bearer <jwt>,Session.request 包装,第三方域名不注入、已有头不覆盖、 登出清空、SHUFUAI_DISABLE_USER_TOKEN_HOOK 可关);main.py 暴露桥方法并在启动安装钩子 - 服务端:守卫契约测试补 5 个用户态前缀用例(开关关闭放行 / 打开后匿名 401 / 用户令牌通过 / 内部令牌仍放行 / /api/ziniao 第二层) - 翻开关的前置条件(客户端铺开后置 aiimage.security.user-tool-guard-enabled=true)写入报告 C8 快照 JSON 写入节流 - 读端改以 biz_task_result_item 行为准、JSON 仅兜底(历史任务 JSON 仍是唯一副本时可用) - 整档 JSON 改 30s 节流写,终态路径 force 立即写;新增 2 个契约测试钉住语义 验证:mvn test 2888 全绿;npm test 741 全绿;user_token 钩子自测(注入/归一/第三方跳过/不覆盖/登出)通过
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import { test } from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { resetUserTokenBridgeStateForTest, syncUserTokenToBridge } from '../src/shared/auth/user-token-bridge.ts'
|
||||
import type { TokenPushTarget } from '../src/shared/auth/user-token-bridge.ts'
|
||||
|
||||
function collector() {
|
||||
const pushed: string[] = []
|
||||
return {
|
||||
target: { push: (value: string) => pushed.push(value) } as TokenPushTarget,
|
||||
pushed,
|
||||
}
|
||||
}
|
||||
|
||||
test('令牌变化时推送,重复值不重复推送', () => {
|
||||
resetUserTokenBridgeStateForTest()
|
||||
const { target, pushed } = collector()
|
||||
|
||||
assert.equal(syncUserTokenToBridge('abc', target), true)
|
||||
assert.equal(syncUserTokenToBridge('abc', target), false, '同值不重复推送')
|
||||
assert.equal(syncUserTokenToBridge(' def ', target), true, '去空白后不同则推送')
|
||||
assert.deepEqual(pushed, ['abc', 'def'])
|
||||
})
|
||||
|
||||
test('登出推空串以清空 Python 侧令牌', () => {
|
||||
resetUserTokenBridgeStateForTest()
|
||||
const { target, pushed } = collector()
|
||||
|
||||
syncUserTokenToBridge('abc', target)
|
||||
assert.equal(syncUserTokenToBridge('', target), true)
|
||||
assert.deepEqual(pushed, ['abc', ''])
|
||||
})
|
||||
|
||||
test('没有可用的桥时返回 false 且不记录状态(后续有桥仍会推送)', () => {
|
||||
resetUserTokenBridgeStateForTest()
|
||||
const { target, pushed } = collector()
|
||||
|
||||
assert.equal(syncUserTokenToBridge('abc', null), false, '无桥不推送')
|
||||
assert.equal(syncUserTokenToBridge('abc', target), true, '之后有桥仍推送')
|
||||
assert.deepEqual(pushed, ['abc'])
|
||||
})
|
||||
|
||||
test('推送目标抛异常时返回 false', () => {
|
||||
resetUserTokenBridgeStateForTest()
|
||||
const throwing: TokenPushTarget = {
|
||||
push: () => {
|
||||
throw new Error('bridge down')
|
||||
},
|
||||
}
|
||||
|
||||
assert.equal(syncUserTokenToBridge('abc', throwing), false)
|
||||
})
|
||||
Reference in New Issue
Block a user