pbl_scense_ext/scripts/rbac_set_perm.py
2026-09-22 20:54:19 +08:00

65 lines
2.5 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.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""RBAC 单条权限登记 CLI(M9-收口C,QC 退回意见 #10 方案 a)。
接口(与 scripts/load_path.py register() 的 subprocess 调用契约严格一致):
python3 scripts/rbac_set_perm.py <role> <path>
例:python3 scripts/rbac_set_perm.py logined /pbl_scense_ext/api/pbl_overlay_bootstrap.dspy
退出码:rc=0 表示该 (role, path) 已幂等落库 permission + rolepermission;
rc!=0 表示未落库(参数非法 / 路径不在种子清单 / DB 不可达)。
**不猜、不静默成功**——DB 不可达时返回 2,由 load_path.py 计入 pending,
使 `total=26 ok=26 pending=0` 只在真实落库时才成立。
实现下沉到 scripts/m9c_rbac_seed.py 的 --upsert-one(幂等 upsert,id 由
path/role 的 md5 派生,重复执行零差异),本文件只做 CLI 适配与参数校验,
不重复实现导入逻辑。
被 apps/pbls/build.sh 第 9 步(import_rp)经 load_path.register() 调用;
RBAC_SET_PERM 环境变量可覆盖本工具路径(保持向后兼容)。
"""
import os
import re
import subprocess
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
SEED_TOOL = os.path.join(HERE, 'm9c_rbac_seed.py')
MODULE = 'pbl_scense_ext'
PSEUDO_ROLES = ('logined', 'any')
WILDCARD_RE = re.compile(r'[%*?]')
def main(argv):
if len(argv) != 3:
print('usage: rbac_set_perm.py <role> <path> (role in %s)' % (PSEUDO_ROLES,))
return 64
role, path = argv[1], argv[2]
# 参数硬校验:与 module-development-spec 硬门禁 6.6 一致,通配符零容忍
if role not in PSEUDO_ROLES:
print('FAIL 角色必须是伪角色 %s(rbac userperm.py 语义),收到 %s' % (PSEUDO_ROLES, role))
return 64
if WILDCARD_RE.search(path):
print('FAIL 禁止通配符(硬政策): %s' % path)
return 64
if not path.startswith('/%s' % MODULE):
print('FAIL 路径必须落在模块自动路由 /%s 下: %s' % (MODULE, path))
return 64
if not os.path.isfile(SEED_TOOL):
print('FAIL 缺少导入器 %s' % SEED_TOOL)
return 66
cmd = [sys.executable, SEED_TOOL, '--upsert-one', role, path]
if os.environ.get('PBL_SCENSE_EXT_DBNAME'):
cmd += ['--dbname', os.environ['PBL_SCENSE_EXT_DBNAME']]
rc = subprocess.call(cmd)
if rc == 0:
print('OK %-8s %s' % (role, path))
else:
print('PENDING(rc=%d) %-8s %s' % (rc, role, path))
return rc
if __name__ == '__main__':
sys.exit(main(sys.argv))