ipapi/internal/config/config.go
sneak 08ca75966e Fix dependency injection and implement proper CIDR checking
- Add http module for proper FX dependency injection
- Fix router to accept state manager parameter
- Implement proper CIDR-based checking for RFC1918 and documentation IPs
- Add reasonable timeouts (30s) for database downloads
- Update tests to download databases to temporary directories
- Add tests for multiple IP lookups and error cases
- All tests passing
2025-07-27 18:44:53 +02:00

104 lines
2.0 KiB
Go

// Package config handles application configuration.
package config
import (
"os"
"path/filepath"
"runtime"
"strconv"
"git.eeqj.de/sneak/smartconfig"
)
// Config holds the application configuration.
type Config struct {
Port int
StateDir string
LogLevel string
}
// New creates a new configuration instance.
func New(configFile string) (*Config, error) {
// Check if config file exists first
if _, err := os.Stat(configFile); os.IsNotExist(err) {
return newDefaultConfig(), nil
}
// Load smartconfig
sc, err := smartconfig.NewFromConfigPath(configFile)
if err != nil {
return nil, err
}
cfg := &Config{}
// Get port from smartconfig or environment or default
if port, err := sc.GetInt("port"); err == nil {
cfg.Port = port
} else {
cfg.Port = getPortFromEnv()
}
// Get state directory
if stateDir, err := sc.GetString("state_dir"); err == nil {
cfg.StateDir = stateDir
} else {
cfg.StateDir = getDefaultStateDir()
}
// Get log level
if logLevel, err := sc.GetString("log_level"); err == nil {
cfg.LogLevel = logLevel
} else {
cfg.LogLevel = "info"
}
return cfg, nil
}
func newDefaultConfig() *Config {
return &Config{
Port: getPortFromEnv(),
StateDir: getDefaultStateDir(),
LogLevel: "info",
}
}
func getPortFromEnv() int {
const defaultPort = 8080
portStr := os.Getenv("PORT")
if portStr == "" {
return defaultPort
}
port, err := strconv.Atoi(portStr)
if err != nil {
return defaultPort
}
return port
}
func getDefaultStateDir() string {
switch runtime.GOOS {
case "darwin":
// macOS: use ~/Library/Application Support/berlin.sneak.app.ipapi/
home, err := os.UserHomeDir()
if err != nil {
return "/var/lib/ipapi"
}
return filepath.Join(home, "Library", "Application Support", "berlin.sneak.app.ipapi")
case "windows":
// Windows: use %APPDATA%\berlin.sneak.app.ipapi
appData := os.Getenv("APPDATA")
if appData == "" {
return "/var/lib/ipapi"
}
return filepath.Join(appData, "berlin.sneak.app.ipapi")
default:
// Linux and other Unix-like systems
return "/var/lib/ipapi"
}
}