route-auth-gate.test.js
4.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/**
* route-auth-gate.test.js —— 38 号文档 Phase 1 的守卫测试
*
* 只验证一件事:"这个 router 的 requireAuth/requireAdmin/requireAuthOrInternal 是不是真的
* 挂在最前面",不发真实 HTTP 请求、不碰 DB —— 结构检查:`router.stack` 里能不能找到那个
* 中间件函数本身(同一个函数引用,不是同名重写),且它排在所有具体路由(`layer.route` 有值
* 的层)前面。真正打 HTTP 会 401 由各业务测试文件顺带覆盖(jwt-auth.js 的
* FORCE_REAL_AUTH 默认在测试环境放行,这里显式打开验证真实拦截效果)。
*
* 这条测试存在的理由:67 处业务路由测试全靠 supertest 直打路由,从没设过登录 cookie——
* 如果只跑那些测试,`router.use(requireAuth)` 被误删也不会被任何测试发现(默认放行,
* 删不删都是 200)。这条测试专门盯"锁挂了没有"这一件事,跟业务逻辑测试互不重叠。
*/
import { describe, it, expect, afterAll } from 'vitest';
process.env.NODE_ENV = 'test';
process.env.FORCE_REAL_AUTH = '1'; // 关掉 jwt-auth.js 的测试环境默认放行
const {
requireAuth,
requireAdmin,
requireAuthOrInternal,
} = require('../../middleware/jwt-auth');
/** router.stack 里有没有这个中间件函数本身,且排在第一条具体路由之前 */
function gateIndex(router, middlewareFn) {
const stack = router.stack || [];
return stack.findIndex((layer) => layer.handle === middlewareFn);
}
function firstRouteIndex(router) {
const stack = router.stack || [];
return stack.findIndex((layer) => !!layer.route);
}
function expectGated(router, middlewareFn, label) {
const gateAt = gateIndex(router, middlewareFn);
const routeAt = firstRouteIndex(router);
expect(gateAt, `${label}: 没有挂上预期的鉴权中间件`).toBeGreaterThanOrEqual(0);
expect(gateAt, `${label}: 鉴权中间件排在了具体路由后面,前面那些路由没被拦到`)
.toBeLessThan(routeAt === -1 ? Infinity : routeAt);
}
describe('route-auth-gate(38 号文档 Phase 1)', () => {
afterAll(() => {
delete process.env.FORCE_REAL_AUTH;
});
it('company.js 挂了 requireAuthOrInternal(39 号文档:goals/tasks 系列端点要给 agent 用 curl 直接调,比如 ceo 的心跳监督循环,不是普通 requireAuth)', () => {
expectGated(require('../../routes/company.js'), requireAuthOrInternal, 'company.js');
});
it('tasks.js 挂了 requireAuth', () => {
expectGated(require('../../routes/tasks.js'), requireAuth, 'tasks.js');
});
it('graph-run.js 两个挂载点都挂了 requireAuthOrInternal(39 号文档:ceo 心跳要能读/停/重试 run,不能只有 company.js 一侧放行 agent 自环调用)', () => {
const graphRun = require('../../routes/graph-run.js');
expectGated(graphRun, requireAuthOrInternal, 'graph-run.js router');
expectGated(graphRun.companyRouter, requireAuthOrInternal, 'graph-run.js companyRouter');
});
it('okr.js 挂了 requireAdmin(孤儿页面,前端无入口,收紧到 admin-only,见 38 号文档 Phase 2)', () => {
expectGated(require('../../routes/okr.js'), requireAdmin, 'okr.js');
});
it('arena.js 挂了 requireAuth', () => {
expectGated(require('../../routes/arena.js'), requireAuth, 'arena.js');
});
it('config.js 挂了 requireAuth', () => {
expectGated(require('../../routes/config.js'), requireAuth, 'config.js');
});
it('evolution.js 挂了 requireAuth', () => {
expectGated(require('../../routes/evolution.js'), requireAuth, 'evolution.js');
});
it('whatsapp-auth.js 挂了 requireAuth', () => {
expectGated(require('../../routes/whatsapp-auth.js'), requireAuth, 'whatsapp-auth.js');
});
it('dream.js 挂了 requireAdmin(系统级,只有 admin 能看,不是登录即可看)', () => {
expectGated(require('../../routes/dream.js'), requireAdmin, 'dream.js');
});
it('agent-chat.js 挂了 requireAuthOrInternal(不是普通 requireAuth——三处服务端自环调用要放行)', () => {
expectGated(require('../../routes/agent-chat.js'), requireAuthOrInternal, 'agent-chat.js');
});
it('open-api.js 不该挂 cookie 鉴权(它自己一套 OPEN_API_KEYS 体系,面向外部 Skill 市场调用方)', () => {
const openApi = require('../../routes/open-api.js');
expect(gateIndex(openApi, requireAuth)).toBe(-1);
expect(gateIndex(openApi, requireAuthOrInternal)).toBe(-1);
});
it('auth.js 自身不挂全局鉴权(登录/注册端点必须对未登录用户可达)', () => {
const auth = require('../../routes/auth.js');
expect(gateIndex(auth, requireAuth)).toBe(-1);
});
});