统一项目权限读取模型
1、合并列表与详情读取权限,统一使用 subjects:read、project_members:read、monitoring_issues:read 等业务读取 key。 2、增加历史读取权限 key 的兼容映射,确保存量项目权限覆盖值不会丢失。 3、同步前端权限工具、路由权限与权限管理页面,避免继续引用已合并的旧权限 key。 4、补充项目角色启停保护与抽屉未保存变更守卫,防止停用 PM 或仍有关联成员的角色。
This commit is contained in:
@@ -5,25 +5,30 @@ describe("project route permissions", () => {
|
||||
it("maps project routes to backend operation keys", () => {
|
||||
expect(getProjectRoutePermission("/project/overview")).toEqual({ operationKey: "project_overview:read" });
|
||||
expect(getProjectRoutePermission("/project/milestones")).toEqual({ operationKey: "project_milestones:read" });
|
||||
expect(getProjectRoutePermission("/fees/contracts")).toEqual({ operationKey: "fees_contracts:read" });
|
||||
expect(getProjectRoutePermission("/finance/contracts")).toBeNull();
|
||||
expect(getProjectRoutePermission("/finance/contracts/new")).toBeNull();
|
||||
expect(getProjectRoutePermission("/finance/contracts/abc/edit")).toBeNull();
|
||||
expect(getProjectRoutePermission("/drug/shipments")).toEqual({ operationKey: "drug_shipments:read" });
|
||||
expect(getProjectRoutePermission("/drug/shipments/new")).toEqual({ operationKey: "drug_shipments:create" });
|
||||
expect(getProjectRoutePermission("/drug/shipments/abc/edit")).toEqual({ operationKey: "drug_shipments:update" });
|
||||
expect(getProjectRoutePermission("/drug/shipments/abc")).toEqual({ operationKey: "drug_shipments:read" });
|
||||
expect(getProjectRoutePermission("/subjects/new")).toEqual({ operationKey: "subjects:create" });
|
||||
expect(getProjectRoutePermission("/subjects/abc/edit")).toEqual({ operationKey: "subjects:update" });
|
||||
expect(getProjectRoutePermission("/risk-issues")).toEqual({ operationKey: "subject_aes:list" });
|
||||
expect(getProjectRoutePermission("/risk-issues/sae")).toEqual({ operationKey: "subject_aes:list" });
|
||||
expect(getProjectRoutePermission("/risk-issues")).toEqual({ operationKey: "subject_aes:read" });
|
||||
expect(getProjectRoutePermission("/risk-issues/sae")).toEqual({ operationKey: "subject_aes:read" });
|
||||
expect(getProjectRoutePermission("/risk-issues/pd")).toEqual({ operationKey: "subject_pds:list" });
|
||||
expect(getProjectRoutePermission("/risk-issues/monitoring-visits")).toEqual({ operationKey: "monitoring_issues:list" });
|
||||
expect(getProjectRoutePermission("/risk-issues/monitoring-visits")).toEqual({ operationKey: "monitoring_issues:read" });
|
||||
expect(getProjectRoutePermission("/etmf")).toEqual({ operationKey: "documents:read" });
|
||||
expect(getProjectRoutePermission("/startup/feasibility/new")).toEqual({ operationKey: "startup_initiation:create" });
|
||||
expect(getProjectRoutePermission("/startup/feasibility/abc/edit")).toEqual({ operationKey: "startup_initiation:update" });
|
||||
expect(getProjectRoutePermission("/startup/ethics/new")).toEqual({ operationKey: "startup_ethics:create" });
|
||||
expect(getProjectRoutePermission("/startup/ethics/abc/edit")).toEqual({ operationKey: "startup_ethics:update" });
|
||||
expect(getProjectRoutePermission("/startup/feasibility-ethics")).toEqual({
|
||||
operationKeys: ["startup_initiation:read", "startup_ethics:read"],
|
||||
});
|
||||
expect(getProjectRoutePermission("/startup/kickoff/new")).toEqual({ operationKey: "startup_auth:create" });
|
||||
expect(getProjectRoutePermission("/startup/kickoff/abc/edit")).toEqual({ operationKey: "startup_auth:update" });
|
||||
expect(getProjectRoutePermission("/startup/kickoff/abc/edit")).toBeNull();
|
||||
expect(getProjectRoutePermission("/startup/training/new")).toBeNull();
|
||||
expect(getProjectRoutePermission("/startup/training/abc/edit")).toBeNull();
|
||||
expect(getProjectRoutePermission("/knowledge/medical-consult/abc")).toEqual({ operationKey: "faq:read" });
|
||||
expect(getProjectRoutePermission("/knowledge/precautions/new")).toEqual({ operationKey: "precautions:create" });
|
||||
expect(getProjectRoutePermission("/knowledge/precautions/abc/edit")).toEqual({ operationKey: "precautions:update" });
|
||||
@@ -42,4 +47,46 @@ describe("project route permissions", () => {
|
||||
expect(hasProjectPermission(matrix, "CRA", getProjectRoutePermission("/knowledge/precautions"), false)).toBe(true);
|
||||
expect(findFirstAccessibleProjectPath(matrix, "CRA", false)).toBe("/knowledge/precautions");
|
||||
});
|
||||
|
||||
it("can fall back to every accessible risk issue child module", () => {
|
||||
expect(
|
||||
findFirstAccessibleProjectPath(
|
||||
{
|
||||
QA: {
|
||||
"subject_aes:read": { allowed: false },
|
||||
"subject_pds:list": { allowed: true },
|
||||
"monitoring_issues:read": { allowed: false },
|
||||
},
|
||||
} as any,
|
||||
"QA",
|
||||
false,
|
||||
),
|
||||
).toBe("/risk-issues/pd");
|
||||
|
||||
expect(
|
||||
findFirstAccessibleProjectPath(
|
||||
{
|
||||
QA: {
|
||||
"subject_aes:read": { allowed: false },
|
||||
"subject_pds:list": { allowed: false },
|
||||
"monitoring_issues:read": { allowed: true },
|
||||
},
|
||||
} as any,
|
||||
"QA",
|
||||
false,
|
||||
),
|
||||
).toBe("/risk-issues/monitoring-visits");
|
||||
});
|
||||
|
||||
it("allows combined landing pages when any child module is readable", () => {
|
||||
const matrix = {
|
||||
CRA: {
|
||||
"startup_initiation:read": { allowed: false },
|
||||
"startup_ethics:read": { allowed: true },
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(hasProjectPermission(matrix, "CRA", getProjectRoutePermission("/startup/feasibility-ethics"), false)).toBe(true);
|
||||
expect(findFirstAccessibleProjectPath(matrix, "CRA", false)).toBe("/startup/feasibility-ethics");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user