feat: add scripts/load_path.py for RBAC permission initialization
- Add scripts/load_path.py with all 28 wwwroot paths - menu.ui set to 'any' role (public nav access) - All other paths set to 'logined' role (dashboard visible to authenticated users) - Idempotent: skips already-registered paths
This commit is contained in:
parent
e7fc646372
commit
fd8443f445
141
scripts/load_path.py
Normal file
141
scripts/load_path.py
Normal file
@ -0,0 +1,141 @@
|
||||
"""Generate RBAC permissions for dashboard_for_sage module paths.
|
||||
|
||||
Run from Sage root with Sage venv:
|
||||
cd ~/repos/sage && ./py3/bin/python ../dashboard_for_sage/scripts/load_path.py
|
||||
|
||||
Or set SAGE_ROOT environment variable.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import asyncio
|
||||
|
||||
# Ensure Sage root is in path
|
||||
sage_root = os.environ.get('SAGE_ROOT')
|
||||
if sage_root and sage_root not in sys.path:
|
||||
sys.path.insert(0, sage_root)
|
||||
|
||||
from sqlor.dbpools import DBPools
|
||||
from appPublic.jsonConfig import getConfig
|
||||
from appPublic.dictObject import DictObject
|
||||
from appPublic.uniqueID import getID
|
||||
|
||||
|
||||
# ── Permission definitions ──
|
||||
# Format: (path, role)
|
||||
# Dashboard files are accessible to all logined users except menu.ui (any)
|
||||
paths = [
|
||||
# Module root and index
|
||||
("/dashboard_for_sage", "logined"),
|
||||
("/dashboard_for_sage/index.ui", "logined"),
|
||||
|
||||
# Menu — must be any so unauthenticated users can see nav
|
||||
("/dashboard_for_sage/menu.ui", "any"),
|
||||
|
||||
# Shell / theme files
|
||||
("/dashboard_for_sage/shell.ui", "logined"),
|
||||
("/dashboard_for_sage/shell_theme.css", "logined"),
|
||||
("/dashboard_for_sage/shell_theme.js", "logined"),
|
||||
|
||||
# Global menu
|
||||
("/dashboard_for_sage/global_menu.ui", "logined"),
|
||||
|
||||
# Stat cards
|
||||
("/dashboard_for_sage/stat_today_usage.ui", "logined"),
|
||||
("/dashboard_for_sage/stat_today_amount.ui", "logined"),
|
||||
("/dashboard_for_sage/stat_total_users.ui", "logined"),
|
||||
("/dashboard_for_sage/stat_active_users.ui", "logined"),
|
||||
("/dashboard_for_sage/stat_concurrent.ui", "logined"),
|
||||
("/dashboard_for_sage/stat_errors.ui", "logined"),
|
||||
("/dashboard_for_sage/stat_new_users_month.ui", "logined"),
|
||||
("/dashboard_for_sage/stat_total_orgs.ui", "logined"),
|
||||
|
||||
# Legacy stat cards (backward compat)
|
||||
("/dashboard_for_sage/today_usage.ui", "logined"),
|
||||
("/dashboard_for_sage/today_amount.ui", "logined"),
|
||||
("/dashboard_for_sage/total_users.ui", "logined"),
|
||||
("/dashboard_for_sage/concurrent_users.ui", "logined"),
|
||||
("/dashboard_for_sage/accounting_errors.ui", "logined"),
|
||||
|
||||
# Top 5 ranking cards
|
||||
("/dashboard_for_sage/table_top_users.ui", "logined"),
|
||||
("/dashboard_for_sage/table_top_users_amount.ui", "logined"),
|
||||
("/dashboard_for_sage/table_top_users_count.ui", "logined"),
|
||||
("/dashboard_for_sage/table_top_providers_amount.ui", "logined"),
|
||||
("/dashboard_for_sage/table_top_providers_count.ui", "logined"),
|
||||
("/dashboard_for_sage/top_users_amount.ui", "logined"),
|
||||
|
||||
# Charts
|
||||
("/dashboard_for_sage/chart_top_models.ui", "logined"),
|
||||
("/dashboard_for_sage/top_models_chart.ui", "logined"),
|
||||
|
||||
# API endpoints
|
||||
("/dashboard_for_sage/api/top_models.dspy", "logined"),
|
||||
]
|
||||
|
||||
|
||||
async def add_roleperm(sor, roleid, permid):
|
||||
"""Add role-permission mapping if not exists."""
|
||||
ns = {'roleid': roleid, 'permid': permid}
|
||||
recs = await sor.R('rolepermission', ns.copy())
|
||||
if not recs:
|
||||
ns['id'] = getID()
|
||||
await sor.C('rolepermission', ns.copy())
|
||||
|
||||
|
||||
async def add_roles_perm(sor, perm, roles):
|
||||
"""Register permission for special roles."""
|
||||
if roles in [['any'], ['anonymous'], ['logined']]:
|
||||
role = roles[0]
|
||||
await add_roleperm(sor, role, perm.id)
|
||||
return
|
||||
|
||||
for role in roles:
|
||||
if '.' in role:
|
||||
orgtypeid, name = role.split('.', 1)
|
||||
else:
|
||||
orgtypeid, name = '*', role
|
||||
|
||||
ns = {'orgtypeid': orgtypeid, 'name': name}
|
||||
roles_rec = await sor.R('role', ns.copy())
|
||||
if not roles_rec:
|
||||
ns['id'] = getID()
|
||||
await sor.C('role', ns.copy())
|
||||
else:
|
||||
ns['id'] = roles_rec[0].id
|
||||
|
||||
await add_roleperm(sor, ns['id'], perm.id)
|
||||
|
||||
# Remove 'any' fallback for this perm
|
||||
ns_any = {'roleid': 'any', 'permid': perm.id}
|
||||
existing = await sor.R('rolepermission', ns_any.copy())
|
||||
if existing:
|
||||
await sor.D('rolepermission', {'id': existing[0].id})
|
||||
|
||||
|
||||
async def main():
|
||||
config = getConfig('.')
|
||||
db = DBPools(config.databases)
|
||||
cnt = 0
|
||||
|
||||
async with db.sqlorContext('sage') as sor:
|
||||
for path, role in paths:
|
||||
ns = {'path': path}
|
||||
recs = await sor.R('permission', ns.copy())
|
||||
if recs:
|
||||
# Permission exists, skip (idempotent)
|
||||
continue
|
||||
|
||||
cnt += 1
|
||||
pid = getID()
|
||||
ns['id'] = pid
|
||||
await sor.C('permission', ns.copy())
|
||||
perm = DictObject(**ns)
|
||||
await add_roles_perm(sor, perm, [role])
|
||||
|
||||
print(f'{cnt} path(s) inserted for dashboard_for_sage')
|
||||
if cnt == 0:
|
||||
print('All paths already registered — no changes needed.')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.get_event_loop().run_until_complete(main())
|
||||
Loading…
x
Reference in New Issue
Block a user