pbl_appcodes/scripts/load_path.py

96 lines
3.9 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 -*-
"""pbl_appcodes 模块 RBAC / 路径声明脚本(per-module,中央层 apps/pbls 聚合)。
═══════════════════════════════════════════════════════════════════════════════
结论:本模块 **零 Web 可访问路径**(NO_WEB_PATHS = True,显式声明)
═══════════════════════════════════════════════════════════════════════════════
pbl_appcodes 只做枚举编码注入(appcodes / appcodes_kv 种子,幂等,零自有表),
只交付 Python 库函数(``pbl_appcodes/*.py``)与 init 种子数据,
**不提供任何 .dspy / .ui / .js / .css 文件**,因此 RBAC permission 表零登记项。
为什么写成显式声明而不是留空(M11b-2c-T3 QC 退回意见 #2 的连带治理):
中央聚合器把「有 scripts/load_path.py 但一条路径都没聚合到」判为聚合失败
(rc=1),除非模块显式声明 ``NO_WEB_PATHS``。「无路径」是事实断言,须可 grep。
用法:
python3 load_path.py # 打印声明(零路径,无需登记)
python3 load_path.py --check # 自检:无通配符 + 与磁盘 wwwroot 一致性
"""
import os
import sys
MODULE = 'pbl_appcodes'
NO_WEB_PATHS = True
DECLARATION = (
'pbl_appcodes 仅提供枚举编码注入(库函数 + init 种子数据,零自有表),'
'不新增任何 .dspy/.ui/.js/.css 可访问路径,故 RBAC 零登记项;'
'禁通配符(%/*),后续若新增 Web 路径须按 any/logined/owner.* 分层逐条登记。'
)
PATHS_ANY = []
PATHS_LOGINED = []
PATHS_OWNER_SUPERUSER = []
PATHS_OWNER_OPERATOR = []
PATHS = []
FORBIDDEN_WILDCARDS = ('%', '*')
def _wwwroot_files():
root = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
'wwwroot')
found = []
for base, _dirs, files in os.walk(root):
for fn in files:
if fn.endswith(('.dspy', '.ui', '.js', '.css')):
found.append(os.path.relpath(os.path.join(base, fn), root))
return sorted(found)
def check():
print('=' * 78)
print('[%s] RBAC 路径声明自检 (--check) module=%s' % (MODULE, MODULE))
print('=' * 78)
print(' NO_WEB_PATHS = %s' % NO_WEB_PATHS)
print(' 声明: %s' % DECLARATION)
rc = 0
tiers = (('any', PATHS_ANY), ('logined', PATHS_LOGINED),
('owner.superuser', PATHS_OWNER_SUPERUSER),
('owner.operator', PATHS_OWNER_OPERATOR))
bad = [t + ':' + p for t, ps in tiers for p in ps
if any(w in p for w in FORBIDDEN_WILDCARDS)]
if bad:
print(' FAIL 含禁用通配符: %s' % bad)
rc = 1
else:
print(' OK 通配符检查通过(无任何路径,自然无通配符)')
total = sum(len(ps) for _t, ps in tiers)
if total:
print(' FAIL NO_WEB_PATHS=True 但声明了 %d 条路径(自相矛盾)' % total)
rc = 1
else:
print(' OK 声明路径合计 0 条,与 NO_WEB_PATHS=True 一致')
on_disk = _wwwroot_files()
if on_disk:
print(' FAIL 磁盘 wwwroot 存在 %d 个 Web 文件却未登记: %s'
% (len(on_disk), on_disk))
rc = 1
else:
print(' OK 磁盘 wwwroot 无 .dspy/.ui/.js/.css 文件,与零路径声明一致')
print('[%s] --check 结论: %s' % (MODULE, 'PASS' if rc == 0 else 'FAIL'))
return rc
def main():
if '--check' in sys.argv[1:]:
return check()
print('[%s] %s' % (MODULE, DECLARATION))
print('[%s] 无路径需要登记(NO_WEB_PATHS=True);可执行 `--check` 离线复核。' % MODULE)
return 0
if __name__ == '__main__':
sys.exit(main())