mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 13:00:52 +08:00
refactor(access): migrate to SDKConfig for authentication and provider management
- Replaced `config.Config` with `SDKConfig` in authentication and provider logic for consistency with SDK changes. - Updated provider registration, reconciliation, and build functions to align with the `SDKConfig` structure. - Refactored related imports and handlers to support the new configuration approach. - Improved clarity and reduced redundancy in API key synchronization and provider initialization.
This commit is contained in:
@@ -5,8 +5,8 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
||||
sdkaccess "github.com/router-for-me/CLIProxyAPI/v6/sdk/access"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/sdk/config"
|
||||
)
|
||||
|
||||
type provider struct {
|
||||
@@ -18,7 +18,7 @@ func init() {
|
||||
sdkaccess.RegisterProvider(config.AccessProviderTypeConfigAPIKey, newProvider)
|
||||
}
|
||||
|
||||
func newProvider(cfg *config.AccessProvider, _ *config.Config) (sdkaccess.Provider, error) {
|
||||
func newProvider(cfg *config.AccessProvider, _ *config.SDKConfig) (sdkaccess.Provider, error) {
|
||||
name := cfg.Name
|
||||
if name == "" {
|
||||
name = config.DefaultAccessProviderName
|
||||
|
||||
@@ -1,252 +0,0 @@
|
||||
package access
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
||||
)
|
||||
|
||||
// ReconcileProviders builds the desired provider list by reusing existing providers when possible
|
||||
// and creating or removing providers only when their configuration changed. It returns the final
|
||||
// ordered provider slice along with the identifiers of providers that were added, updated, or
|
||||
// removed compared to the previous configuration.
|
||||
func ReconcileProviders(oldCfg, newCfg *config.Config, existing []Provider) (result []Provider, added, updated, removed []string, err error) {
|
||||
if newCfg == nil {
|
||||
return nil, nil, nil, nil, nil
|
||||
}
|
||||
|
||||
existingMap := make(map[string]Provider, len(existing))
|
||||
for _, provider := range existing {
|
||||
if provider == nil {
|
||||
continue
|
||||
}
|
||||
existingMap[provider.Identifier()] = provider
|
||||
}
|
||||
|
||||
oldCfgMap := accessProviderMap(oldCfg)
|
||||
newEntries := collectProviderEntries(newCfg)
|
||||
|
||||
result = make([]Provider, 0, len(newEntries))
|
||||
finalIDs := make(map[string]struct{}, len(newEntries))
|
||||
|
||||
isInlineProvider := func(id string) bool {
|
||||
return strings.EqualFold(id, config.DefaultAccessProviderName)
|
||||
}
|
||||
appendChange := func(list *[]string, id string) {
|
||||
if isInlineProvider(id) {
|
||||
return
|
||||
}
|
||||
*list = append(*list, id)
|
||||
}
|
||||
|
||||
for _, providerCfg := range newEntries {
|
||||
key := providerIdentifier(providerCfg)
|
||||
if key == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if oldCfgProvider, ok := oldCfgMap[key]; ok {
|
||||
isAliased := oldCfgProvider == providerCfg
|
||||
if !isAliased && providerConfigEqual(oldCfgProvider, providerCfg) {
|
||||
if existingProvider, okExisting := existingMap[key]; okExisting {
|
||||
result = append(result, existingProvider)
|
||||
finalIDs[key] = struct{}{}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider, buildErr := buildProvider(providerCfg, newCfg)
|
||||
if buildErr != nil {
|
||||
return nil, nil, nil, nil, buildErr
|
||||
}
|
||||
if _, ok := oldCfgMap[key]; ok {
|
||||
if _, existed := existingMap[key]; existed {
|
||||
appendChange(&updated, key)
|
||||
} else {
|
||||
appendChange(&added, key)
|
||||
}
|
||||
} else {
|
||||
appendChange(&added, key)
|
||||
}
|
||||
result = append(result, provider)
|
||||
finalIDs[key] = struct{}{}
|
||||
}
|
||||
|
||||
if len(result) == 0 && len(newCfg.APIKeys) > 0 {
|
||||
config.SyncInlineAPIKeys(newCfg, newCfg.APIKeys)
|
||||
if providerCfg := newCfg.ConfigAPIKeyProvider(); providerCfg != nil {
|
||||
key := providerIdentifier(providerCfg)
|
||||
if key != "" {
|
||||
if oldCfgProvider, ok := oldCfgMap[key]; ok {
|
||||
isAliased := oldCfgProvider == providerCfg
|
||||
if !isAliased && providerConfigEqual(oldCfgProvider, providerCfg) {
|
||||
if existingProvider, okExisting := existingMap[key]; okExisting {
|
||||
result = append(result, existingProvider)
|
||||
} else {
|
||||
provider, buildErr := buildProvider(providerCfg, newCfg)
|
||||
if buildErr != nil {
|
||||
return nil, nil, nil, nil, buildErr
|
||||
}
|
||||
if _, existed := existingMap[key]; existed {
|
||||
appendChange(&updated, key)
|
||||
} else {
|
||||
appendChange(&added, key)
|
||||
}
|
||||
result = append(result, provider)
|
||||
}
|
||||
} else {
|
||||
provider, buildErr := buildProvider(providerCfg, newCfg)
|
||||
if buildErr != nil {
|
||||
return nil, nil, nil, nil, buildErr
|
||||
}
|
||||
if _, existed := existingMap[key]; existed {
|
||||
appendChange(&updated, key)
|
||||
} else {
|
||||
appendChange(&added, key)
|
||||
}
|
||||
result = append(result, provider)
|
||||
}
|
||||
} else {
|
||||
provider, buildErr := buildProvider(providerCfg, newCfg)
|
||||
if buildErr != nil {
|
||||
return nil, nil, nil, nil, buildErr
|
||||
}
|
||||
appendChange(&added, key)
|
||||
result = append(result, provider)
|
||||
}
|
||||
finalIDs[key] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removedSet := make(map[string]struct{})
|
||||
for id := range existingMap {
|
||||
if _, ok := finalIDs[id]; !ok {
|
||||
if isInlineProvider(id) {
|
||||
continue
|
||||
}
|
||||
removedSet[id] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
removed = make([]string, 0, len(removedSet))
|
||||
for id := range removedSet {
|
||||
removed = append(removed, id)
|
||||
}
|
||||
|
||||
sort.Strings(added)
|
||||
sort.Strings(updated)
|
||||
sort.Strings(removed)
|
||||
|
||||
return result, added, updated, removed, nil
|
||||
}
|
||||
|
||||
func accessProviderMap(cfg *config.Config) map[string]*config.AccessProvider {
|
||||
result := make(map[string]*config.AccessProvider)
|
||||
if cfg == nil {
|
||||
return result
|
||||
}
|
||||
for i := range cfg.Access.Providers {
|
||||
providerCfg := &cfg.Access.Providers[i]
|
||||
if providerCfg.Type == "" {
|
||||
continue
|
||||
}
|
||||
key := providerIdentifier(providerCfg)
|
||||
if key == "" {
|
||||
continue
|
||||
}
|
||||
result[key] = providerCfg
|
||||
}
|
||||
if len(result) == 0 && len(cfg.APIKeys) > 0 {
|
||||
if provider := cfg.ConfigAPIKeyProvider(); provider != nil {
|
||||
if key := providerIdentifier(provider); key != "" {
|
||||
result[key] = provider
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func collectProviderEntries(cfg *config.Config) []*config.AccessProvider {
|
||||
entries := make([]*config.AccessProvider, 0, len(cfg.Access.Providers))
|
||||
if cfg == nil {
|
||||
return entries
|
||||
}
|
||||
for i := range cfg.Access.Providers {
|
||||
providerCfg := &cfg.Access.Providers[i]
|
||||
if providerCfg.Type == "" {
|
||||
continue
|
||||
}
|
||||
if key := providerIdentifier(providerCfg); key != "" {
|
||||
entries = append(entries, providerCfg)
|
||||
}
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
func providerIdentifier(provider *config.AccessProvider) string {
|
||||
if provider == nil {
|
||||
return ""
|
||||
}
|
||||
if name := strings.TrimSpace(provider.Name); name != "" {
|
||||
return name
|
||||
}
|
||||
typ := strings.TrimSpace(provider.Type)
|
||||
if typ == "" {
|
||||
return ""
|
||||
}
|
||||
if strings.EqualFold(typ, config.AccessProviderTypeConfigAPIKey) {
|
||||
return config.DefaultAccessProviderName
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
func providerConfigEqual(a, b *config.AccessProvider) bool {
|
||||
if a == nil || b == nil {
|
||||
return a == nil && b == nil
|
||||
}
|
||||
if !strings.EqualFold(strings.TrimSpace(a.Type), strings.TrimSpace(b.Type)) {
|
||||
return false
|
||||
}
|
||||
if strings.TrimSpace(a.SDK) != strings.TrimSpace(b.SDK) {
|
||||
return false
|
||||
}
|
||||
if !stringSetEqual(a.APIKeys, b.APIKeys) {
|
||||
return false
|
||||
}
|
||||
if len(a.Config) != len(b.Config) {
|
||||
return false
|
||||
}
|
||||
if len(a.Config) > 0 && !reflect.DeepEqual(a.Config, b.Config) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func stringSetEqual(a, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
if len(a) == 0 {
|
||||
return true
|
||||
}
|
||||
seen := make(map[string]int, len(a))
|
||||
for _, val := range a {
|
||||
seen[val]++
|
||||
}
|
||||
for _, val := range b {
|
||||
count := seen[val]
|
||||
if count == 0 {
|
||||
return false
|
||||
}
|
||||
if count == 1 {
|
||||
delete(seen, val)
|
||||
} else {
|
||||
seen[val] = count - 1
|
||||
}
|
||||
}
|
||||
return len(seen) == 0
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/sdk/config"
|
||||
)
|
||||
|
||||
// Provider validates credentials for incoming requests.
|
||||
@@ -23,7 +23,7 @@ type Result struct {
|
||||
}
|
||||
|
||||
// ProviderFactory builds a provider from configuration data.
|
||||
type ProviderFactory func(cfg *config.AccessProvider, root *config.Config) (Provider, error)
|
||||
type ProviderFactory func(cfg *config.AccessProvider, root *config.SDKConfig) (Provider, error)
|
||||
|
||||
var (
|
||||
registryMu sync.RWMutex
|
||||
@@ -40,7 +40,7 @@ func RegisterProvider(typ string, factory ProviderFactory) {
|
||||
registryMu.Unlock()
|
||||
}
|
||||
|
||||
func buildProvider(cfg *config.AccessProvider, root *config.Config) (Provider, error) {
|
||||
func BuildProvider(cfg *config.AccessProvider, root *config.SDKConfig) (Provider, error) {
|
||||
if cfg == nil {
|
||||
return nil, fmt.Errorf("access: nil provider config")
|
||||
}
|
||||
@@ -58,7 +58,7 @@ func buildProvider(cfg *config.AccessProvider, root *config.Config) (Provider, e
|
||||
}
|
||||
|
||||
// BuildProviders constructs providers declared in configuration.
|
||||
func BuildProviders(root *config.Config) ([]Provider, error) {
|
||||
func BuildProviders(root *config.SDKConfig) ([]Provider, error) {
|
||||
if root == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -68,7 +68,7 @@ func BuildProviders(root *config.Config) ([]Provider, error) {
|
||||
if providerCfg.Type == "" {
|
||||
continue
|
||||
}
|
||||
provider, err := buildProvider(providerCfg, root)
|
||||
provider, err := BuildProvider(providerCfg, root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -77,7 +77,7 @@ func BuildProviders(root *config.Config) ([]Provider, error) {
|
||||
if len(providers) == 0 && len(root.APIKeys) > 0 {
|
||||
config.SyncInlineAPIKeys(root, root.APIKeys)
|
||||
if providerCfg := root.ConfigAPIKeyProvider(); providerCfg != nil {
|
||||
provider, err := buildProvider(providerCfg, root)
|
||||
provider, err := BuildProvider(providerCfg, root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user