mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 12:02:27 +08:00
refactor(platform): 平台白名单由数据库约束改为应用层校验
新增迁移 242 删除 user_platform_quotas_platform_check 与 composite_model_routes_target_platform_check(DROP ... IF EXISTS,可重入)。 此后新增平台只需在平台清单中登记,不再需要改约束的迁移;此前 Grok、国产 厂商、MiniMax、OpenCode 共写过 5 次。 平台合法性改由应用层保证,与原约束的拒绝范围相同: - user_platform_quotas 用原生 SQL 写入,不经过 ent Validate,repository 在 BulkInsertInitial / UpsertForUser 写入前校验平台,非法值在发出任何 SQL 前 返回错误(此前由数据库拒绝并回滚); - ent schema 的 platform / target_platform 校验改查平台清单,组合路由新增 target_platform 校验(service 层与 admin 接口的原有校验保留)。 渠道监控的 provider 约束表示已实现的探测能力,不属于平台清单,保留不动。 集成测试(真实 PostgreSQL):在还原旧约束的库上重复执行迁移、约束被移除、 渠道监控约束保留、数据库层可写入未来的新平台值;repository 拒绝未登记平台 且不产生副作用(去掉校验后该测试失败)。全部仓储集成测试通过。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
3b89cc08dd
commit
eefa7dd9dc
@@ -906,7 +906,21 @@ func init() {
|
||||
// compositemodelroute.DefaultTargetPlatform holds the default value on creation for the target_platform field.
|
||||
compositemodelroute.DefaultTargetPlatform = compositemodelrouteDescTargetPlatform.Default.(string)
|
||||
// compositemodelroute.TargetPlatformValidator is a validator for the "target_platform" field. It is called by the builders before save.
|
||||
compositemodelroute.TargetPlatformValidator = compositemodelrouteDescTargetPlatform.Validators[0].(func(string) error)
|
||||
compositemodelroute.TargetPlatformValidator = func() func(string) error {
|
||||
validators := compositemodelrouteDescTargetPlatform.Validators
|
||||
fns := [...]func(string) error{
|
||||
validators[0].(func(string) error),
|
||||
validators[1].(func(string) error),
|
||||
}
|
||||
return func(target_platform string) error {
|
||||
for _, fn := range fns {
|
||||
if err := fn(target_platform); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
// compositemodelrouteDescUpstreamModel is the schema descriptor for upstream_model field.
|
||||
compositemodelrouteDescUpstreamModel := compositemodelrouteFields[4].Descriptor()
|
||||
// compositemodelroute.DefaultUpstreamModel holds the default value on creation for the upstream_model field.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
|
||||
"github.com/Wei-Shaw/sub2api/internal/domain"
|
||||
|
||||
@@ -45,6 +47,13 @@ func (CompositeModelRoute) Fields() []ent.Field {
|
||||
field.String("target_platform").
|
||||
MaxLen(50).
|
||||
Default(domain.PlatformOpenAI).
|
||||
Validate(func(s string) error {
|
||||
// 目标平台须为平台清单中的具体平台;数据库不再维护 CHECK 约束。
|
||||
if !domain.IsConcretePlatform(s) {
|
||||
return fmt.Errorf("target_platform %q is not a concrete platform", s)
|
||||
}
|
||||
return nil
|
||||
}).
|
||||
Comment("Concrete provider platform."),
|
||||
field.String("upstream_model").
|
||||
MaxLen(200).
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"entgo.io/ent/schema/field"
|
||||
"entgo.io/ent/schema/index"
|
||||
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
|
||||
"github.com/Wei-Shaw/sub2api/internal/domain"
|
||||
)
|
||||
|
||||
// UserPlatformQuota holds the schema definition for per-user per-platform quota.
|
||||
@@ -38,15 +39,12 @@ func (UserPlatformQuota) Fields() []ent.Field {
|
||||
MaxLen(32).
|
||||
NotEmpty().
|
||||
Validate(func(s string) error {
|
||||
// 注意:平台列表的单一权威源为 service.AllowedQuotaPlatforms;
|
||||
// 此处为 ent 构建期约束,需与 service.AllowedQuotaPlatforms 保持同步。
|
||||
switch s {
|
||||
case "anthropic", "openai", "gemini", "antigravity", "grok",
|
||||
"kimi", "zhipu", "deepseek", "minimax", "opencode_go", "typesafe":
|
||||
return nil
|
||||
default:
|
||||
// 平台白名单为平台清单(domain/platforms.go)中的全部具体平台,
|
||||
// 与 service.AllowedQuotaPlatforms 同源;数据库不再维护 CHECK 约束。
|
||||
if !domain.IsConcretePlatform(s) {
|
||||
return fmt.Errorf("platform %q is not allowed", s)
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
|
||||
// 日 / 周 / 月 USD 上限:
|
||||
|
||||
Reference in New Issue
Block a user