Files
registry/test/tokenService.test.js
T
jif2.zhang be2e4d9cdf
build-and-deploy / build-and-deploy (push) Successful in 42s
feat: MCP 端点鉴权改用后台 Token 管理,废弃 mcp_kv 配置
- tokenService 支持 mcpEnabled 标记,新增 getMcpTokenValues 与迁移逻辑
- /mcp 鉴权改为校验 Token 表中标记为 MCP 访问的生效令牌
- 启动时自动把旧 mcp_token 配置迁成一条 MCP Token,保证旧客户端不中断
- admin 页面 Token 表新增 MCP 访问列与生成/编辑开关
- 新增 tokenService 测试(58 项全部通过)
2026-09-20 21:45:18 +08:00

80 lines
3.0 KiB
JavaScript

/**
* Token 服务单元测试
* 覆盖:mcpEnabled 标记、MCP token 列表过滤、历史 MCP 配置迁移
* 运行:npm test
*/
const test = require("node:test");
const assert = require("node:assert");
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");
// 使用临时数据目录,避免污染真实 data/
const tmpDataDir = fs.mkdtempSync(path.join(os.tmpdir(), "registry-token-test-"));
process.env.REGISTRY_DATA_DIR = tmpDataDir;
const { init } = require("../src/persistence/duckdbAdapter");
const tokenService = require("../src/services/tokenService");
test.before(async () => {
await init();
});
test("createToken 保存 mcpEnabled 标记", async () => {
const mcpToken = await tokenService.createToken({
name: "mcp-key",
projectId: "all",
permission: "readwrite",
mcpEnabled: true,
expiresInDays: 30,
});
assert.strictEqual(mcpToken.mcpEnabled, true);
const plainToken = await tokenService.createToken({
name: "plain",
mcpEnabled: false,
});
assert.strictEqual(plainToken.mcpEnabled, false);
});
test("getMcpTokenValues 仅返回生效的 MCP token 明文", async () => {
const values = await tokenService.getMcpTokenValues();
assert.ok(values.length >= 1);
// 明文值以 reg_ 开头
assert.ok(values.every((v) => typeof v === "string" && v.startsWith("reg_")));
});
test("updateToken 可切换 mcpEnabled", async () => {
const plain = await tokenService.createToken({ name: "toggle", mcpEnabled: false });
const before = await tokenService.getMcpTokenValues();
assert.ok(!before.includes(plain.value));
await tokenService.updateToken(plain.id, { mcpEnabled: true });
const after = await tokenService.getMcpTokenValues();
assert.ok(after.includes(plain.value));
});
test("吊销或过期后 MCP token 不再生效", async () => {
const t = await tokenService.createToken({ name: "will-revoke", mcpEnabled: true, expiresInDays: 30 });
const ok = await tokenService.getMcpTokenValues();
assert.ok(ok.includes(t.value));
await tokenService.revokeToken(t.id);
const revoked = await tokenService.getMcpTokenValues();
assert.ok(!revoked.includes(t.value));
});
test("migrateLegacyMcpToken 把历史 mcp_kv 配置迁移为 Token 记录", async () => {
// 清理当前 token 表,模拟空 MCP 标记状态
const { loadApiTokens, saveApiTokens, saveMcpConfig, loadMcpConfig } = require("../src/persistence/duckdbAdapter");
await saveApiTokens([]);
await saveMcpConfig({ enabled: true, token: "legacy-mcp-token-abc" });
await tokenService.migrateLegacyMcpToken();
const tokens = await loadApiTokens();
const migrated = tokens.find((t) => t.mcpEnabled);
assert.ok(migrated, "应生成一条 mcpEnabled 的 Token");
assert.strictEqual(migrated.value, "legacy-mcp-token-abc");
const values = await tokenService.getMcpTokenValues();
assert.ok(values.includes("legacy-mcp-token-abc"));
// 旧配置已清空
const mcp = await loadMcpConfig();
assert.strictEqual(mcp.token, "");
});