feat: 配置API(分组校验管线/整份版本/回滚/重置出厂/试金石/平台设置)
- config_validation.validate_group: 九组校验管线(类型/键 allowlist/数值 范围/prompts 大小上限 50KB·100KB/wall 全量交 compile_wall/push.prefix 跨租户查重 spec E1),错误清单中文带字段路径 - config_routes: GET/PUT config(整组替换原样入版本,MAX+1,热 reload)/ reset(按 Tenant.profile 取出厂档案组)/versions 列表·详情/rollback (旧版复制为新版本,历史不可变)/wall/test 试金石(逐句判定,不落库 不 bump)/settings 平台设置 CRUD(仅超管,resolver 接线归 Phase 3) - db.write_config_version: 版本写入公共路径(创建向导与配置 API 单一 事实源);Tenant 落 profile 列(重置出厂按它取对应档案) - _profile_snapshot/_blankify 迁 tenant_source(两路由模块共用); db_source_app/super_client 夹具收拢 conftest(两测试文件共用) - 测试: 519 → 537 全绿 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
"""租户管理 API(Phase 2 Task 5):超管的创建向导/站点/域名/停用 + 403 边界。
|
||||
|
||||
db_source_app 夹具:app.state.registry 用 DbTenantSource(生产形态)指向
|
||||
临时 platform.db——创建 API 写库后 registry_reload 走 DB 源闭环(Task 4
|
||||
db_source_app/super_client 夹具(Task 6 起收拢到 conftest,与配置 API 测试
|
||||
共用):app.state.registry 用 DbTenantSource(生产形态)指向临时
|
||||
platform.db——创建 API 写库后 registry_reload 走 DB 源闭环(Task 4
|
||||
的 upsert 语义:未加载的 slug 直接插入,创建即可用)。platform.db 起始
|
||||
为空(schema+bootstrap 超管由 lifespan 跑)——租户全部经创建 API 进入,
|
||||
registry 不做初始 load_all(生产装配的启动次序归 Task 11)。
|
||||
@@ -20,62 +21,23 @@ from sqlalchemy.pool import NullPool
|
||||
|
||||
from app.engine.services.ai_service import PromptProvider
|
||||
from app.engine.wall_schema import compile_wall
|
||||
from app.main import app
|
||||
from app.platform.db import (
|
||||
AdminUser,
|
||||
Site,
|
||||
SiteDomain,
|
||||
Tenant,
|
||||
TenantConfigVersion,
|
||||
make_platform_engine,
|
||||
)
|
||||
from app.platform.defaults import DEFAULT_CONFIG
|
||||
from app.platform.registry import TenantDisabledError, TenantRegistry
|
||||
from app.platform.routes.tenant_routes import _blankify
|
||||
from app.platform.tenant_source import DbTenantSource, FileTenantSource
|
||||
from tests.conftest import SEED_DIR, app_test_client
|
||||
from app.platform.registry import TenantDisabledError
|
||||
from app.platform.tenant_source import FileTenantSource, _blankify
|
||||
from tests.conftest import SEED_DIR
|
||||
|
||||
TENANTS = "/api/platform/tenants"
|
||||
LOGIN = "/api/platform/auth/login"
|
||||
CHANGE_PW = "/api/platform/auth/change-password"
|
||||
|
||||
|
||||
# ---- 夹具 ----------------------------------------------------------------------
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def db_source_app(tmp_path):
|
||||
"""app + 生产形态 registry(DbTenantSource 指向临时 platform.db)。
|
||||
|
||||
platform_engine 也指同一临时库(lifespan 在 portal 循环里 ensure_schema
|
||||
+ bootstrap 超管 admin/admin123)。teardown 复位 app.state(照抄
|
||||
app_test_client 的关残留窗纪律;engine dispose 由 lifespan finally)。
|
||||
"""
|
||||
engine = make_platform_engine(tmp_path / "platform.db")
|
||||
app.state.registry = TenantRegistry(
|
||||
DbTenantSource(engine), data_dir=tmp_path / "tenants")
|
||||
app.state.platform_engine = engine
|
||||
try:
|
||||
yield app
|
||||
finally:
|
||||
app.state.registry = None
|
||||
app.state.platform_engine = None
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def super_client(db_source_app, tmp_path):
|
||||
"""超管 client:lifespan bootstrap 的 admin/admin123 登录 + 首登改密
|
||||
(过 must_change 409 门)。token 挂 client.platform_token。"""
|
||||
with app_test_client(db_source_app, "http://testserver", tmp_path) as c:
|
||||
r = c.post(LOGIN, json={"username": "admin", "password": "admin123"})
|
||||
assert r.status_code == 200
|
||||
c.platform_token = r.json()["token"]
|
||||
r = c.post(CHANGE_PW, headers=_auth(c), json={
|
||||
"old_password": "admin123", "new_password": "sup3r-pass-1"})
|
||||
assert r.status_code == 200
|
||||
yield c
|
||||
|
||||
|
||||
# ---- 助手 ----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user