package config import ( "crypto/rand" "encoding/hex" "log" "os" "strings" "github.com/joho/godotenv" ) type Config struct { Port string DBPath string AppURL string FrontendURL string JWTSecret string EncryptionKey string GoogleClientID string GoogleClientSecret string StaticDir string } // Load liest die Konfiguration aus Umgebungsvariablen (.env wird unterstützt). // Fehlende Secrets werden nur für die Entwicklung zufällig erzeugt. func Load() Config { _ = godotenv.Load() cfg := Config{ Port: env("PORT", "8080"), DBPath: env("DB_PATH", "wannpassts.db"), AppURL: strings.TrimSuffix(env("APP_URL", "http://localhost:8080"), "/"), FrontendURL: strings.TrimSuffix(os.Getenv("FRONTEND_URL"), "/"), JWTSecret: os.Getenv("JWT_SECRET"), EncryptionKey: os.Getenv("ENCRYPTION_KEY"), GoogleClientID: os.Getenv("GOOGLE_CLIENT_ID"), GoogleClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"), StaticDir: env("STATIC_DIR", ""), } // FRONTEND_URL ist optional: Ohne eigenen Wert leiten Google-Callbacks etc. // auf die öffentliche App-URL (APP_URL) – wichtig für Single-Origin-Deployments. if cfg.FrontendURL == "" { cfg.FrontendURL = cfg.AppURL } if cfg.JWTSecret == "" { cfg.JWTSecret = randomHex(32) log.Println("WARNUNG: JWT_SECRET nicht gesetzt – temporäres Secret erzeugt (Sessions verfallen bei Neustart).") } if cfg.EncryptionKey == "" { cfg.EncryptionKey = randomHex(32) log.Println("WARNUNG: ENCRYPTION_KEY nicht gesetzt – temporärer Schlüssel erzeugt (Kalender-Tokens verfallen bei Neustart).") } return cfg } func env(key, def string) string { if v := os.Getenv(key); v != "" { return v } return def } func randomHex(n int) string { b := make([]byte, n) if _, err := rand.Read(b); err != nil { log.Fatalf("Zufallszahl nicht verfügbar: %v", err) } return hex.EncodeToString(b) }