mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 04:50:52 +08:00
refactor(util): Centralize auth directory path resolution
Introduces a new utility function, `util.ResolveAuthDir`, to handle the normalization and resolution of the authentication directory path. Previously, the logic for expanding the tilde (~) to the user's home directory was implemented inline in `main.go`. This refactoring extracts that logic into a reusable function within the `util` package. The new `ResolveAuthDir` function is now used consistently across the application: - During initial server startup in `main.go`. - When counting authentication files in `util.CountAuthFiles`. - When the configuration is reloaded by the watcher. This change eliminates code duplication, improves consistency, and makes the path resolution logic more robust and maintainable.
This commit is contained in:
@@ -8,7 +8,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/cmd"
|
"github.com/router-for-me/CLIProxyAPI/v6/internal/cmd"
|
||||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
||||||
@@ -123,22 +122,10 @@ func main() {
|
|||||||
// Set the log level based on the configuration.
|
// Set the log level based on the configuration.
|
||||||
util.SetLogLevel(cfg)
|
util.SetLogLevel(cfg)
|
||||||
|
|
||||||
// Expand the tilde (~) in the auth directory path to the user's home directory.
|
if resolvedAuthDir, errResolveAuthDir := util.ResolveAuthDir(cfg.AuthDir); errResolveAuthDir != nil {
|
||||||
if strings.HasPrefix(cfg.AuthDir, "~") {
|
log.Fatalf("failed to resolve auth directory: %v", errResolveAuthDir)
|
||||||
home, errUserHomeDir := os.UserHomeDir()
|
} else {
|
||||||
if errUserHomeDir != nil {
|
cfg.AuthDir = resolvedAuthDir
|
||||||
log.Fatalf("failed to get home directory: %v", errUserHomeDir)
|
|
||||||
}
|
|
||||||
// Reconstruct the path by replacing the tilde with the user's home directory.
|
|
||||||
remainder := strings.TrimPrefix(cfg.AuthDir, "~")
|
|
||||||
remainder = strings.TrimLeft(remainder, "/\\")
|
|
||||||
if remainder == "" {
|
|
||||||
cfg.AuthDir = home
|
|
||||||
} else {
|
|
||||||
// Normalize any slash style in the remainder so Windows paths keep nested directories.
|
|
||||||
normalized := strings.ReplaceAll(remainder, "\\", "/")
|
|
||||||
cfg.AuthDir = filepath.Join(home, filepath.FromSlash(normalized))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create login options to be used in authentication flows.
|
// Create login options to be used in authentication flows.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -30,23 +31,42 @@ func SetLogLevel(cfg *config.Config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CountAuthFiles returns the number of JSON auth files located under the provided directory.
|
// ResolveAuthDir normalizes the auth directory path for consistent reuse throughout the app.
|
||||||
// The function resolves leading tildes to the user's home directory and performs a case-insensitive
|
// It expands a leading tilde (~) to the user's home directory and returns a cleaned path.
|
||||||
// match on the ".json" suffix so that files saved with uppercase extensions are also counted.
|
func ResolveAuthDir(authDir string) (string, error) {
|
||||||
func CountAuthFiles(authDir string) int {
|
|
||||||
if authDir == "" {
|
if authDir == "" {
|
||||||
return 0
|
return "", nil
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(authDir, "~") {
|
if strings.HasPrefix(authDir, "~") {
|
||||||
home, err := os.UserHomeDir()
|
home, err := os.UserHomeDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("countAuthFiles: failed to resolve home directory: %v", err)
|
return "", fmt.Errorf("resolve auth dir: %w", err)
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
authDir = filepath.Join(home, authDir[1:])
|
remainder := strings.TrimPrefix(authDir, "~")
|
||||||
|
remainder = strings.TrimLeft(remainder, "/\\")
|
||||||
|
if remainder == "" {
|
||||||
|
return filepath.Clean(home), nil
|
||||||
|
}
|
||||||
|
normalized := strings.ReplaceAll(remainder, "\\", "/")
|
||||||
|
return filepath.Clean(filepath.Join(home, filepath.FromSlash(normalized))), nil
|
||||||
|
}
|
||||||
|
return filepath.Clean(authDir), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountAuthFiles returns the number of JSON auth files located under the provided directory.
|
||||||
|
// The function resolves leading tildes to the user's home directory and performs a case-insensitive
|
||||||
|
// match on the ".json" suffix so that files saved with uppercase extensions are also counted.
|
||||||
|
func CountAuthFiles(authDir string) int {
|
||||||
|
dir, err := ResolveAuthDir(authDir)
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("countAuthFiles: failed to resolve auth directory: %v", err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if dir == "" {
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
count := 0
|
count := 0
|
||||||
walkErr := filepath.WalkDir(authDir, func(path string, d fs.DirEntry, err error) error {
|
walkErr := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("countAuthFiles: error accessing %s: %v", path, err)
|
log.Debugf("countAuthFiles: error accessing %s: %v", path, err)
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -463,6 +463,12 @@ func (w *Watcher) reloadConfig() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if resolvedAuthDir, errResolveAuthDir := util.ResolveAuthDir(newConfig.AuthDir); errResolveAuthDir != nil {
|
||||||
|
log.Errorf("failed to resolve auth directory from config: %v", errResolveAuthDir)
|
||||||
|
} else {
|
||||||
|
newConfig.AuthDir = resolvedAuthDir
|
||||||
|
}
|
||||||
|
|
||||||
w.clientsMutex.Lock()
|
w.clientsMutex.Lock()
|
||||||
oldConfig := w.config
|
oldConfig := w.config
|
||||||
w.config = newConfig
|
w.config = newConfig
|
||||||
@@ -582,19 +588,22 @@ func (w *Watcher) reloadClients(rescanAuth bool) {
|
|||||||
|
|
||||||
// Rebuild auth file hash cache for current clients
|
// Rebuild auth file hash cache for current clients
|
||||||
w.lastAuthHashes = make(map[string]string)
|
w.lastAuthHashes = make(map[string]string)
|
||||||
// Recompute hashes for current auth files
|
if resolvedAuthDir, errResolveAuthDir := util.ResolveAuthDir(cfg.AuthDir); errResolveAuthDir != nil {
|
||||||
_ = filepath.Walk(cfg.AuthDir, func(path string, info fs.FileInfo, err error) error {
|
log.Errorf("failed to resolve auth directory for hash cache: %v", errResolveAuthDir)
|
||||||
if err != nil {
|
} else if resolvedAuthDir != "" {
|
||||||
return nil
|
_ = filepath.Walk(resolvedAuthDir, func(path string, info fs.FileInfo, err error) error {
|
||||||
}
|
if err != nil {
|
||||||
if !info.IsDir() && strings.HasSuffix(strings.ToLower(info.Name()), ".json") {
|
return nil
|
||||||
if data, errReadFile := os.ReadFile(path); errReadFile == nil && len(data) > 0 {
|
|
||||||
sum := sha256.Sum256(data)
|
|
||||||
w.lastAuthHashes[path] = hex.EncodeToString(sum[:])
|
|
||||||
}
|
}
|
||||||
}
|
if !info.IsDir() && strings.HasSuffix(strings.ToLower(info.Name()), ".json") {
|
||||||
return nil
|
if data, errReadFile := os.ReadFile(path); errReadFile == nil && len(data) > 0 {
|
||||||
})
|
sum := sha256.Sum256(data)
|
||||||
|
w.lastAuthHashes[path] = hex.EncodeToString(sum[:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
w.clientsMutex.Unlock()
|
w.clientsMutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -869,14 +878,13 @@ func (w *Watcher) loadFileClients(cfg *config.Config) int {
|
|||||||
authFileCount := 0
|
authFileCount := 0
|
||||||
successfulAuthCount := 0
|
successfulAuthCount := 0
|
||||||
|
|
||||||
authDir := cfg.AuthDir
|
authDir, errResolveAuthDir := util.ResolveAuthDir(cfg.AuthDir)
|
||||||
if strings.HasPrefix(authDir, "~") {
|
if errResolveAuthDir != nil {
|
||||||
home, err := os.UserHomeDir()
|
log.Errorf("failed to resolve auth directory: %v", errResolveAuthDir)
|
||||||
if err != nil {
|
return 0
|
||||||
log.Errorf("failed to get home directory: %v", err)
|
}
|
||||||
return 0
|
if authDir == "" {
|
||||||
}
|
return 0
|
||||||
authDir = filepath.Join(home, authDir[1:])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errWalk := filepath.Walk(authDir, func(path string, info fs.FileInfo, err error) error {
|
errWalk := filepath.Walk(authDir, func(path string, info fs.FileInfo, err error) error {
|
||||||
|
|||||||
Reference in New Issue
Block a user