统一项目权限读取模型
1、合并列表与详情读取权限,统一使用 subjects:read、project_members:read、monitoring_issues:read 等业务读取 key。 2、增加历史读取权限 key 的兼容映射,确保存量项目权限覆盖值不会丢失。 3、同步前端权限工具、路由权限与权限管理页面,避免继续引用已合并的旧权限 key。 4、补充项目角色启停保护与抽屉未保存变更守卫,防止停用 PM 或仍有关联成员的角色。
This commit is contained in:
@@ -5,6 +5,28 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
READ_PERMISSION_ALIASES: dict[str, str] = {
|
||||
"subjects:list": "subjects:read",
|
||||
"subject_aes:list": "subject_aes:read",
|
||||
"fees_contracts:list": "fees_contracts:read",
|
||||
"project_members:list": "project_members:read",
|
||||
"project_members:candidates": "project_members:read",
|
||||
"sites:list": "sites:read",
|
||||
"startup_ethics:list": "startup_ethics:read",
|
||||
"startup_initiation:list": "startup_initiation:read",
|
||||
"monitoring_issues:list": "monitoring_issues:read",
|
||||
"drug_shipments:list": "drug_shipments:read",
|
||||
"audit_logs:list": "audit_logs:read",
|
||||
"precautions:list": "precautions:read",
|
||||
"subject_histories:list": "subject_histories:read",
|
||||
"material_equipments:list": "material_equipments:read",
|
||||
}
|
||||
|
||||
|
||||
def canonical_permission_key(endpoint_key: str) -> str:
|
||||
return READ_PERMISSION_ALIASES.get(endpoint_key, endpoint_key)
|
||||
|
||||
|
||||
# 接口级权限配置
|
||||
# 格式: "业务操作名": {配置信息}
|
||||
API_ENDPOINT_PERMISSIONS = {
|
||||
@@ -16,17 +38,10 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"default_roles": ["PM", "CRA"],
|
||||
"prerequisite_permissions": ["sites:read"],
|
||||
},
|
||||
"subjects:list": {
|
||||
"module": "subjects",
|
||||
"action": "read",
|
||||
"description": "查询参与者列表",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA", "CTA"],
|
||||
"prerequisite_permissions": [],
|
||||
},
|
||||
"subjects:read": {
|
||||
"module": "subjects",
|
||||
"action": "read",
|
||||
"description": "查询参与者详情",
|
||||
"description": "查询参与者",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA", "CTA"],
|
||||
"prerequisite_permissions": [],
|
||||
},
|
||||
@@ -81,17 +96,10 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"default_roles": ["PM", "CRA", "PV", "QA"],
|
||||
"prerequisite_permissions": ["subjects:read", "sites:read"],
|
||||
},
|
||||
"subject_aes:list": {
|
||||
"module": "subjects",
|
||||
"action": "read",
|
||||
"description": "查询参与者AE列表",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA", "CTA"],
|
||||
"prerequisite_permissions": [],
|
||||
},
|
||||
"subject_aes:read": {
|
||||
"module": "subjects",
|
||||
"action": "read",
|
||||
"description": "查询参与者AE详情",
|
||||
"description": "查询参与者AE",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA", "CTA"],
|
||||
"prerequisite_permissions": [],
|
||||
},
|
||||
@@ -100,14 +108,14 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"action": "write",
|
||||
"description": "更新参与者AE",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA"],
|
||||
"prerequisite_permissions": ["subject_aes:list", "subjects:read", "sites:read"],
|
||||
"prerequisite_permissions": ["subject_aes:read", "subjects:read", "sites:read"],
|
||||
},
|
||||
"subject_aes:delete": {
|
||||
"module": "subjects",
|
||||
"action": "write",
|
||||
"description": "删除参与者AE",
|
||||
"default_roles": ["PM"],
|
||||
"prerequisite_permissions": ["subject_aes:list", "subjects:read", "sites:read"],
|
||||
"prerequisite_permissions": ["subject_aes:read", "subjects:read", "sites:read"],
|
||||
},
|
||||
# 合同费用管理 (fees_contracts)
|
||||
"fees_contracts:create": {
|
||||
@@ -117,17 +125,10 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"default_roles": ["PM"],
|
||||
"prerequisite_permissions": ["sites:read"],
|
||||
},
|
||||
"fees_contracts:list": {
|
||||
"module": "fees",
|
||||
"action": "read",
|
||||
"description": "查询合同费用列表",
|
||||
"default_roles": ["PM", "CRA", "CTA"],
|
||||
"prerequisite_permissions": [],
|
||||
},
|
||||
"fees_contracts:read": {
|
||||
"module": "fees",
|
||||
"action": "read",
|
||||
"description": "查询合同费用详情",
|
||||
"description": "查询合同费用",
|
||||
"default_roles": ["PM", "CRA", "CTA"],
|
||||
"prerequisite_permissions": [],
|
||||
},
|
||||
@@ -152,16 +153,10 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"description": "添加项目成员",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"project_members:list": {
|
||||
"project_members:read": {
|
||||
"module": "project_members",
|
||||
"action": "read",
|
||||
"description": "查询项目成员列表",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"project_members:candidates": {
|
||||
"module": "project_members",
|
||||
"action": "read",
|
||||
"description": "查询项目成员候选人",
|
||||
"description": "查询项目成员",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"project_members:update": {
|
||||
@@ -183,16 +178,10 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"description": "创建中心",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"sites:list": {
|
||||
"module": "sites",
|
||||
"action": "read",
|
||||
"description": "查询中心列表",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA", "CTA"],
|
||||
},
|
||||
"sites:read": {
|
||||
"module": "sites",
|
||||
"action": "read",
|
||||
"description": "查询中心详情",
|
||||
"description": "查询中心",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA", "CTA"],
|
||||
},
|
||||
"sites:update": {
|
||||
@@ -214,16 +203,10 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"description": "创建伦理记录",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"startup_ethics:list": {
|
||||
"module": "startup_ethics",
|
||||
"action": "read",
|
||||
"description": "查询伦理记录列表",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA"],
|
||||
},
|
||||
"startup_ethics:read": {
|
||||
"module": "startup_ethics",
|
||||
"action": "read",
|
||||
"description": "查询伦理记录详情",
|
||||
"description": "查询伦理记录",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA"],
|
||||
},
|
||||
"startup_ethics:update": {
|
||||
@@ -245,16 +228,10 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"description": "创建立项记录",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"startup_initiation:list": {
|
||||
"module": "startup_ethics",
|
||||
"action": "read",
|
||||
"description": "查询立项记录列表",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA"],
|
||||
},
|
||||
"startup_initiation:read": {
|
||||
"module": "startup_ethics",
|
||||
"action": "read",
|
||||
"description": "查询立项记录详情",
|
||||
"description": "查询立项记录",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA"],
|
||||
},
|
||||
"startup_initiation:update": {
|
||||
@@ -278,16 +255,10 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"prerequisite_permissions": ["sites:read", "subjects:read"],
|
||||
},
|
||||
# 监查访视问题
|
||||
"monitoring_issues:list": {
|
||||
"module": "risk_issues",
|
||||
"action": "read",
|
||||
"description": "查询监查访视问题列表",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA"],
|
||||
},
|
||||
"monitoring_issues:read": {
|
||||
"module": "risk_issues",
|
||||
"action": "read",
|
||||
"description": "查询监查访视问题详情",
|
||||
"description": "查询监查访视问题",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA"],
|
||||
},
|
||||
"monitoring_issues:create": {
|
||||
@@ -319,17 +290,10 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"default_roles": ["PM", "CTA"],
|
||||
"prerequisite_permissions": ["sites:read"],
|
||||
},
|
||||
"drug_shipments:list": {
|
||||
"module": "materials",
|
||||
"action": "read",
|
||||
"description": "查询药物发货列表",
|
||||
"default_roles": ["PM", "CRA", "CTA"],
|
||||
"prerequisite_permissions": [],
|
||||
},
|
||||
"drug_shipments:read": {
|
||||
"module": "materials",
|
||||
"action": "read",
|
||||
"description": "查询药物发货详情",
|
||||
"description": "查询药物发货",
|
||||
"default_roles": ["PM", "CRA", "CTA"],
|
||||
"prerequisite_permissions": [],
|
||||
},
|
||||
@@ -377,16 +341,10 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"prerequisite_permissions": ["subjects:read", "sites:read"],
|
||||
},
|
||||
# 审计日志管理
|
||||
"audit_logs:list": {
|
||||
"module": "audit_export",
|
||||
"action": "read",
|
||||
"description": "查询审计日志列表",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"audit_logs:read": {
|
||||
"module": "audit_export",
|
||||
"action": "read",
|
||||
"description": "查询审计日志详情",
|
||||
"description": "查询审计日志",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"audit_logs:export": {
|
||||
@@ -402,16 +360,10 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"description": "创建注意事项",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA"],
|
||||
},
|
||||
"precautions:list": {
|
||||
"module": "shared_library",
|
||||
"action": "read",
|
||||
"description": "查询注意事项列表",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA", "CTA"],
|
||||
},
|
||||
"precautions:read": {
|
||||
"module": "shared_library",
|
||||
"action": "read",
|
||||
"description": "查询注意事项详情",
|
||||
"description": "查询注意事项",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA", "CTA"],
|
||||
},
|
||||
"precautions:update": {
|
||||
@@ -453,7 +405,7 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
},
|
||||
"setup_config:delete_version": {
|
||||
"module": "setup_config",
|
||||
"action": "write",
|
||||
"action": "delete",
|
||||
"description": "删除立项配置版本",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
@@ -496,107 +448,41 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
# 模块附件管理
|
||||
"fees_contracts_attachments:create": {
|
||||
"module": "fees",
|
||||
"action": "write",
|
||||
"description": "上传合同费用附件",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"fees_contracts_attachments:read": {
|
||||
"module": "fees",
|
||||
"action": "read",
|
||||
"description": "查询合同费用附件",
|
||||
"default_roles": ["PM", "CRA", "CTA"],
|
||||
},
|
||||
"fees_contracts_attachments:delete": {
|
||||
"module": "fees",
|
||||
"action": "write",
|
||||
"description": "删除合同费用附件",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"startup_initiation_attachments:create": {
|
||||
"module": "startup_ethics",
|
||||
"action": "write",
|
||||
"description": "上传立项记录附件",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"startup_initiation_attachments:read": {
|
||||
"module": "startup_ethics",
|
||||
"action": "read",
|
||||
"description": "查询立项记录附件",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA"],
|
||||
},
|
||||
"startup_initiation_attachments:delete": {
|
||||
"module": "startup_ethics",
|
||||
"action": "write",
|
||||
"description": "删除立项记录附件",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"startup_ethics_attachments:create": {
|
||||
"module": "startup_ethics",
|
||||
"action": "write",
|
||||
"description": "上传伦理记录附件",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"startup_ethics_attachments:read": {
|
||||
"module": "startup_ethics",
|
||||
"action": "read",
|
||||
"description": "查询伦理记录附件",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA"],
|
||||
},
|
||||
"startup_ethics_attachments:delete": {
|
||||
"module": "startup_ethics",
|
||||
"action": "write",
|
||||
"description": "删除伦理记录附件",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"startup_auth_attachments:create": {
|
||||
"module": "startup_auth",
|
||||
"action": "write",
|
||||
"description": "上传启动授权附件",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"startup_auth_attachments:read": {
|
||||
"module": "startup_auth",
|
||||
"action": "read",
|
||||
"description": "查询启动授权附件",
|
||||
"default_roles": ["PM", "CRA", "PV", "CTA"],
|
||||
},
|
||||
"startup_auth_attachments:delete": {
|
||||
"module": "startup_auth",
|
||||
"action": "write",
|
||||
"description": "删除启动授权附件",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"drug_shipments_attachments:create": {
|
||||
"module": "materials",
|
||||
"action": "write",
|
||||
"description": "上传药物发货附件",
|
||||
"default_roles": ["PM", "CTA"],
|
||||
},
|
||||
"drug_shipments_attachments:read": {
|
||||
"module": "materials",
|
||||
"action": "read",
|
||||
"description": "查询药物发货附件",
|
||||
"default_roles": ["PM", "CRA", "CTA"],
|
||||
},
|
||||
"drug_shipments_attachments:delete": {
|
||||
"module": "materials",
|
||||
"action": "write",
|
||||
"description": "删除药物发货附件",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"precautions_attachments:create": {
|
||||
"module": "shared_library",
|
||||
"material_equipments_attachments:delete": {
|
||||
"module": "materials",
|
||||
"action": "write",
|
||||
"description": "上传注意事项附件",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA"],
|
||||
},
|
||||
"precautions_attachments:read": {
|
||||
"module": "shared_library",
|
||||
"action": "read",
|
||||
"description": "查询注意事项附件",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA", "CTA"],
|
||||
"description": "删除物资设备附件",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"precautions_attachments:delete": {
|
||||
"module": "shared_library",
|
||||
@@ -604,18 +490,6 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"description": "删除注意事项附件",
|
||||
"default_roles": ["PM"],
|
||||
},
|
||||
"faq_attachments:create": {
|
||||
"module": "shared_library",
|
||||
"action": "write",
|
||||
"description": "上传FAQ附件",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA"],
|
||||
},
|
||||
"faq_attachments:read": {
|
||||
"module": "shared_library",
|
||||
"action": "read",
|
||||
"description": "查询FAQ附件",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA", "CTA"],
|
||||
},
|
||||
"faq_attachments:delete": {
|
||||
"module": "shared_library",
|
||||
"action": "write",
|
||||
@@ -693,17 +567,10 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"default_roles": ["PM", "CRA"],
|
||||
"prerequisite_permissions": ["subjects:read"],
|
||||
},
|
||||
"subject_histories:list": {
|
||||
"module": "subjects",
|
||||
"action": "read",
|
||||
"description": "查询病史记录列表",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA", "CTA"],
|
||||
"prerequisite_permissions": [],
|
||||
},
|
||||
"subject_histories:read": {
|
||||
"module": "subjects",
|
||||
"action": "read",
|
||||
"description": "查询病史记录详情",
|
||||
"description": "查询病史记录",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA", "CTA"],
|
||||
"prerequisite_permissions": [],
|
||||
},
|
||||
@@ -728,16 +595,10 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
"description": "创建物资设备",
|
||||
"default_roles": ["PM", "CRA"],
|
||||
},
|
||||
"material_equipments:list": {
|
||||
"module": "materials",
|
||||
"action": "read",
|
||||
"description": "查询物资设备列表",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA", "CTA"],
|
||||
},
|
||||
"material_equipments:read": {
|
||||
"module": "materials",
|
||||
"action": "read",
|
||||
"description": "查询物资设备详情",
|
||||
"description": "查询物资设备",
|
||||
"default_roles": ["PM", "CRA", "PV", "QA", "CTA"],
|
||||
},
|
||||
"material_equipments:update": {
|
||||
@@ -784,9 +645,7 @@ API_ENDPOINT_PERMISSIONS = {
|
||||
OPERATION_TO_ENDPOINTS: dict[str, dict[str, list[str]]] = {
|
||||
"subjects": {
|
||||
"read": [
|
||||
"subjects:list",
|
||||
"subjects:read",
|
||||
"subject_aes:list",
|
||||
"subject_aes:read",
|
||||
],
|
||||
"write": [
|
||||
@@ -810,7 +669,6 @@ OPERATION_TO_ENDPOINTS: dict[str, dict[str, list[str]]] = {
|
||||
},
|
||||
"risk_issues": {
|
||||
"read": [
|
||||
"monitoring_issues:list",
|
||||
"monitoring_issues:read",
|
||||
],
|
||||
"write": [
|
||||
@@ -821,22 +679,18 @@ OPERATION_TO_ENDPOINTS: dict[str, dict[str, list[str]]] = {
|
||||
},
|
||||
"fees": {
|
||||
"read": [
|
||||
"fees_contracts:list",
|
||||
"fees_contracts:read",
|
||||
"fees_contracts_attachments:read",
|
||||
],
|
||||
"write": [
|
||||
"fees_contracts:create",
|
||||
"fees_contracts:update",
|
||||
"fees_contracts:delete",
|
||||
"fees_contracts_attachments:create",
|
||||
"fees_contracts_attachments:delete",
|
||||
],
|
||||
},
|
||||
"project_members": {
|
||||
"read": [
|
||||
"project_members:list",
|
||||
"project_members:candidates",
|
||||
"project_members:read",
|
||||
],
|
||||
"write": [
|
||||
"project_members:create",
|
||||
@@ -846,7 +700,6 @@ OPERATION_TO_ENDPOINTS: dict[str, dict[str, list[str]]] = {
|
||||
},
|
||||
"sites": {
|
||||
"read": [
|
||||
"sites:list",
|
||||
"sites:read",
|
||||
],
|
||||
"write": [
|
||||
@@ -857,12 +710,8 @@ OPERATION_TO_ENDPOINTS: dict[str, dict[str, list[str]]] = {
|
||||
},
|
||||
"startup_ethics": {
|
||||
"read": [
|
||||
"startup_ethics:list",
|
||||
"startup_ethics:read",
|
||||
"startup_initiation:list",
|
||||
"startup_initiation:read",
|
||||
"startup_ethics_attachments:read",
|
||||
"startup_initiation_attachments:read",
|
||||
],
|
||||
"write": [
|
||||
"startup_ethics:create",
|
||||
@@ -871,22 +720,18 @@ OPERATION_TO_ENDPOINTS: dict[str, dict[str, list[str]]] = {
|
||||
"startup_initiation:create",
|
||||
"startup_initiation:update",
|
||||
"startup_initiation:delete",
|
||||
"startup_ethics_attachments:create",
|
||||
"startup_ethics_attachments:delete",
|
||||
"startup_initiation_attachments:create",
|
||||
"startup_initiation_attachments:delete",
|
||||
],
|
||||
},
|
||||
"startup_auth": {
|
||||
"read": [
|
||||
"startup_auth:read",
|
||||
"startup_auth_attachments:read",
|
||||
],
|
||||
"write": [
|
||||
"startup_auth:create",
|
||||
"startup_auth:update",
|
||||
"startup_auth:delete",
|
||||
"startup_auth_attachments:create",
|
||||
"startup_auth_attachments:delete",
|
||||
],
|
||||
},
|
||||
@@ -898,11 +743,8 @@ OPERATION_TO_ENDPOINTS: dict[str, dict[str, list[str]]] = {
|
||||
},
|
||||
"materials": {
|
||||
"read": [
|
||||
"drug_shipments:list",
|
||||
"drug_shipments:read",
|
||||
"material_equipments:list",
|
||||
"material_equipments:read",
|
||||
"drug_shipments_attachments:read",
|
||||
],
|
||||
"write": [
|
||||
"drug_shipments:create",
|
||||
@@ -911,13 +753,12 @@ OPERATION_TO_ENDPOINTS: dict[str, dict[str, list[str]]] = {
|
||||
"material_equipments:create",
|
||||
"material_equipments:update",
|
||||
"material_equipments:delete",
|
||||
"drug_shipments_attachments:create",
|
||||
"drug_shipments_attachments:delete",
|
||||
"material_equipments_attachments:delete",
|
||||
],
|
||||
},
|
||||
"audit_export": {
|
||||
"read": [
|
||||
"audit_logs:list",
|
||||
"audit_logs:read",
|
||||
"audit_logs:export",
|
||||
],
|
||||
@@ -925,7 +766,6 @@ OPERATION_TO_ENDPOINTS: dict[str, dict[str, list[str]]] = {
|
||||
},
|
||||
"subject_histories": {
|
||||
"read": [
|
||||
"subject_histories:list",
|
||||
"subject_histories:read",
|
||||
],
|
||||
"write": [
|
||||
@@ -965,18 +805,14 @@ OPERATION_TO_ENDPOINTS: dict[str, dict[str, list[str]]] = {
|
||||
},
|
||||
"shared_library": {
|
||||
"read": [
|
||||
"precautions:list",
|
||||
"precautions:read",
|
||||
"precautions_attachments:read",
|
||||
"faq:read",
|
||||
"faq_category:read",
|
||||
"faq_attachments:read",
|
||||
],
|
||||
"write": [
|
||||
"precautions:create",
|
||||
"precautions:update",
|
||||
"precautions:delete",
|
||||
"precautions_attachments:create",
|
||||
"precautions_attachments:delete",
|
||||
"faq:create",
|
||||
"faq:update",
|
||||
@@ -986,7 +822,6 @@ OPERATION_TO_ENDPOINTS: dict[str, dict[str, list[str]]] = {
|
||||
"faq_category:delete",
|
||||
"faq_reply:create",
|
||||
"faq_reply:delete",
|
||||
"faq_attachments:create",
|
||||
"faq_attachments:delete",
|
||||
],
|
||||
},
|
||||
@@ -1010,8 +845,8 @@ OPERATION_PREREQUISITES: dict[str, list[str]] = {
|
||||
|
||||
# 参与者AE
|
||||
"subject_aes:create": ["subjects:read", "sites:read"],
|
||||
"subject_aes:update": ["subject_aes:list", "subjects:read", "sites:read"],
|
||||
"subject_aes:delete": ["subject_aes:list", "subjects:read", "sites:read"],
|
||||
"subject_aes:update": ["subject_aes:read", "subjects:read", "sites:read"],
|
||||
"subject_aes:delete": ["subject_aes:read", "subjects:read", "sites:read"],
|
||||
|
||||
# 合同费用
|
||||
"fees_contracts:create": ["sites:read"],
|
||||
|
||||
@@ -7,7 +7,12 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.api_endpoint_permission import ApiEndpointPermission
|
||||
from app.models.study import Study
|
||||
from app.core.api_permissions import API_ENDPOINT_PERMISSIONS, OPERATION_PREREQUISITES, PROJECT_PERMISSION_ROLES
|
||||
from app.core.api_permissions import (
|
||||
API_ENDPOINT_PERMISSIONS,
|
||||
OPERATION_PREREQUISITES,
|
||||
PROJECT_PERMISSION_ROLES,
|
||||
canonical_permission_key,
|
||||
)
|
||||
from app.core.permission_cache import get_permission_cache
|
||||
|
||||
|
||||
@@ -34,7 +39,10 @@ async def _get_project_permission_overrides(
|
||||
|
||||
permissions: dict[str, dict[str, bool]] = {}
|
||||
for row in rows:
|
||||
permissions.setdefault(row.role, {})[row.endpoint_key] = row.allowed
|
||||
endpoint_key = canonical_permission_key(row.endpoint_key)
|
||||
role_permissions = permissions.setdefault(row.role, {})
|
||||
if row.endpoint_key == endpoint_key or endpoint_key not in role_permissions:
|
||||
role_permissions[endpoint_key] = row.allowed
|
||||
|
||||
cache.set_project_permissions(study_id, permissions)
|
||||
return permissions
|
||||
@@ -48,6 +56,7 @@ async def role_has_api_permission(
|
||||
check_prerequisites: bool = True,
|
||||
) -> bool:
|
||||
"""检查角色是否有权访问特定接口"""
|
||||
endpoint_key = canonical_permission_key(endpoint_key)
|
||||
if endpoint_key not in API_ENDPOINT_PERMISSIONS:
|
||||
return False
|
||||
|
||||
@@ -93,6 +102,7 @@ async def get_missing_prerequisites(
|
||||
return []
|
||||
|
||||
missing = []
|
||||
endpoint_key = canonical_permission_key(endpoint_key)
|
||||
prerequisites = OPERATION_PREREQUISITES.get(endpoint_key, [])
|
||||
for prereq_endpoint in prerequisites:
|
||||
has_prereq = await role_has_api_permission(
|
||||
@@ -132,6 +142,7 @@ async def get_api_endpoint_permissions(
|
||||
if role not in matrix:
|
||||
matrix[role] = {}
|
||||
for endpoint_key, allowed in endpoints.items():
|
||||
endpoint_key = canonical_permission_key(endpoint_key)
|
||||
if endpoint_key not in API_ENDPOINT_PERMISSIONS:
|
||||
continue
|
||||
matrix[role][endpoint_key] = {"allowed": allowed}
|
||||
@@ -153,6 +164,7 @@ async def replace_api_endpoint_permissions(
|
||||
if role in ("ADMIN", "PM"):
|
||||
continue
|
||||
for endpoint_key, allowed in endpoints.items():
|
||||
endpoint_key = canonical_permission_key(endpoint_key)
|
||||
if endpoint_key not in API_ENDPOINT_PERMISSIONS:
|
||||
continue
|
||||
result = await db.execute(
|
||||
|
||||
Reference in New Issue
Block a user