mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 13:00:52 +08:00
- Replaced legacy `api-keys` field with `auth.providers` in configuration, supporting multiple authentication providers including `config-api-key`. - Added synchronization to maintain compatibility with legacy `api-keys`. - Updated core components like request handling and middleware to use the new provider system. - Enhanced management API endpoints for seamless integration with `auth.providers`.
89 lines
2.2 KiB
Go
89 lines
2.2 KiB
Go
package access
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"sync"
|
|
|
|
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
|
)
|
|
|
|
// Provider validates credentials for incoming requests.
|
|
type Provider interface {
|
|
Identifier() string
|
|
Authenticate(ctx context.Context, r *http.Request) (*Result, error)
|
|
}
|
|
|
|
// Result conveys authentication outcome.
|
|
type Result struct {
|
|
Provider string
|
|
Principal string
|
|
Metadata map[string]string
|
|
}
|
|
|
|
// ProviderFactory builds a provider from configuration data.
|
|
type ProviderFactory func(cfg *config.AccessProvider, root *config.Config) (Provider, error)
|
|
|
|
var (
|
|
registryMu sync.RWMutex
|
|
registry = make(map[string]ProviderFactory)
|
|
)
|
|
|
|
// RegisterProvider registers a provider factory for a given type identifier.
|
|
func RegisterProvider(typ string, factory ProviderFactory) {
|
|
if typ == "" || factory == nil {
|
|
return
|
|
}
|
|
registryMu.Lock()
|
|
registry[typ] = factory
|
|
registryMu.Unlock()
|
|
}
|
|
|
|
func buildProvider(cfg *config.AccessProvider, root *config.Config) (Provider, error) {
|
|
if cfg == nil {
|
|
return nil, fmt.Errorf("access: nil provider config")
|
|
}
|
|
registryMu.RLock()
|
|
factory, ok := registry[cfg.Type]
|
|
registryMu.RUnlock()
|
|
if !ok {
|
|
return nil, fmt.Errorf("access: provider type %q is not registered", cfg.Type)
|
|
}
|
|
provider, err := factory(cfg, root)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("access: failed to build provider %q: %w", cfg.Name, err)
|
|
}
|
|
return provider, nil
|
|
}
|
|
|
|
// BuildProviders constructs providers declared in configuration.
|
|
func BuildProviders(root *config.Config) ([]Provider, error) {
|
|
if root == nil {
|
|
return nil, nil
|
|
}
|
|
providers := make([]Provider, 0, len(root.Access.Providers))
|
|
for i := range root.Access.Providers {
|
|
providerCfg := &root.Access.Providers[i]
|
|
if providerCfg.Type == "" {
|
|
continue
|
|
}
|
|
provider, err := buildProvider(providerCfg, root)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
providers = append(providers, provider)
|
|
}
|
|
if len(providers) == 0 && len(root.APIKeys) > 0 {
|
|
config.SyncInlineAPIKeys(root, root.APIKeys)
|
|
if providerCfg := root.ConfigAPIKeyProvider(); providerCfg != nil {
|
|
provider, err := buildProvider(providerCfg, root)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
providers = append(providers, provider)
|
|
}
|
|
}
|
|
return providers, nil
|
|
}
|