完善项目级权限与项目管理入口

- 新增项目成员候选用户接口,避免 PM 读取全局用户列表
- 按项目角色和权限矩阵控制项目管理、成员、中心与审计入口
- 合并侧边栏管理后台入口,统一从项目管理进入成员等模块
- 加强成员管理安全约束,禁止 PM 修改自己、系统管理员或更高权限角色
- 修复多项目角色缓存串用问题,并补充前后端回归测试
This commit is contained in:
Cheng Zhou
2026-05-13 14:16:15 +08:00
parent ab1975d3c6
commit a17f4cc522
21 changed files with 452 additions and 134 deletions
+7 -7
View File
@@ -9,19 +9,19 @@ describe("admin project route permissions", () => {
const source = readRouter();
expect(source).toContain('adminProjectPermission: { module: "project_members", action: "read" }');
expect(source).toContain('adminProjectPermission: { module: "project_members", action: "write" }');
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('if (role !== "PM") return false;');
expect(source).toContain("roles?.PM?.[permission.module]?.[permission.action]");
expect(source).toContain("roles?.[role]?.[permission.module]?.[permission.action]");
});
it("sends authorized project PMs to the management backend after login", () => {
it("keeps login landing independent from PM management backend access", () => {
const source = readRouter();
expect(source).toContain("const findPmAdminLandingPath = async");
expect(source).toContain("pmAdminLandingModules.find");
expect(source).toContain("const pmAdminLanding = isAdmin ? null : await findPmAdminLandingPath()");
expect(source).toContain("? pmAdminLanding");
expect(source).toContain("`/admin/projects/${studyId}/members`");
expect(source).not.toContain("findPmAdminLandingPath");
expect(source).not.toContain("pmAdminLandingModules");
expect(source).toContain(' : studyStore.currentStudy\n ? "/project/overview"\n : "/workbench",');
});
});