refactor(api): split Provider into ProviderGroup and APIKey models

Restructure the provider management system by separating the monolithic
Provider model into two distinct entities:

- ProviderGroup: defines shared upstream configuration (type, base_url,
  google settings, models, status)
- APIKey: represents individual credentials within a group (api_key,
  weight, status, auto_ban, ban settings)

This change also updates:
- Binding model to reference GroupID instead of RouteGroup string
- All CRUD handlers for the new provider-group and api-key endpoints
- Sync service to rebuild provider snapshots from joined tables
- Model registry to aggregate capabilities across group/key pairs
- Access handler to validate namespace existence and subset constraints
- Migration importer to handle the new schema structure
- All related tests to use the new model relationships

BREAKING CHANGE: Provider API endpoints replaced with /provider-groups
and /api-keys endpoints; Binding.RouteGroup replaced with Binding.GroupID
This commit is contained in:
zenfun
2025-12-24 02:15:52 +08:00
parent cd5616dc26
commit dea8363e41
27 changed files with 1222 additions and 1625 deletions

View File

@@ -135,7 +135,7 @@ func main() {
// Auto Migrate
if logDB != db {
if err := db.AutoMigrate(&model.Master{}, &model.Key{}, &model.Provider{}, &model.Model{}, &model.Binding{}, &model.Namespace{}, &model.OperationLog{}); err != nil {
if err := db.AutoMigrate(&model.Master{}, &model.Key{}, &model.ProviderGroup{}, &model.APIKey{}, &model.Model{}, &model.Binding{}, &model.Namespace{}, &model.OperationLog{}); err != nil {
fatal(logger, "failed to auto migrate", "err", err)
}
if err := logDB.AutoMigrate(&model.LogRecord{}); err != nil {
@@ -145,7 +145,7 @@ func main() {
fatal(logger, "failed to ensure log indexes", "err", err)
}
} else {
if err := db.AutoMigrate(&model.Master{}, &model.Key{}, &model.Provider{}, &model.Model{}, &model.Binding{}, &model.Namespace{}, &model.OperationLog{}, &model.LogRecord{}); err != nil {
if err := db.AutoMigrate(&model.Master{}, &model.Key{}, &model.ProviderGroup{}, &model.APIKey{}, &model.Model{}, &model.Binding{}, &model.Namespace{}, &model.OperationLog{}, &model.LogRecord{}); err != nil {
fatal(logger, "failed to auto migrate", "err", err)
}
if err := service.EnsureLogIndexes(db); err != nil {
@@ -287,17 +287,17 @@ func main() {
adminGroup.POST("/model-registry/refresh", modelRegistryHandler.Refresh)
adminGroup.POST("/model-registry/rollback", modelRegistryHandler.Rollback)
// Other admin routes for managing providers, models, etc.
adminGroup.POST("/providers", handler.CreateProvider)
adminGroup.GET("/providers", handler.ListProviders)
adminGroup.GET("/providers/:id", handler.GetProvider)
adminGroup.POST("/providers/preset", handler.CreateProviderPreset)
adminGroup.POST("/providers/custom", handler.CreateProviderCustom)
adminGroup.POST("/providers/google", handler.CreateProviderGoogle)
adminGroup.PUT("/providers/:id", handler.UpdateProvider)
adminGroup.DELETE("/providers/:id", handler.DeleteProvider)
adminGroup.POST("/providers/batch", handler.BatchProviders)
adminGroup.POST("/providers/:id/test", handler.TestProvider)
adminGroup.POST("/providers/:id/fetch-models", handler.FetchProviderModels)
adminGroup.POST("/provider-groups", handler.CreateProviderGroup)
adminGroup.GET("/provider-groups", handler.ListProviderGroups)
adminGroup.GET("/provider-groups/:id", handler.GetProviderGroup)
adminGroup.PUT("/provider-groups/:id", handler.UpdateProviderGroup)
adminGroup.DELETE("/provider-groups/:id", handler.DeleteProviderGroup)
adminGroup.POST("/api-keys", handler.CreateAPIKey)
adminGroup.GET("/api-keys", handler.ListAPIKeys)
adminGroup.GET("/api-keys/:id", handler.GetAPIKey)
adminGroup.PUT("/api-keys/:id", handler.UpdateAPIKey)
adminGroup.DELETE("/api-keys/:id", handler.DeleteAPIKey)
adminGroup.POST("/api-keys/batch", handler.BatchAPIKeys)
adminGroup.POST("/models", handler.CreateModel)
adminGroup.GET("/models", handler.ListModels)
adminGroup.PUT("/models/:id", handler.UpdateModel)
@@ -406,7 +406,7 @@ func runImport(logger *slog.Logger, args []string) int {
return 1
}
if err := db.AutoMigrate(&model.Master{}, &model.Key{}, &model.Provider{}, &model.Model{}, &model.Binding{}, &model.Namespace{}); err != nil {
if err := db.AutoMigrate(&model.Master{}, &model.Key{}, &model.ProviderGroup{}, &model.APIKey{}, &model.Model{}, &model.Binding{}, &model.Namespace{}); err != nil {
logger.Error("failed to auto migrate", "err", err)
return 1
}