diff --git a/internal/watcher/clients.go b/internal/watcher/clients.go index 60ff61972..7746f4ad3 100644 --- a/internal/watcher/clients.go +++ b/internal/watcher/clients.go @@ -8,7 +8,6 @@ import ( "encoding/hex" "encoding/json" "fmt" - "io/fs" "os" "path/filepath" "strings" @@ -85,14 +84,22 @@ func (w *Watcher) reloadClients(rescanAuth bool, affectedOAuthProviders []string if resolvedAuthDir, errResolveAuthDir := util.ResolveAuthDir(cfg.AuthDir); errResolveAuthDir != nil { log.Errorf("failed to resolve auth directory for hash cache: %v", errResolveAuthDir) } else if resolvedAuthDir != "" { - _ = filepath.Walk(resolvedAuthDir, func(path string, info fs.FileInfo, err error) error { - if err != nil { - return nil - } - if !info.IsDir() && strings.HasSuffix(strings.ToLower(info.Name()), ".json") { - if data, errReadFile := os.ReadFile(path); errReadFile == nil && len(data) > 0 { + entries, errReadDir := os.ReadDir(resolvedAuthDir) + if errReadDir != nil { + log.Errorf("failed to read auth directory for hash cache: %v", errReadDir) + } else { + for _, entry := range entries { + if entry == nil || entry.IsDir() { + continue + } + name := entry.Name() + if !strings.HasSuffix(strings.ToLower(name), ".json") { + continue + } + fullPath := filepath.Join(resolvedAuthDir, name) + if data, errReadFile := os.ReadFile(fullPath); errReadFile == nil && len(data) > 0 { sum := sha256.Sum256(data) - normalizedPath := w.normalizeAuthPath(path) + normalizedPath := w.normalizeAuthPath(fullPath) w.lastAuthHashes[normalizedPath] = hex.EncodeToString(sum[:]) // Parse and cache auth content for future diff comparisons (debug only). if cacheAuthContents { @@ -107,15 +114,14 @@ func (w *Watcher) reloadClients(rescanAuth bool, affectedOAuthProviders []string Now: time.Now(), IDGenerator: synthesizer.NewStableIDGenerator(), } - if generated := synthesizer.SynthesizeAuthFile(ctx, path, data); len(generated) > 0 { + if generated := synthesizer.SynthesizeAuthFile(ctx, fullPath, data); len(generated) > 0 { if pathAuths := authSliceToMap(generated); len(pathAuths) > 0 { w.fileAuthsByPath[normalizedPath] = authIDSet(pathAuths) } } } } - return nil - }) + } } w.clientsMutex.Unlock() } @@ -306,23 +312,25 @@ func (w *Watcher) loadFileClients(cfg *config.Config) int { return 0 } - errWalk := filepath.Walk(authDir, func(path string, info fs.FileInfo, err error) error { - if err != nil { - log.Debugf("error accessing path %s: %v", path, err) - return err + entries, errReadDir := os.ReadDir(authDir) + if errReadDir != nil { + log.Errorf("error reading auth directory: %v", errReadDir) + return 0 + } + for _, entry := range entries { + if entry == nil || entry.IsDir() { + continue } - if !info.IsDir() && strings.HasSuffix(strings.ToLower(info.Name()), ".json") { - authFileCount++ - log.Debugf("processing auth file %d: %s", authFileCount, filepath.Base(path)) - if data, errCreate := os.ReadFile(path); errCreate == nil && len(data) > 0 { - successfulAuthCount++ - } + name := entry.Name() + if !strings.HasSuffix(strings.ToLower(name), ".json") { + continue + } + authFileCount++ + log.Debugf("processing auth file %d: %s", authFileCount, name) + fullPath := filepath.Join(authDir, name) + if data, errReadFile := os.ReadFile(fullPath); errReadFile == nil && len(data) > 0 { + successfulAuthCount++ } - return nil - }) - - if errWalk != nil { - log.Errorf("error walking auth directory: %v", errWalk) } log.Debugf("auth directory scan complete - found %d .json files, %d readable", authFileCount, successfulAuthCount) return authFileCount diff --git a/internal/watcher/events.go b/internal/watcher/events.go index 250cf75cb..d3a4ee8f7 100644 --- a/internal/watcher/events.go +++ b/internal/watcher/events.go @@ -72,7 +72,7 @@ func (w *Watcher) handleEvent(event fsnotify.Event) { normalizedAuthDir := w.normalizeAuthPath(w.authDir) isConfigEvent := normalizedName == normalizedConfigPath && event.Op&configOps != 0 authOps := fsnotify.Create | fsnotify.Write | fsnotify.Remove | fsnotify.Rename - isAuthJSON := strings.HasPrefix(normalizedName, normalizedAuthDir) && strings.HasSuffix(normalizedName, ".json") && event.Op&authOps != 0 + isAuthJSON := filepath.Dir(normalizedName) == normalizedAuthDir && strings.HasSuffix(normalizedName, ".json") && event.Op&authOps != 0 if !isConfigEvent && !isAuthJSON { // Ignore unrelated files (e.g., cookie snapshots *.cookie) and other noise. return diff --git a/sdk/cliproxy/auth/conductor.go b/sdk/cliproxy/auth/conductor.go index fc25ca2b3..3cf025241 100644 --- a/sdk/cliproxy/auth/conductor.go +++ b/sdk/cliproxy/auth/conductor.go @@ -2903,19 +2903,19 @@ func (m *Manager) StartAutoRefresh(parent context.Context, interval time.Duratio } m.mu.Lock() - cancel := m.refreshCancel + cancelPrev := m.refreshCancel m.refreshCancel = nil m.refreshLoop = nil m.mu.Unlock() - if cancel != nil { - cancel() + if cancelPrev != nil { + cancelPrev() } - ctx, cancel := context.WithCancel(parent) + ctx, cancelCtx := context.WithCancel(parent) loop := newAuthAutoRefreshLoop(m, interval) m.mu.Lock() - m.refreshCancel = cancel + m.refreshCancel = cancelCtx m.refreshLoop = loop m.mu.Unlock()