#!/usr/bin/env python3 # -*- coding: utf-8 -*- """pbl_kdb_ext RBAC 路径注册(硬门禁 6.6 / QC #11)。 约定: - 路径 = 模块自动路由 `/pbl_kdb_ext/...`,不带端口、不带 /wss 前缀; - 角色 `logined` = 登录即可访问的读接口(本模块零写入,无 teacher/admin 写接口); - 入口页与其目录路径必须同时注册(QC #1):`/pbl_kdb_ext` + `/pbl_kdb_ext/index.ui`, 否则入口页上线即 403; - 禁止通配符(`%` / `*`)——每条路径显式列出(module-development-spec:load_path.py Wildcards FORBIDDEN); - 由 apps/pbls/build.sh 第 8 步调用 `register()`;rbac CLI 不在位时打印 PENDING 清单(不静默跳过、不崩溃)。 """ import os import subprocess import sys MODULE = 'pbl_kdb_ext' # (path, role) —— 显式枚举,无通配符 PATHS = [ # 入口页(目录路径 + 文件路径都要注册,QC #1) ('/pbl_kdb_ext', 'logined'), ('/pbl_kdb_ext/index.ui', 'logined'), # 三个只读契约接口 ('/pbl_kdb_ext/api/pbl_kdb_search.dspy', 'logined'), ('/pbl_kdb_ext/api/pbl_kdb_get.dspy', 'logined'), ('/pbl_kdb_ext/api/pbl_research_aggregate.dspy', 'logined'), ] def register(): """逐条注册 RBAC 权限路径。 返回 True = 全部注册成功;False = 存在 pending(CLI 不在位/失败), 此时打印待补清单供部署角色手工执行 set_role_perm.py,脚本本身不抛异常。 """ tool = os.environ.get('RBAC_SET_PERM', 'set_role_perm.py') py = sys.executable if os.environ.get('PY') else 'python3' done, missing = 0, [] for path, role in PATHS: try: rc = subprocess.call([py, tool, role, path], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) except OSError: rc = 1 if rc == 0: done += 1 else: missing.append((path, role)) # QC #3:格式串占位符与实参个数必须一致(原 `%%-12s` 转义后只剩 1 个 %s 却传 2 个参数 → TypeError) print('[%s] rbac paths: total=%d ok=%d pending=%d' % (MODULE, len(PATHS), done, len(missing))) for path, role in missing: print(' PENDING %-12s %s' % (role, path)) return len(missing) == 0 if __name__ == '__main__': sys.exit(0 if register() else 1)