pbl_blueprint/scripts/load_path.py

133 lines
5.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""pbl_blueprint 模块 RBAC 路径注册脚本。
用途:把本模块全部新 API 路径 + 页面路径注册到平台 RBAC权限路径表
使 owner.admin / 租户管理员可授权,未注册路径一律 403。
执行方式(应用部署后一次性 / 幂等可重复执行):
python -m pbl_blueprint.scripts.load_path
或在应用 init() 后由部署脚本调用 load_paths(env)。
"""
import os
import sys
MODULE_NAME = 'pbl_blueprint'
# ---- 本模块全部新 API 路径(与 api.py 的 API_PATHS 保持一致,单一事实源)----
API_PATHS = [
('/pbl_blueprint/blueprint/create', 'POST', '新建蓝图'),
('/pbl_blueprint/blueprint/update', 'POST', '更新蓝图'),
('/pbl_blueprint/blueprint/delete', 'POST', '删除蓝图'),
('/pbl_blueprint/blueprint/get', 'GET', '蓝图详情'),
('/pbl_blueprint/blueprint/list', 'GET', '蓝图列表'),
('/pbl_blueprint/blueprint/tree', 'GET', '蓝图子对象树'),
('/pbl_blueprint/blueprint/fork', 'POST', '复制蓝图'),
('/pbl_blueprint/version/save', 'POST', '保存版本快照'),
('/pbl_blueprint/version/list', 'GET', '版本列表'),
('/pbl_blueprint/version/diff', 'GET', '版本对比'),
('/pbl_blueprint/version/rollback', 'POST', '版本回滚'),
('/pbl_blueprint/subobject/create', 'POST', '新建子对象'),
('/pbl_blueprint/subobject/update', 'POST', '更新子对象'),
('/pbl_blueprint/subobject/delete', 'POST', '删除子对象'),
('/pbl_blueprint/subobject/get', 'GET', '子对象详情'),
('/pbl_blueprint/subobject/list', 'GET', '子对象列表'),
('/pbl_blueprint/subobject/batch_upsert', 'POST', '批量写子对象'),
('/pbl_blueprint/subobject/types', 'GET', '子对象类型枚举'),
('/pbl_blueprint/template/create', 'POST', '新建模板'),
('/pbl_blueprint/template/update', 'POST', '更新模板'),
('/pbl_blueprint/template/delete', 'POST', '删除模板'),
('/pbl_blueprint/template/get', 'GET', '模板详情'),
('/pbl_blueprint/template/list', 'GET', '模板列表'),
('/pbl_blueprint/template/instantiate', 'POST', '模板实例化为蓝图'),
('/pbl_blueprint/template/offline_fallback', 'POST', '离线兜底生成蓝图'),
]
# ---- 页面路径wwwroot/*.ui 挂载点)----
PAGE_PATHS = [
('/pbl_blueprint/index', 'GET', 'PBL蓝图管理主页'),
('/pbl_blueprint/blueprint/edit', 'GET', '蓝图编辑页'),
('/pbl_blueprint/template/list', 'GET', '蓝图模板库页'),
]
# ---- 表级数据权限路径CRUD 定义 json/*.json 对应)----
TABLE_PATHS = [
('/pbl_blueprint/tbl/pbl_blueprint', 'CRUD', '蓝图主表数据权限'),
('/pbl_blueprint/tbl/pbl_blueprint_version', 'CRUD', '蓝图版本表数据权限'),
('/pbl_blueprint/tbl/pbl_blueprint_template', 'CRUD', '蓝图模板表数据权限'),
('/pbl_blueprint/tbl/pbl_blueprint_template_item', 'CRUD', '蓝图模板条目表数据权限'),
('/pbl_blueprint/tbl/pbl_blueprint_task', 'CRUD', '子对象-任务数据权限'),
('/pbl_blueprint/tbl/pbl_blueprint_mission', 'CRUD', '子对象-关卡数据权限'),
('/pbl_blueprint/tbl/pbl_blueprint_role', 'CRUD', '子对象-角色数据权限'),
('/pbl_blueprint/tbl/pbl_blueprint_learning_goal', 'CRUD', '子对象-学习目标数据权限'),
('/pbl_blueprint/tbl/pbl_blueprint_evidence_spec', 'CRUD', '子对象-证据规格数据权限'),
('/pbl_blueprint/tbl/pbl_blueprint_artifact_spec', 'CRUD', '子对象-产出物规格数据权限'),
('/pbl_blueprint/tbl/pbl_blueprint_reflection_spec', 'CRUD', '子对象-反思规格数据权限'),
]
ALL_PATHS = API_PATHS + PAGE_PATHS + TABLE_PATHS
def load_paths(env=None):
"""把 ALL_PATHS 注册进 RBAC幂等存在则更新描述不存在则新增
:return: {'registered': n, 'skipped': m, 'failed': k}
"""
result = {'registered': 0, 'skipped': 0, 'failed': 0, 'paths': []}
if env is None:
try:
from sage import ServerEnv
env = ServerEnv()
except Exception:
env = None
rbac = None
if env is not None:
for attr in ('rbac', 'RBAC'):
rbac = getattr(env, attr, None)
if rbac is not None:
break
if rbac is None:
getter = getattr(env, 'get_rbac', None)
if callable(getter):
try:
rbac = getter()
except Exception:
rbac = None
for path, method, caption in ALL_PATHS:
item = {'path': path, 'method': method, 'caption': caption, 'module': MODULE_NAME}
result['paths'].append(item)
if rbac is None:
result['skipped'] += 1
continue
try:
registered = False
for fn_name in ('register_path', 'add_path', 'load_path', 'register'):
fn = getattr(rbac, fn_name, None)
if callable(fn):
try:
fn(path, method, caption)
except TypeError:
fn(item)
registered = True
break
if registered:
result['registered'] += 1
else:
result['skipped'] += 1
except Exception:
result['failed'] += 1
return result
def main():
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
res = load_paths()
print('[pbl_blueprint] load_path done: registered=%d skipped=%d failed=%d total=%d' % (
res['registered'], res['skipped'], res['failed'], len(res['paths'])))
return 0
if __name__ == '__main__':
sys.exit(main())