package auth import ( "context" "fmt" "github.com/router-for-me/CLIProxyAPI/v6/internal/config" ) // Manager aggregates authenticators and coordinates persistence via a token store. type Manager struct { authenticators map[string]Authenticator store TokenStore } // NewManager constructs a manager with the provided token store and authenticators. // If store is nil, the caller must set it later using SetStore. func NewManager(store TokenStore, authenticators ...Authenticator) *Manager { mgr := &Manager{ authenticators: make(map[string]Authenticator), store: store, } for i := range authenticators { mgr.Register(authenticators[i]) } return mgr } // Register adds or replaces an authenticator keyed by its provider identifier. func (m *Manager) Register(a Authenticator) { if a == nil { return } if m.authenticators == nil { m.authenticators = make(map[string]Authenticator) } m.authenticators[a.Provider()] = a } // SetStore updates the token store used for persistence. func (m *Manager) SetStore(store TokenStore) { m.store = store } // Login executes the provider login flow and persists the resulting token record. func (m *Manager) Login(ctx context.Context, provider string, cfg *config.Config, opts *LoginOptions) (*TokenRecord, string, error) { auth, ok := m.authenticators[provider] if !ok { return nil, "", fmt.Errorf("cliproxy auth: authenticator %s not registered", provider) } record, err := auth.Login(ctx, cfg, opts) if err != nil { return nil, "", err } if record == nil { return nil, "", fmt.Errorf("cliproxy auth: authenticator %s returned nil record", provider) } if m.store == nil { return record, "", nil } savedPath, err := m.store.Save(ctx, cfg, record) if err != nil { return record, "", err } return record, savedPath, nil } // Refresh delegates to the provider-specific refresh implementation and persists the result. func (m *Manager) Refresh(ctx context.Context, provider string, cfg *config.Config, record *TokenRecord) (*TokenRecord, string, error) { auth, ok := m.authenticators[provider] if !ok { return nil, "", fmt.Errorf("cliproxy auth: authenticator %s not registered", provider) } updated, err := auth.Refresh(ctx, cfg, record) if err != nil { return nil, "", err } if updated == nil { updated = record } if m.store == nil { return updated, "", nil } savedPath, err := m.store.Save(ctx, cfg, updated) if err != nil { return updated, "", err } return updated, savedPath, nil }