61 lines
2.3 KiB
Python
61 lines
2.3 KiB
Python
#!/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)
|