- Introduced new endpoints for contact discovery, including scanning, listing, and managing discovered contacts. - Implemented retry logic for handling missing DAV credentials during contact operations. - Added public share functionality for drive API, allowing users to manage public shares, including upload, delete, and rename operations. - Updated Nextcloud configuration to support public share links and improved error handling for public share permissions. - Enhanced logging and validation across contact and drive APIs for better error tracking and user feedback. - Added tests for new contact matching and ranking functionalities to ensure accuracy and reliability.
85 lines
1.7 KiB
Go
85 lines
1.7 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"log/slog"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
var ErrVerifierUnavailable = errors.New("verifier unavailable")
|
|
|
|
// Holder keeps an OIDC verifier available, retrying in the background when Authentik
|
|
// is not ready at ultid startup (common in local Docker compose).
|
|
type Holder struct {
|
|
v atomic.Pointer[Verifier]
|
|
|
|
issuerURL string
|
|
clientID string
|
|
discoveryHost string
|
|
}
|
|
|
|
func NewHolder(initial *Verifier) *Holder {
|
|
h := &Holder{}
|
|
if initial != nil {
|
|
h.v.Store(initial)
|
|
}
|
|
return h
|
|
}
|
|
|
|
func NewHolderPending(issuerURL, clientID, discoveryHost string) *Holder {
|
|
return &Holder{
|
|
issuerURL: issuerURL,
|
|
clientID: clientID,
|
|
discoveryHost: discoveryHost,
|
|
}
|
|
}
|
|
|
|
func (h *Holder) Ready() bool {
|
|
return h != nil && h.v.Load() != nil
|
|
}
|
|
|
|
func (h *Holder) Get() *Verifier {
|
|
if h == nil {
|
|
return nil
|
|
}
|
|
return h.v.Load()
|
|
}
|
|
|
|
func (h *Holder) Verify(ctx context.Context, rawToken string) (*Claims, error) {
|
|
v := h.Get()
|
|
if v == nil {
|
|
return nil, ErrVerifierUnavailable
|
|
}
|
|
return v.Verify(ctx, rawToken)
|
|
}
|
|
|
|
// StartBackgroundRetry keeps trying until the verifier is ready or ctx is cancelled.
|
|
func (h *Holder) StartBackgroundRetry(ctx context.Context, interval time.Duration) {
|
|
if h == nil || h.Ready() || h.issuerURL == "" || h.clientID == "" {
|
|
return
|
|
}
|
|
if interval <= 0 {
|
|
interval = 5 * time.Second
|
|
}
|
|
go func() {
|
|
ticker := time.NewTicker(interval)
|
|
defer ticker.Stop()
|
|
for {
|
|
v, err := NewVerifier(ctx, h.issuerURL, h.clientID, h.discoveryHost)
|
|
if err == nil {
|
|
h.v.Store(v)
|
|
slog.Info("OIDC verifier ready (background retry)")
|
|
return
|
|
}
|
|
slog.Warn("OIDC verifier background retry", "error", err)
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case <-ticker.C:
|
|
}
|
|
}
|
|
}()
|
|
}
|