mirror of
https://github.com/EZ-Api/ez-api.git
synced 2026-01-13 17:47:51 +00:00
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:
@@ -1,12 +1,14 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ez-api/ez-api/internal/model"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type AccessResponse struct {
|
||||
@@ -94,6 +96,10 @@ func (h *Handler) UpdateMasterAccess(c *gin.Context) {
|
||||
}
|
||||
nsList := normalizeNamespaces(nextNamespaces, nextDefault)
|
||||
nextNamespaces = strings.Join(nsList, ",")
|
||||
if err := ensureNamespacesExist(h.db, nsList); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.db.Model(&m).Updates(map[string]any{
|
||||
"default_namespace": nextDefault,
|
||||
@@ -203,6 +209,21 @@ func (h *Handler) UpdateKeyAccess(c *gin.Context) {
|
||||
}
|
||||
nsList := normalizeNamespaces(nextNamespaces, nextDefault)
|
||||
nextNamespaces = strings.Join(nsList, ",")
|
||||
if err := ensureNamespacesExist(h.db, nsList); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var master model.Master
|
||||
if err := h.db.First(&master, k.MasterID).Error; err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "master not found"})
|
||||
return
|
||||
}
|
||||
masterNamespaces := normalizeNamespaces(master.Namespaces, master.DefaultNamespace)
|
||||
if !isSubset(nsList, masterNamespaces) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "namespaces must be a subset of master namespaces"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.db.Model(&k).Updates(map[string]any{
|
||||
"default_namespace": nextDefault,
|
||||
@@ -264,6 +285,39 @@ func normalizeNamespaces(raw string, defaultNamespace string) []string {
|
||||
return out
|
||||
}
|
||||
|
||||
func ensureNamespacesExist(db *gorm.DB, namespaces []string) error {
|
||||
if db == nil {
|
||||
return fmt.Errorf("db required")
|
||||
}
|
||||
if len(namespaces) == 0 {
|
||||
return fmt.Errorf("namespaces required")
|
||||
}
|
||||
var rows []model.Namespace
|
||||
if err := db.Where("name IN ?", namespaces).Find(&rows).Error; err != nil {
|
||||
return fmt.Errorf("failed to load namespaces")
|
||||
}
|
||||
if len(rows) != len(namespaces) {
|
||||
return fmt.Errorf("namespace not found")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isSubset(child, parent []string) bool {
|
||||
if len(child) == 0 {
|
||||
return true
|
||||
}
|
||||
parentSet := make(map[string]struct{}, len(parent))
|
||||
for _, p := range parent {
|
||||
parentSet[strings.TrimSpace(p)] = struct{}{}
|
||||
}
|
||||
for _, c := range child {
|
||||
if _, ok := parentSet[strings.TrimSpace(c)]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func parseUintParam(c *gin.Context, name string) (uint, bool) {
|
||||
idRaw := strings.TrimSpace(c.Param(name))
|
||||
if idRaw == "" {
|
||||
|
||||
Reference in New Issue
Block a user