| package access |
|
|
| import ( |
| "context" |
| "errors" |
| "net/http" |
| "sync" |
| ) |
|
|
| |
| type Manager struct { |
| mu sync.RWMutex |
| providers []Provider |
| } |
|
|
| |
| func NewManager() *Manager { |
| return &Manager{} |
| } |
|
|
| |
| func (m *Manager) SetProviders(providers []Provider) { |
| if m == nil { |
| return |
| } |
| cloned := make([]Provider, len(providers)) |
| copy(cloned, providers) |
| m.mu.Lock() |
| m.providers = cloned |
| m.mu.Unlock() |
| } |
|
|
| |
| func (m *Manager) Providers() []Provider { |
| if m == nil { |
| return nil |
| } |
| m.mu.RLock() |
| defer m.mu.RUnlock() |
| snapshot := make([]Provider, len(m.providers)) |
| copy(snapshot, m.providers) |
| return snapshot |
| } |
|
|
| |
| func (m *Manager) Authenticate(ctx context.Context, r *http.Request) (*Result, error) { |
| if m == nil { |
| return nil, nil |
| } |
| providers := m.Providers() |
| if len(providers) == 0 { |
| return nil, nil |
| } |
|
|
| var ( |
| missing bool |
| invalid bool |
| ) |
|
|
| for _, provider := range providers { |
| if provider == nil { |
| continue |
| } |
| res, err := provider.Authenticate(ctx, r) |
| if err == nil { |
| return res, nil |
| } |
| if errors.Is(err, ErrNotHandled) { |
| continue |
| } |
| if errors.Is(err, ErrNoCredentials) { |
| missing = true |
| continue |
| } |
| if errors.Is(err, ErrInvalidCredential) { |
| invalid = true |
| continue |
| } |
| return nil, err |
| } |
|
|
| if invalid { |
| return nil, ErrInvalidCredential |
| } |
| if missing { |
| return nil, ErrNoCredentials |
| } |
| return nil, ErrNoCredentials |
| } |
|
|