Files
todo-vibe-coding/internal/iam/config.go

96 lines
2.6 KiB
Go

package iam
import (
"os"
"strconv"
"strings"
"time"
)
type Config struct {
AccessSecret string
RefreshSecret string
RefreshPepper string
AccessTTL time.Duration
RefreshTTL time.Duration
SessionTTL time.Duration
RefreshCookieName string
CookieSecure bool
CookieDomain string
CookiePath string
CookieSameSite string
RedisAddr string
RedisPassword string
RedisDB int
}
func LoadConfig() Config {
cfg := Config{
AccessSecret: firstNonEmpty(strings.TrimSpace(os.Getenv("ACCESS_SECRET")), strings.TrimSpace(os.Getenv("AUTH_SECRET")), "dev-access-secret-change-me"),
RefreshSecret: firstNonEmpty(strings.TrimSpace(os.Getenv("REFRESH_SECRET")), strings.TrimSpace(os.Getenv("AUTH_SECRET")), "dev-refresh-secret-change-me"),
RefreshPepper: firstNonEmpty(strings.TrimSpace(os.Getenv("REFRESH_PEPPER")), "dev-refresh-pepper-change-me"),
AccessTTL: parseDuration("ACCESS_TTL", 60*time.Minute),
RefreshTTL: parseDuration("REFRESH_TTL", 7*24*time.Hour),
RefreshCookieName: firstNonEmpty(strings.TrimSpace(os.Getenv("REFRESH_COOKIE_NAME")), "rt"),
CookieSecure: parseBool("COOKIE_SECURE", isProduction()),
CookieDomain: strings.TrimSpace(os.Getenv("COOKIE_DOMAIN")),
CookiePath: firstNonEmpty(strings.TrimSpace(os.Getenv("COOKIE_PATH")), "/"),
CookieSameSite: firstNonEmpty(strings.TrimSpace(os.Getenv("COOKIE_SAMESITE")), "Lax"),
RedisAddr: strings.TrimSpace(os.Getenv("REDIS_ADDR")),
RedisPassword: os.Getenv("REDIS_PASSWORD"),
RedisDB: parseInt("REDIS_DB", 0),
}
cfg.SessionTTL = parseDuration("SESSION_TTL", cfg.RefreshTTL)
return cfg
}
func parseDuration(key string, fallback time.Duration) time.Duration {
value := strings.TrimSpace(os.Getenv(key))
if value == "" {
return fallback
}
d, err := time.ParseDuration(value)
if err != nil || d <= 0 {
return fallback
}
return d
}
func parseBool(key string, fallback bool) bool {
value := strings.TrimSpace(os.Getenv(key))
if value == "" {
return fallback
}
parsed, err := strconv.ParseBool(value)
if err != nil {
return fallback
}
return parsed
}
func parseInt(key string, fallback int) int {
value := strings.TrimSpace(os.Getenv(key))
if value == "" {
return fallback
}
parsed, err := strconv.Atoi(value)
if err != nil {
return fallback
}
return parsed
}
func isProduction() bool {
env := strings.ToLower(strings.TrimSpace(os.Getenv("APP_ENV")))
return env == "prod" || env == "production"
}
func firstNonEmpty(values ...string) string {
for _, v := range values {
if strings.TrimSpace(v) != "" {
return v
}
}
return ""
}