Files
ctms/frontend/src/router.test.ts
T
Cheng Zhou 934d114a29 feat(perm/frontend): PM 视角的权限管理界面与个人有效权限接入
- store/study 与 router 改为读取 /api-permissions/me 拉取当前用户在
  当前项目的有效权限,菜单与路由守卫据此判定,并在 PM 项目缺省时
  主动 ensureDefaultPmStudy。
- api/projectPermissions 暴露 fetchMyApiEndpointPermissions,并允许
  调用方关闭统一错误提示,便于在批量项目权限拉取场景下静默失败。
- 项目管理:Projects 页根据每个项目的有效权限决定项目入口的可点击
  状态,缺权限时禁用项目名跳转;ProjectDetail 据 setup_config 写权限
  渲染保存/回填/清空/发布按钮,并在无读取权限时提示并退出页面。
- 权限管理:PermissionManagement 切换为按角色提交,Admin 视角才能
  编辑 PM 行;按系统模块美化系统级权限展示并标注 PM 可访问项;项目
  成员表的角色下拉受 PM 等级约束,自定义角色入口下线。
- 监控:PermissionMonitoring/PermissionAccessLogs 增加 isAdmin 与
  showSecurityLog 入参,仅 ADMIN 才能看到底层安全日志与统计。
- ApiEndpointPermissions 表格根据当前用户角色禁用不可写行,避免
  误操作 PM 行;MODULE_LABELS 增加 setup_config 的中文展示。
- 测试同步覆盖以上行为:新版 router/Layout/Projects/PermissionManagement
  /PermissionAccessLogs/PermissionMonitoring/PermissionIpLocations 等
  组件均补足检测,并按需为相关组件提供 pinia + localStorage stub。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 12:38:54 +08:00

47 lines
2.1 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
const readRouter = () => readFileSync(resolve(__dirname, "./router/index.ts"), "utf8");
describe("admin project route permissions", () => {
it("lets any authorized project role open the project management detail page", () => {
const source = readRouter();
expect(source).toContain('name: "AdminProjectDetail"');
expect(source).toContain("requiresProjectMember: true");
expect(source).not.toContain("meta: { title: TEXT.modules.adminProjects.detailTitle, requiresAdmin: true }");
expect(source).toContain("ensureRouteProjectMember(to, studyStore)");
});
it("allows project admin pages through matrix-authorized PMs instead of all project roles", () => {
const source = readRouter();
expect(source).toContain('adminProjectPermission: { module: "sites", action: "read" }');
expect(source).toContain('adminProjectPermission: { module: "audit_export", action: "read" }');
expect(source).toContain("meta: { title: TEXT.menu.projectManagement }");
expect(source).toContain("ADMIN_PROJECT_OPERATION_KEYS");
expect(source).toContain('if (role !== "PM") return false;');
expect(source).toContain("isApiPermissionAllowed");
expect(source).toContain("studyStore.currentPermissions?.[role]?.[operationKey]");
});
it("keeps login landing independent from PM management backend access", () => {
const source = readRouter();
expect(source).not.toContain("findPmAdminLandingPath");
expect(source).not.toContain("pmAdminLandingModules");
expect(source).toContain(' : studyStore.currentStudy\n ? "/project/overview"\n : "/admin/projects",');
});
it("does not register the removed non-admin personal dashboard route", () => {
const source = readRouter();
const removedComponent = ["My", "Work", "bench"].join("");
const removedPath = `/${["work", "bench"].join("")}`;
expect(source).not.toContain(removedComponent);
expect(source).not.toContain(`path: "${removedPath.slice(1)}"`);
expect(source).not.toContain(`"${removedPath}"`);
});
});