2025-07-16 14:19:12 +08:00
2025-07-16 14:19:12 +08:00
2025-07-16 14:19:12 +08:00
2026-04-16 14:36:29 +08:00

rbac — 角色权限模块

产线平台/Sage 系应用的基础模块,提供**用户、机构、角色、权限RBAC**的完整管理体系,以及登录认证(密码/短信/扫码/Bearer API key 等多种认证方式注册点)、权限校验拦截、审计日志和双层权限缓存。所有宿主应用的鉴权都收敛到本模块的 objcheckperm(挂到 AuthAPI.checkUserPermission)。

模块定位

  • 数据模型层:用户/机构/角色/权限四套表(见下)。
  • 认证层:check_perm.py 实现密码登录(含 3 次失败锁定 5 分钟)、getAuthenticationUseridAuthorization 头前缀分发到已注册的认证方法(内置 Basic ,其他模块可通过 register_auth_method 注册,如 dapi 注册 Bearer /Deerer )。
  • 授权层:userperm.pyUserPermissions(单例)负责"用户→角色→路径权限"的判定,含 LRU+Redis 双层缓存。
  • 事件层:init.py 通过 DBPools 绑定 role/userrole/permission/rolepermission 四表的 C/U/D after 事件,变更即失效缓存。

表清单models/*.json

标题 关键字段 说明
users 用户 id, username, password, email, orgid, nick_name, mobile, login_fail_count, last_login_fail, last_login 密码 RC4appPublic.rc4加密存储
organization 机构 id, orgname, orgabbr, alias_name, contactor, contactor_phone, province_id, city_id 支持层级parentid
orgtypes 机构拥有角色 id, orgid, orgtypeid orgtypeid 取自 appbase 的 appcodes_kvparentid='org_type'
role 角色 id, orgtypeid(默认'0'), name 角色全名 = {orgtypeid}.{name}
userrole 用户角色 id, userid, roleid 用户↔角色多对多
permission 权限 id, name, parentid, path, icon, permtype, need_audit path 即受保护的 URL 路径
rolepermission 角色权限表 id, roleid, permid 角色↔权限多对多
audit_log 审计日志 id, permid, userid, params_kw, exe_date, exe_timestamp, remote_ip need_audit 权限调用时由 audit_log.write_audit_log 落表

models/ 为 sqlor DDL 源,json/ 为 bricks CRUD 页面定义(另含 reseller.json、provider.json 等展示用定义)。

角色模型

  • 判定键为 {orgtypeid}.{name},加载用户角色时自动派生通配角色:{orgtypeid}.**.{name};每个登录用户固定拥有 anylogined 两个隐式角色,未登录请求按 anonymous/any 处理。
  • 常用内置角色(由部署脚本/SQL 种子创建):
    • owner.superuser — 平台超级管理员rbac 管理页面、register_rbac_tools_perm.py 注册的工具权限都挂在此角色)。
    • owner.admin — 平台管理员。
    • owner.audit — 审计只读角色(配合 audit_log 模块,审计独立性)。
    • downapp.logined — dapi 模块在 API key 认证成功后自动创建并授予(见 ensure_downappuser_role_and_assign)。
  • 路径匹配(check_roles_path):精确匹配、**/% 前缀通配、/main/xxx/xxx 归一化。
  • 超管创建参考 pipeline-app/scripts/create_superuser.pyorgtypeid=owner, roles=[superuser, admin])。

缓存机制(重点)

UserPermissions 使用双层缓存

  • L1 进程内ur_caches用户→角色LRU maxsize=10000TTL 300srp_caches角色→路径集合全量TTL 600s,双检锁+原子换入防止加载期间 403
  • L2 Redis 共享:经 appPublic.share_cachecache_set/cache_get/cache_invalidate写入key 为 rbac:role_permsrbac:user_roles:{userid}TTL 与 L1 相同600s/300s供多 worker 进程复用。
  • 开关:config.jsonmodule_cache.rbac=false 可整体禁用缓存(调试用)。
  • 失效途径:
    1. role/userrole/permission/rolepermission 表 C/U/D 事件(register_rbac_event_listenersuserrole 变更精确失效单个用户,其余全量失效 rp_caches
    2. hot_reload 事件(on_hot_reload 清空两层);
    3. 手动调用 ServerEnv().invalidate_user_perm_cache(userid) / invalidate_all_perm_caches() / invalidate_role_perm_cache(),或访问 /rbac/refresh_userperm.dspy

部署纪律:直接改数据库里的角色/权限数据(绕过事件绑定)后,缓存不会自动失效。必须 redis-cli FLUSHDB 清掉 L2 共享缓存并重启应用进程清掉各 worker 的 L1 缓存,否则最长 600 秒内旧权限继续生效(可能放行或误拦)。

对外 API / dspy 端点wwwroot/

  • 登录认证:userpassword_login.dspyphone_login.dspygen_sms_code.dspyuser/up_login.dspyuser/code_login.dspyuser/logout.dspyuser/register.dspyuser/sms_register.dspyuser/reset_password/reset_password.dspy
  • 用户资料:user/edit_profile.dspyuser/save_profile.dspy
  • 管理端:add_adminuser.dspyadd_provider.dspyget_provider.dspyadd_reseller.dspyget_reseller.dspy
  • 角色权限查询:get_all_roles.dspyget_normal_roles.dspylist_path_roles.dspyfind_unauth_files.dspy(扫描 wwwroot 中未注册权限的文件)、api/get_search_roleid.dspy
  • 用户 CRUDapi/add_user.dspyapi/update_user.dspy
  • 缓存刷新:refresh_userperm.dspy
  • 用户同步:usersync/index.dspy(把 rbac 用户同步到 dapi 并生成 API key接口文档见 docs/userasync-api.md
  • UIadmin_menu.uilist_path_roles.uiuser/login.uiuser/user_panel.uistat_*.ui(用户/机构统计卡片)等

权限注册分三档:any(免登录,见 scripts/load_path.py 的 PATHS_ANYlogined(登录即可)、具体角色(如 owner.superuser,见 script/register_rbac_tools_perm.py)。

load 注册函数

入口 rbac/init.pyload_rbac(),向 ServerEnv() 单例挂载:

env.userpermissions            # UserPermissions 单例
env.create_org / create_user / register_user / register_auth_method
env.check_user_password / get_user_roles / get_org_users / sor_get_org_users
env.set_role_perm / set_role_perms / sor_add_user_roles
env.get_platform_providers / get_owner_orgid
env.invalidate_user_perm_cache / invalidate_all_perm_caches / invalidate_role_perm_cache
AuthAPI.checkUserPermission = objcheckperm   # ahserver 鉴权拦截点

并绑定 hot_reload 事件与四张权限表的 DB 事件监听。

辅助模块:rbac_tools.pyquery_path_roles/scan_unauth_filesaudit_log.pywrite_audit_logorgs.pyget_platform_providersuser_stats.pyset_role_perms.pyversion.py

宿主集成

宿主应用在启动入口(如 sage/app/sage.pypipeline-app/app/pipeline_app.pycpcc/app/cpcc.pyfilemgr/app/fileMGR.py)中:

from rbac.init import load_rbac
...
load_appbase()   # 先加载 appbaserbac 注册开关读 params 表)
load_rbac()
load_dapi()      # 依赖 rbac 的 register_auth_method必须在其后

依赖ahserverAuthAPI/ServerEnv、sqlorDBPools/get_sor_context、appPublicrc4/share_cache/jsonConfig 等、appbaseparams 表的 register_open 控制注册开关)。

数据库名解析:ServerEnv().get_module_dbname('rbac'),宿主需在 config.json 中配置模块→库映射(或默认同库)。

部署注意

  1. 加载顺序appbase → rbac → dapi/业务模块rbac 必须最先完成 AuthAPI.checkUserPermission 挂载,否则所有请求无鉴权。
  2. 权限注册:部署新页面/dspy 后运行 scripts/load_path.pyany/logined 分档)或 set_role_perm.py 注册路径权限,否则会被默认拦截;可用 find_unauth_files.dspy 扫描遗漏。
  3. 改权限数据后必须 FLUSHDB + 重启(见上文缓存机制),这是双层缓存(进程内 LRU + Redisrp TTL 600s下的硬性运维动作。
  4. script/init.py 内含示例数据库口令,仅供本地初始化参考,生产以宿主 config.json 为准;密码字段一律 RC4appPublic.rc4.password)加密。
  5. 登录防爆破3 次失败锁定 5 分钟(LOGIN_LOCKOUT_DURATION),审计写 audit_log 表;need_audit='1' 的权限调用也会落审计。
  6. usersync 接口把用户下发给 dapi下位系统 API key 体系),文档见 docs/userasync-api.md
Description
No description provided
Readme 1.1 MiB
Languages
Python 88.9%
CSS 10.5%
Shell 0.6%