refactor(auth): simplify auth directory scanning and improve JSON processing logic

- Replaced `filepath.Walk` with `os.ReadDir` for cleaner directory traversal.
- Fixed `isAuthJSON` check to use `filepath.Dir` for directory comparison.
- Updated auth hash cache generation and file synthesis to improve readability and maintainability.
This commit is contained in:
Luis Pater
2026-04-12 13:32:03 +08:00
parent a583463d60
commit 6c0a1efd71
3 changed files with 40 additions and 32 deletions

View File

@@ -8,7 +8,6 @@ import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/fs"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@@ -85,14 +84,22 @@ func (w *Watcher) reloadClients(rescanAuth bool, affectedOAuthProviders []string
if resolvedAuthDir, errResolveAuthDir := util.ResolveAuthDir(cfg.AuthDir); errResolveAuthDir != nil { if resolvedAuthDir, errResolveAuthDir := util.ResolveAuthDir(cfg.AuthDir); errResolveAuthDir != nil {
log.Errorf("failed to resolve auth directory for hash cache: %v", errResolveAuthDir) log.Errorf("failed to resolve auth directory for hash cache: %v", errResolveAuthDir)
} else if resolvedAuthDir != "" { } else if resolvedAuthDir != "" {
_ = filepath.Walk(resolvedAuthDir, func(path string, info fs.FileInfo, err error) error { entries, errReadDir := os.ReadDir(resolvedAuthDir)
if err != nil { if errReadDir != nil {
return nil log.Errorf("failed to read auth directory for hash cache: %v", errReadDir)
} } else {
if !info.IsDir() && strings.HasSuffix(strings.ToLower(info.Name()), ".json") { for _, entry := range entries {
if data, errReadFile := os.ReadFile(path); errReadFile == nil && len(data) > 0 { 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) sum := sha256.Sum256(data)
normalizedPath := w.normalizeAuthPath(path) normalizedPath := w.normalizeAuthPath(fullPath)
w.lastAuthHashes[normalizedPath] = hex.EncodeToString(sum[:]) w.lastAuthHashes[normalizedPath] = hex.EncodeToString(sum[:])
// Parse and cache auth content for future diff comparisons (debug only). // Parse and cache auth content for future diff comparisons (debug only).
if cacheAuthContents { if cacheAuthContents {
@@ -107,15 +114,14 @@ func (w *Watcher) reloadClients(rescanAuth bool, affectedOAuthProviders []string
Now: time.Now(), Now: time.Now(),
IDGenerator: synthesizer.NewStableIDGenerator(), 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 { if pathAuths := authSliceToMap(generated); len(pathAuths) > 0 {
w.fileAuthsByPath[normalizedPath] = authIDSet(pathAuths) w.fileAuthsByPath[normalizedPath] = authIDSet(pathAuths)
} }
} }
} }
} }
return nil }
})
} }
w.clientsMutex.Unlock() w.clientsMutex.Unlock()
} }
@@ -306,23 +312,25 @@ func (w *Watcher) loadFileClients(cfg *config.Config) int {
return 0 return 0
} }
errWalk := filepath.Walk(authDir, func(path string, info fs.FileInfo, err error) error { entries, errReadDir := os.ReadDir(authDir)
if err != nil { if errReadDir != nil {
log.Debugf("error accessing path %s: %v", path, err) log.Errorf("error reading auth directory: %v", errReadDir)
return err return 0
}
for _, entry := range entries {
if entry == nil || entry.IsDir() {
continue
} }
if !info.IsDir() && strings.HasSuffix(strings.ToLower(info.Name()), ".json") { name := entry.Name()
authFileCount++ if !strings.HasSuffix(strings.ToLower(name), ".json") {
log.Debugf("processing auth file %d: %s", authFileCount, filepath.Base(path)) continue
if data, errCreate := os.ReadFile(path); errCreate == nil && len(data) > 0 { }
successfulAuthCount++ 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) log.Debugf("auth directory scan complete - found %d .json files, %d readable", authFileCount, successfulAuthCount)
return authFileCount return authFileCount

View File

@@ -72,7 +72,7 @@ func (w *Watcher) handleEvent(event fsnotify.Event) {
normalizedAuthDir := w.normalizeAuthPath(w.authDir) normalizedAuthDir := w.normalizeAuthPath(w.authDir)
isConfigEvent := normalizedName == normalizedConfigPath && event.Op&configOps != 0 isConfigEvent := normalizedName == normalizedConfigPath && event.Op&configOps != 0
authOps := fsnotify.Create | fsnotify.Write | fsnotify.Remove | fsnotify.Rename 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 { if !isConfigEvent && !isAuthJSON {
// Ignore unrelated files (e.g., cookie snapshots *.cookie) and other noise. // Ignore unrelated files (e.g., cookie snapshots *.cookie) and other noise.
return return

View File

@@ -2903,19 +2903,19 @@ func (m *Manager) StartAutoRefresh(parent context.Context, interval time.Duratio
} }
m.mu.Lock() m.mu.Lock()
cancel := m.refreshCancel cancelPrev := m.refreshCancel
m.refreshCancel = nil m.refreshCancel = nil
m.refreshLoop = nil m.refreshLoop = nil
m.mu.Unlock() m.mu.Unlock()
if cancel != nil { if cancelPrev != nil {
cancel() cancelPrev()
} }
ctx, cancel := context.WithCancel(parent) ctx, cancelCtx := context.WithCancel(parent)
loop := newAuthAutoRefreshLoop(m, interval) loop := newAuthAutoRefreshLoop(m, interval)
m.mu.Lock() m.mu.Lock()
m.refreshCancel = cancel m.refreshCancel = cancelCtx
m.refreshLoop = loop m.refreshLoop = loop
m.mu.Unlock() m.mu.Unlock()