105 lines
3.5 KiB
Python
105 lines
3.5 KiB
Python
"""Permission initialization utility for business modules.
|
|
|
|
Scans wwwroot directory for .ui and .dspy files, registers them in
|
|
the permission table, and grants access to convention roles.
|
|
|
|
Convention roles:
|
|
- any: anyone (no auth required)
|
|
- logined: any logged-in user
|
|
- customer.*: customer org arbitrary role
|
|
- owner.*: owner org arbitrary role
|
|
- owner.superuser: superuser for initialization
|
|
"""
|
|
import os
|
|
from appPublic.uniqueID import getID
|
|
from appPublic.log import debug
|
|
from sqlor.dbpools import DBPools
|
|
|
|
|
|
def collect_ui_dspy_paths(wwwroot_dir):
|
|
"""Scan wwwroot directory and return list of URL paths for .ui/.dspy files."""
|
|
paths = []
|
|
for dirpath, _, filenames in os.walk(wwwroot_dir):
|
|
for fn in sorted(filenames):
|
|
if fn.endswith(('.ui', '.dspy')):
|
|
full = os.path.join(dirpath, fn)
|
|
rel = os.path.relpath(full, wwwroot_dir)
|
|
# Convert to URL path: module_name/relative/path
|
|
url = '/' + rel.replace(os.sep, '/')
|
|
# Skip base.ui (layout template, not a standalone page)
|
|
if fn == 'base.ui':
|
|
continue
|
|
paths.append(url)
|
|
return paths
|
|
|
|
|
|
async def ensure_permission(sor, path, permtype='page'):
|
|
"""Ensure permission exists in database, return permid."""
|
|
recs = await sor.R('permission', {'path': path})
|
|
if recs:
|
|
return recs[0].id
|
|
permid = getID()
|
|
await sor.C('permission', {
|
|
'id': permid,
|
|
'name': path.split('/')[-1],
|
|
'path': path,
|
|
'permtype': permtype,
|
|
})
|
|
return permid
|
|
|
|
|
|
async def ensure_role(sor, orgtypeid, name):
|
|
"""Ensure role exists in database, return roleid."""
|
|
recs = await sor.R('role', {'orgtypeid': orgtypeid, 'name': name})
|
|
if recs:
|
|
return recs[0].id
|
|
roleid = getID()
|
|
await sor.C('role', {
|
|
'id': roleid,
|
|
'orgtypeid': orgtypeid,
|
|
'name': name,
|
|
})
|
|
return roleid
|
|
|
|
|
|
async def grant_permission(sor, roleid, permid):
|
|
"""Grant permission to role if not already granted."""
|
|
recs = await sor.R('rolepermission', {'roleid': roleid, 'permid': permid})
|
|
if not recs:
|
|
await sor.C('rolepermission', {
|
|
'id': getID(),
|
|
'roleid': roleid,
|
|
'permid': permid,
|
|
})
|
|
|
|
|
|
async def init_module_permissions(dbname, module_name, wwwroot_dir):
|
|
"""Initialize permissions for a business module.
|
|
|
|
Scans wwwroot for .ui/.dspy files, registers paths in permission table,
|
|
and grants access to convention roles (logined, customer.*, owner.superuser).
|
|
"""
|
|
paths = collect_ui_dspy_paths(wwwroot_dir)
|
|
if not paths:
|
|
debug(f'{module_name}: no UI/DSPY paths found, skipping permission init')
|
|
return
|
|
|
|
db = DBPools()
|
|
async with db.sqlorContext(dbname) as sor:
|
|
# Ensure convention roles exist
|
|
role_logined = await ensure_role(sor, '*', 'logined')
|
|
role_customer = await ensure_role(sor, 'customer', '*')
|
|
role_superuser = await ensure_role(sor, 'owner', 'superuser')
|
|
|
|
# Register paths and grant permissions
|
|
for path in paths:
|
|
permid = await ensure_permission(sor, path)
|
|
# Grant to logined users
|
|
await grant_permission(sor, role_logined, permid)
|
|
# Grant to customer org users
|
|
await grant_permission(sor, role_customer, permid)
|
|
# Grant to superuser
|
|
await grant_permission(sor, role_superuser, permid)
|
|
|
|
debug(f'{module_name}: registered {len(paths)} permissions')
|