secret/internal/secret/helpers.go
clawbot 6211b8e768 Return error from GetDefaultStateDir when home directory unavailable
When os.UserConfigDir() fails, DetermineStateDir falls back to
os.UserHomeDir(). Previously the error from UserHomeDir was discarded,
which could result in a dangerous root-relative path (/.config/...) if
both calls fail.

Now DetermineStateDir returns (string, error) and propagates failures
from both UserConfigDir and UserHomeDir.

Closes #14
2026-02-15 14:05:15 -08:00

61 lines
1.8 KiB
Go

package secret
import (
"crypto/rand"
"fmt"
"math/big"
"os"
"path/filepath"
)
// generateRandomString generates a random string of the specified length using the given character set
func generateRandomString(length int, charset string) (string, error) {
if length <= 0 {
return "", fmt.Errorf("length must be positive")
}
result := make([]byte, length)
charsetLen := big.NewInt(int64(len(charset)))
for i := range length {
randomIndex, err := rand.Int(rand.Reader, charsetLen)
if err != nil {
return "", fmt.Errorf("failed to generate random number: %w", err)
}
result[i] = charset[randomIndex.Int64()]
}
return string(result), nil
}
// DetermineStateDir determines the state directory based on environment variables and OS.
// It returns an error if no usable directory can be determined.
func DetermineStateDir(customConfigDir string) (string, error) {
// Check for environment variable first
if envStateDir := os.Getenv(EnvStateDir); envStateDir != "" {
return envStateDir, nil
}
// Use custom config dir if provided
if customConfigDir != "" {
return filepath.Join(customConfigDir, AppID), nil
}
// Use os.UserConfigDir() which handles platform-specific directories:
// - On Unix systems, it returns $XDG_CONFIG_HOME or $HOME/.config
// - On Darwin, it returns $HOME/Library/Application Support
// - On Windows, it returns %AppData%
configDir, err := os.UserConfigDir()
if err != nil {
// Fallback to a reasonable default if we can't determine user config dir
homeDir, homeErr := os.UserHomeDir()
if homeErr != nil {
return "", fmt.Errorf("unable to determine state directory: config dir: %w, home dir: %w", err, homeErr)
}
return filepath.Join(homeDir, ".config", AppID), nil
}
return filepath.Join(configDir, AppID), nil
}