Files
iAOP/core/data-bus/postgres_schema.py
T
yunmei 098125164d fix: 对齐技术架构补齐传输 mTLS 与结构化 JSON 日志(NFR 9 章)
架构核对发现 2 处差距,本次补齐:
- Kafka 上行支持 SSL/SASL_SSL 双向 mTLS(8.2 服务间 mTLS 边缘网关↔总线)
- 网关日志支持结构化 JSON 输出(NFR 可维护:统一日志规范)
- 配置示例与 README 验收口径同步更新
2026-08-04 15:46:09 +08:00

117 lines
4.3 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 -*-
"""PostgreSQL 关系表 schema(模板 / 模型 / 用户 / 权限)—— 子任务 #30。
按模板自动生成隔离 schema(`tpl_{tpl}`),内含四张基础关系表:
- templates 模板注册表(行业模板配置资产);
- models 模型注册表(模型版本 / 算法 / 超参包);
- users 用户表(角色 + 细粒度权限 JSONB);
- permissions 角色-资源-动作权限矩阵。
另生成角色授权语句(GRANT),按模板配置声明 databus_ro / databus_rw 等角色。
不依赖 psycopg2:仅产出 DDL 文本,供模板配置台预览 / 运维执行。
"""
from __future__ import annotations
from typing import List, Optional
from .templating import TemplateNaming
# 默认基础表清单(对应子任务 #30「模板/模型/用户/权限」)
DEFAULT_TABLES: List[str] = ["templates", "models", "users", "permissions"]
# 表 → 列定义(可被模板 YAML 的 schema_tables 覆盖为子集/扩展)
TABLE_COLUMNS: dict = {
"templates": [
"id BIGSERIAL PRIMARY KEY",
"template VARCHAR(64) NOT NULL UNIQUE",
"version VARCHAR(32) NOT NULL DEFAULT '0.1.0'",
"config JSONB NOT NULL DEFAULT '{}'::jsonb",
"status VARCHAR(16) NOT NULL DEFAULT 'draft'",
"created_at TIMESTAMPTZ NOT NULL DEFAULT now()",
],
"models": [
"id BIGSERIAL PRIMARY KEY",
"model_id VARCHAR(128) NOT NULL UNIQUE",
"template VARCHAR(64) REFERENCES {schema}.templates(template) ON DELETE CASCADE",
"algorithm VARCHAR(32) NOT NULL DEFAULT 'xgboost'",
"hyperparams JSONB NOT NULL DEFAULT '{}'::jsonb",
"version VARCHAR(32) NOT NULL DEFAULT '0.1.0'",
"status VARCHAR(16) NOT NULL DEFAULT 'staging'",
"created_at TIMESTAMPTZ NOT NULL DEFAULT now()",
],
"users": [
"id BIGSERIAL PRIMARY KEY",
"username VARCHAR(64) NOT NULL UNIQUE",
"role VARCHAR(32) NOT NULL DEFAULT 'viewer'",
"permissions JSONB NOT NULL DEFAULT '[]'::jsonb",
"created_at TIMESTAMPTZ NOT NULL DEFAULT now()",
],
"permissions": [
"id BIGSERIAL PRIMARY KEY",
"role VARCHAR(32) NOT NULL",
"resource VARCHAR(64) NOT NULL",
"action VARCHAR(16) NOT NULL",
"UNIQUE (role, resource, action)",
],
}
def generate_schema_ddl(
naming: TemplateNaming,
tables: Optional[List[str]] = None,
table_columns: Optional[dict] = None,
) -> str:
"""生成 schema 与基础关系表的完整 DDL(幂等 IF NOT EXISTS)。
Args:
naming: 模板命名器(决定 schema 名)。
tables: 表清单(默认 DEFAULT_TABLES)。
table_columns: 表→列定义覆盖(默认 TABLE_COLUMNS)。
Returns:
多语句 DDL 文本(含 CREATE SCHEMA / CREATE TABLE)。
"""
names = tables or DEFAULT_TABLES
cols = table_columns or TABLE_COLUMNS
schema = naming.pg_schema()
lines = [f"CREATE SCHEMA IF NOT EXISTS {schema};", ""]
for table in names:
columns = cols.get(table)
if not columns:
continue
lines.append(f"CREATE TABLE IF NOT EXISTS {schema}.{table} (")
lines.append(" " + ",\n ".join(c.format(schema=schema) for c in columns))
lines.append(");")
lines.append("")
return "\n".join(lines).rstrip() + "\n"
def generate_grant_ddl(
naming: TemplateNaming,
roles: Optional[List[str]] = None,
) -> List[str]:
"""按模板声明的关系角色生成授权语句。
角色约定:`{role}_ro` 只读、`{role}_rw` 读写(可扩展)。
Args:
naming: 模板命名器。
roles: 角色清单(如 ["databus"] → databus_ro / databus_rw)。
Returns:
GRANT 语句列表。
"""
schema = naming.pg_schema()
grants: List[str] = []
for role in (roles or ["databus"]):
for suffix, privileges in (("ro", "SELECT"), ("rw", "SELECT, INSERT, UPDATE, DELETE")):
role_name = f"{role}_{suffix}"
grants.append(f"GRANT USAGE ON SCHEMA {schema} TO {role_name};")
grants.append(
f"GRANT {privileges} ON ALL TABLES IN SCHEMA {schema} TO {role_name};"
)
if suffix == "rw":
grants.append(
f"GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA {schema} TO {role_name};"
)
return grants