107 lines
4.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- 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"],
}