fix(load_path): review修复——单事件循环直连注册(去掉600+次subprocess),get_accdetail恢复page/sort
This commit is contained in:
parent
89592b9585
commit
411d1017cf
@ -48,7 +48,9 @@ where b.subjectid = c.id
|
||||
"""
|
||||
ns = {
|
||||
'accountid': accountid,
|
||||
'orgid': userorgid
|
||||
'orgid': userorgid,
|
||||
'page': page,
|
||||
'sort': 'acc_date desc'
|
||||
}
|
||||
ret = await sor.sqlExe(sql, ns)
|
||||
return ret
|
||||
|
||||
@ -22,11 +22,10 @@ accounting 模块 RBAC 权限管理脚本(角色分层版,2026-08-27 重构
|
||||
用 orgtypeid+name 查 role 表解析出真实 role.id 后注册,同名多条全部注册。
|
||||
|
||||
使用方法:
|
||||
cd <app root>(含 py3/ 与 set_role_perm.py 的目录,如 /d/pipeline/pipeline-app)
|
||||
cd <app root>(含 py3/ 的目录,如 /d/pipeline/pipeline-app)
|
||||
./py3/bin/python pkgs/accounting/scripts/load_path.py [--add-only]
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
import asyncio
|
||||
@ -51,9 +50,6 @@ if not APP_ROOT:
|
||||
print("ERROR: Cannot find app root directory")
|
||||
sys.exit(1)
|
||||
|
||||
PYTHON = os.path.join(APP_ROOT, "py3", "bin", "python")
|
||||
SET_PERM_SCRIPT = os.path.join(APP_ROOT, "set_role_perm.py")
|
||||
|
||||
MOD = "accounting"
|
||||
|
||||
# ============================================================
|
||||
@ -252,102 +248,100 @@ async def _find_rbac_db(db):
|
||||
return None
|
||||
|
||||
|
||||
async def resolve_role_ids(labels):
|
||||
async def resolve_role_ids(sor, labels):
|
||||
"""标签 'orgtypeid.name' → 真实 role.id 列表(同名多条全返回)。"""
|
||||
db = _get_db()
|
||||
dbname = await _find_rbac_db(db)
|
||||
mapping = {}
|
||||
if not dbname:
|
||||
print('WARN: role 表不可达,按字面量注册(可能无效)')
|
||||
return {lb: [lb] for lb in labels}
|
||||
async with db.sqlorContext(dbname) as sor:
|
||||
for label in labels:
|
||||
if label in ('any', 'logined', 'anonymous'):
|
||||
mapping[label] = [label]
|
||||
continue
|
||||
orgtypeid, _, name = label.partition('.')
|
||||
recs = await sor.sqlExe(
|
||||
'select id from role where orgtypeid=${o}$ and name=${n}$',
|
||||
{'o': orgtypeid, 'n': name})
|
||||
ids = [_row_get(r, 'id') for r in recs]
|
||||
ids = [i for i in ids if i]
|
||||
if not ids:
|
||||
print(f'WARN: 角色不存在 {label},跳过')
|
||||
mapping[label] = ids
|
||||
await sor.sqlExe('COMMIT', {})
|
||||
for label in labels:
|
||||
if label in ('any', 'logined', 'anonymous'):
|
||||
mapping[label] = [label]
|
||||
continue
|
||||
orgtypeid, _, name = label.partition('.')
|
||||
recs = await sor.sqlExe(
|
||||
'select id from role where orgtypeid=${o}$ and name=${n}$',
|
||||
{'o': orgtypeid, 'n': name})
|
||||
ids = [_row_get(r, 'id') for r in recs]
|
||||
ids = [i for i in ids if i]
|
||||
if not ids:
|
||||
print(f'WARN: 角色不存在 {label},跳过')
|
||||
mapping[label] = ids
|
||||
return mapping
|
||||
|
||||
|
||||
async def clean_accounting_roleperms():
|
||||
"""删除 /accounting/ 下全部旧授权(保留 permission 行本身)。"""
|
||||
db = _get_db()
|
||||
dbname = await _find_rbac_db(db)
|
||||
if not dbname:
|
||||
print('ERROR: 无法定位 RBAC 库,清理中止')
|
||||
return -1
|
||||
total = 0
|
||||
async with db.sqlorContext(dbname) as sor:
|
||||
perms = await sor.sqlExe(
|
||||
'select id from permission where path like ${p}$ or path=${p2}$',
|
||||
{'p': f'/{MOD}/%', 'p2': f'/{MOD}'})
|
||||
for p in perms:
|
||||
pid = _row_get(p, 'id')
|
||||
r = await sor.sqlExe('delete from rolepermission where permid=${pid}$', {'pid': pid})
|
||||
total += 1
|
||||
await sor.sqlExe('COMMIT', {})
|
||||
print(f'清理完成:/accounting/ 下 {len(perms)} 个 permission 的旧授权已删除')
|
||||
return total
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 注册
|
||||
# ============================================================
|
||||
|
||||
def run_set_perm(role_id, path):
|
||||
cmd = [PYTHON, SET_PERM_SCRIPT, role_id, path]
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, cwd=APP_ROOT)
|
||||
if result.returncode != 0:
|
||||
print(f" FAIL {role_id} {path}: {(result.stderr or result.stdout).strip()[:200]}")
|
||||
async def set_role_perm(sor, role_id, path):
|
||||
"""注册单条权限(幂等):permission 缺则建,rolepermission 缺则建。"""
|
||||
from appPublic.uniqueID import getID
|
||||
recs = await sor.R('permission', {'path': path})
|
||||
if not recs:
|
||||
permid = getID()
|
||||
await sor.C('permission', {'id': permid, 'path': path})
|
||||
else:
|
||||
permid = _row_get(recs[0], 'id')
|
||||
rp = await sor.R('rolepermission', {'roleid': role_id, 'permid': permid})
|
||||
if rp:
|
||||
return False
|
||||
await sor.C('rolepermission', {'id': getID(), 'roleid': role_id, 'permid': permid})
|
||||
return True
|
||||
|
||||
|
||||
def register_role_paths(role_label, role_ids, paths):
|
||||
if not role_ids:
|
||||
return 0
|
||||
count = 0
|
||||
for rid in role_ids:
|
||||
for p in paths:
|
||||
if run_set_perm(rid, p):
|
||||
count += 1
|
||||
print(f" {role_label} ({','.join(role_ids)}): {count}/{len(paths) * len(role_ids)} entries registered")
|
||||
return count
|
||||
async def run_all(add_only):
|
||||
db = _get_db()
|
||||
dbname = await _find_rbac_db(db)
|
||||
if not dbname:
|
||||
print('ERROR: 无法定位 RBAC 库(role 表不可达),中止')
|
||||
return 1
|
||||
print(f'RBAC 库: {dbname}')
|
||||
|
||||
total = 0
|
||||
async with db.sqlorContext(dbname) as sor:
|
||||
if not add_only:
|
||||
print('=== 清理旧授权 ===')
|
||||
perms = await sor.sqlExe(
|
||||
'select id from permission where path like ${p}$ or path=${p2}$',
|
||||
{'p': f'/{MOD}/%', 'p2': f'/{MOD}'})
|
||||
for p in perms:
|
||||
await sor.sqlExe('delete from rolepermission where permid=${pid}$',
|
||||
{'pid': _row_get(p, 'id')})
|
||||
await sor.sqlExe('COMMIT', {})
|
||||
print(f'清理完成:/accounting/ 下 {len(perms)} 个 permission 的旧授权已删除')
|
||||
|
||||
print('=== 解析角色 ===')
|
||||
all_labels = sorted(set(FIN_ROLES + PROXY_ROLES))
|
||||
role_map = await resolve_role_ids(sor, all_labels)
|
||||
for lb in all_labels:
|
||||
print(f' {lb} -> {role_map.get(lb) or "(不存在)"}')
|
||||
|
||||
print('=== 注册新矩阵 ===')
|
||||
|
||||
async def register_group(group_label, role_ids, paths):
|
||||
nonlocal total
|
||||
if not role_ids:
|
||||
return
|
||||
added = 0
|
||||
for rid in role_ids:
|
||||
for p in paths:
|
||||
if await set_role_perm(sor, rid, p):
|
||||
added += 1
|
||||
await sor.sqlExe('COMMIT', {})
|
||||
total += added
|
||||
print(f' {group_label} ({",".join(role_ids)}): +{added} 条'
|
||||
f'(目标 {len(paths) * len(role_ids)} 条,其余为已存在)')
|
||||
|
||||
await register_group('any', ['any'], PATHS_ANY)
|
||||
await register_group('logined', ['logined'], PATHS_LOGINED)
|
||||
for label in FIN_ROLES:
|
||||
await register_group(label, role_map.get(label, []), PATHS_FIN)
|
||||
for label in PROXY_ROLES:
|
||||
await register_group(label, role_map.get(label, []), PATHS_PROXY)
|
||||
|
||||
print(f'\nDone. 本次新增 {total} 条授权。')
|
||||
print('NOTE: 重启应用(或调用 /rbac/refresh_userperm.dspy)后权限生效。')
|
||||
return 0
|
||||
|
||||
|
||||
def main():
|
||||
add_only = '--add-only' in sys.argv
|
||||
print(f"App root: {APP_ROOT}")
|
||||
|
||||
if not add_only:
|
||||
print('=== 清理旧授权 ===')
|
||||
asyncio.run(clean_accounting_roleperms())
|
||||
|
||||
print('=== 解析角色 ===')
|
||||
all_labels = sorted(set(FIN_ROLES + PROXY_ROLES))
|
||||
role_map = asyncio.run(resolve_role_ids(all_labels))
|
||||
for lb in all_labels:
|
||||
print(f' {lb} -> {role_map.get(lb) or "(不存在)"}')
|
||||
|
||||
print('=== 注册新矩阵 ===')
|
||||
total = 0
|
||||
total += register_role_paths('any', ['any'], PATHS_ANY)
|
||||
total += register_role_paths('logined', ['logined'], PATHS_LOGINED)
|
||||
for label in FIN_ROLES:
|
||||
total += register_role_paths(label, role_map.get(label, []), PATHS_FIN)
|
||||
for label in PROXY_ROLES:
|
||||
total += register_role_paths(label, role_map.get(label, []), PATHS_PROXY)
|
||||
print(f"\nDone. Total {total} permission entries registered.")
|
||||
print("NOTE: 重启应用(或调用 /rbac/refresh_userperm.dspy)后权限生效。")
|
||||
sys.exit(asyncio.run(run_all(add_only)))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user