107 lines
4.2 KiB
Python
107 lines
4.2 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""pbl_domain_ext 模块挂载入口。
|
||
|
||
应用侧调用 ``load_pbl_domain_ext()`` 完成:
|
||
1. 注册 13 个 dspy 契约路由(wwwroot/api/*.dspy -> api.py 契约函数);
|
||
2. 注册 RBAC 权限点(owner.pbl / tenant 管理员可写,其余只读);
|
||
3. 注入 sqlor 句柄与库名(ServerEnv().get_module_dbname);
|
||
4. 幂等保障扩展列名为设计 §J1 权威名 ``ext_json``(旧名 ext_json 自动 RENAME)。
|
||
|
||
铁律:本模块**不创建/不修改** world、scene、entity 三张基础域基表。
|
||
"""
|
||
|
||
from . import api, db
|
||
from .base import TABLE, EXT_FIELD, REF_TYPES, BIND_STATES
|
||
from .errors import PblDomainExtError
|
||
|
||
__all__ = ["load_pbl_domain_ext", "MODULE_NAME", "API_ROUTES", "PERMISSIONS",
|
||
"TABLE", "EXT_FIELD", "REF_TYPES", "BIND_STATES"]
|
||
|
||
MODULE_NAME = "pbl_domain_ext"
|
||
|
||
#: dspy 契约路由表:url 后缀 -> (action 名, 是否写操作)
|
||
API_ROUTES = [
|
||
("pbl_domain_ref_bind", "pbl_domain_ref_bind", True),
|
||
("pbl_domain_ref_unbind", "pbl_domain_ref_unbind", True),
|
||
("pbl_domain_ref_update", "pbl_domain_ref_update", True),
|
||
("pbl_domain_ref_get", "pbl_domain_ref_get", False),
|
||
("pbl_domain_ref_list", "pbl_domain_ref_list", False),
|
||
("pbl_domain_ref_check_access", "pbl_domain_ref_check_access", False),
|
||
("pbl_world_list_by_tenant", "pbl_world_list_by_tenant", False),
|
||
("pbl_world_get_context", "pbl_world_get_context", False),
|
||
("pbl_scene_list_by_world", "pbl_scene_list_by_world", False),
|
||
("pbl_entity_list_by_scene", "pbl_entity_list_by_scene", False),
|
||
("pbl_team_bind_world", "pbl_team_bind_world", True),
|
||
("pbl_team_world_list", "pbl_team_world_list", False),
|
||
("pbl_team_list_by_class", "pbl_team_list_by_class", False),
|
||
]
|
||
|
||
#: RBAC 权限点(写 4 个 + 读 1 个聚合)
|
||
PERMISSIONS = [
|
||
{"code": "pbl_domain_ext:ref:write", "name": "PBL基础域关联-写",
|
||
"note": "绑定/解绑/更新 pbl_domain_ref"},
|
||
{"code": "pbl_domain_ext:ref:read", "name": "PBL基础域关联-读",
|
||
"note": "查询关联记录与基础域只读视图"},
|
||
{"code": "pbl_domain_ext:team:bind", "name": "PBL团队绑定世界",
|
||
"note": "team/class 与 world 的绑定关系维护"},
|
||
]
|
||
|
||
|
||
def _register_routes(app=None):
|
||
"""注册 dspy 路由(平台 register_dspy 可用时走平台,否则仅返回路由表)。"""
|
||
registered = []
|
||
for name, action, is_write in API_ROUTES:
|
||
url = "/%s/api/%s.dspy" % (MODULE_NAME, name)
|
||
registered.append({"url": url, "action": action, "write": is_write,
|
||
"handler": getattr(api, action, None)})
|
||
if app is not None and hasattr(app, "register_dspy"):
|
||
for item in registered:
|
||
try:
|
||
app.register_dspy(item["url"], item["handler"])
|
||
except Exception: # noqa: BLE001 平台版本差异不阻断挂载
|
||
pass
|
||
return registered
|
||
|
||
|
||
def _register_permissions(app=None):
|
||
"""注册 RBAC 权限点(幂等)。"""
|
||
if app is not None and hasattr(app, "register_permissions"):
|
||
try:
|
||
app.register_permissions(MODULE_NAME, PERMISSIONS)
|
||
except Exception: # noqa: BLE001
|
||
pass
|
||
return list(PERMISSIONS)
|
||
|
||
|
||
def load_pbl_domain_ext(app=None, sor=None, ensure_schema=True):
|
||
"""挂载模块。
|
||
|
||
:param app: 应用对象(可选,用于注册路由/权限)
|
||
:param sor: sqlor 句柄(可选;缺省时由 db.get_sor() 惰性从 ServerEnv 取)
|
||
:param ensure_schema: 是否执行 ext_json 列名幂等保障(默认 True)
|
||
:return: 挂载信息 dict
|
||
"""
|
||
if sor is not None:
|
||
db.set_sor(sor)
|
||
routes = _register_routes(app)
|
||
perms = _register_permissions(app)
|
||
|
||
schema_action = "skip"
|
||
if ensure_schema:
|
||
try:
|
||
schema_action = db.ensure_ext_column()
|
||
except PblDomainExtError as exc:
|
||
schema_action = "skip(%s)" % exc.code
|
||
|
||
return {
|
||
"module": MODULE_NAME,
|
||
"table": TABLE,
|
||
"ext_field": EXT_FIELD,
|
||
"ref_types": list(REF_TYPES),
|
||
"bind_states": list(BIND_STATES),
|
||
"routes": routes,
|
||
"permissions": perms,
|
||
"schema_action": schema_action,
|
||
"base_tables_readonly": ["world", "scene", "entity"],
|
||
}
|