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 = {
|
ns = {
|
||||||
'accountid': accountid,
|
'accountid': accountid,
|
||||||
'orgid': userorgid
|
'orgid': userorgid,
|
||||||
|
'page': page,
|
||||||
|
'sort': 'acc_date desc'
|
||||||
}
|
}
|
||||||
ret = await sor.sqlExe(sql, ns)
|
ret = await sor.sqlExe(sql, ns)
|
||||||
return ret
|
return ret
|
||||||
|
|||||||
@ -22,11 +22,10 @@ accounting 模块 RBAC 权限管理脚本(角色分层版,2026-08-27 重构
|
|||||||
用 orgtypeid+name 查 role 表解析出真实 role.id 后注册,同名多条全部注册。
|
用 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]
|
./py3/bin/python pkgs/accounting/scripts/load_path.py [--add-only]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import asyncio
|
import asyncio
|
||||||
@ -51,9 +50,6 @@ if not APP_ROOT:
|
|||||||
print("ERROR: Cannot find app root directory")
|
print("ERROR: Cannot find app root directory")
|
||||||
sys.exit(1)
|
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"
|
MOD = "accounting"
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@ -252,102 +248,100 @@ async def _find_rbac_db(db):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
async def resolve_role_ids(labels):
|
async def resolve_role_ids(sor, labels):
|
||||||
"""标签 'orgtypeid.name' → 真实 role.id 列表(同名多条全返回)。"""
|
"""标签 'orgtypeid.name' → 真实 role.id 列表(同名多条全返回)。"""
|
||||||
db = _get_db()
|
|
||||||
dbname = await _find_rbac_db(db)
|
|
||||||
mapping = {}
|
mapping = {}
|
||||||
if not dbname:
|
for label in labels:
|
||||||
print('WARN: role 表不可达,按字面量注册(可能无效)')
|
if label in ('any', 'logined', 'anonymous'):
|
||||||
return {lb: [lb] for lb in labels}
|
mapping[label] = [label]
|
||||||
async with db.sqlorContext(dbname) as sor:
|
continue
|
||||||
for label in labels:
|
orgtypeid, _, name = label.partition('.')
|
||||||
if label in ('any', 'logined', 'anonymous'):
|
recs = await sor.sqlExe(
|
||||||
mapping[label] = [label]
|
'select id from role where orgtypeid=${o}$ and name=${n}$',
|
||||||
continue
|
{'o': orgtypeid, 'n': name})
|
||||||
orgtypeid, _, name = label.partition('.')
|
ids = [_row_get(r, 'id') for r in recs]
|
||||||
recs = await sor.sqlExe(
|
ids = [i for i in ids if i]
|
||||||
'select id from role where orgtypeid=${o}$ and name=${n}$',
|
if not ids:
|
||||||
{'o': orgtypeid, 'n': name})
|
print(f'WARN: 角色不存在 {label},跳过')
|
||||||
ids = [_row_get(r, 'id') for r in recs]
|
mapping[label] = ids
|
||||||
ids = [i for i in ids if i]
|
|
||||||
if not ids:
|
|
||||||
print(f'WARN: 角色不存在 {label},跳过')
|
|
||||||
mapping[label] = ids
|
|
||||||
await sor.sqlExe('COMMIT', {})
|
|
||||||
return mapping
|
return mapping
|
||||||
|
|
||||||
|
|
||||||
async def clean_accounting_roleperms():
|
async def set_role_perm(sor, role_id, path):
|
||||||
"""删除 /accounting/ 下全部旧授权(保留 permission 行本身)。"""
|
"""注册单条权限(幂等):permission 缺则建,rolepermission 缺则建。"""
|
||||||
db = _get_db()
|
from appPublic.uniqueID import getID
|
||||||
dbname = await _find_rbac_db(db)
|
recs = await sor.R('permission', {'path': path})
|
||||||
if not dbname:
|
if not recs:
|
||||||
print('ERROR: 无法定位 RBAC 库,清理中止')
|
permid = getID()
|
||||||
return -1
|
await sor.C('permission', {'id': permid, 'path': path})
|
||||||
total = 0
|
else:
|
||||||
async with db.sqlorContext(dbname) as sor:
|
permid = _row_get(recs[0], 'id')
|
||||||
perms = await sor.sqlExe(
|
rp = await sor.R('rolepermission', {'roleid': role_id, 'permid': permid})
|
||||||
'select id from permission where path like ${p}$ or path=${p2}$',
|
if rp:
|
||||||
{'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]}")
|
|
||||||
return False
|
return False
|
||||||
|
await sor.C('rolepermission', {'id': getID(), 'roleid': role_id, 'permid': permid})
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def register_role_paths(role_label, role_ids, paths):
|
async def run_all(add_only):
|
||||||
if not role_ids:
|
db = _get_db()
|
||||||
return 0
|
dbname = await _find_rbac_db(db)
|
||||||
count = 0
|
if not dbname:
|
||||||
for rid in role_ids:
|
print('ERROR: 无法定位 RBAC 库(role 表不可达),中止')
|
||||||
for p in paths:
|
return 1
|
||||||
if run_set_perm(rid, p):
|
print(f'RBAC 库: {dbname}')
|
||||||
count += 1
|
|
||||||
print(f" {role_label} ({','.join(role_ids)}): {count}/{len(paths) * len(role_ids)} entries registered")
|
total = 0
|
||||||
return count
|
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():
|
def main():
|
||||||
add_only = '--add-only' in sys.argv
|
add_only = '--add-only' in sys.argv
|
||||||
print(f"App root: {APP_ROOT}")
|
print(f"App root: {APP_ROOT}")
|
||||||
|
sys.exit(asyncio.run(run_all(add_only)))
|
||||||
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)后权限生效。")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user