package config import ( "log/slog" "os" "path/filepath" "strings" ) type Config struct { Port string DataDir string DatabasePath string JWTSecret string BaseURL string AllowRegistration bool LogLevel string Debug bool DemoMode bool // Optional SMTP environment variables (can also be overridden/configured in DB system_settings) SMTPHost string SMTPPort string SMTPUser string SMTPPass string SMTPFrom string SMTPTLS bool } func Load() *Config { port := getEnv("PORT", "8080") dataDir := getEnv("DATA_DIR", "./data") dbURL := getEnv("DATABASE_URL", "") dbPath := filepath.Join(dataDir, "mindsift.db") if strings.HasPrefix(dbURL, "sqlite://") { dbPath = strings.TrimPrefix(dbURL, "sqlite://") } else if dbURL != "" && !strings.HasPrefix(dbURL, "postgres") { dbPath = dbURL } jwtSecret := getEnv("JWT_SECRET", "mindsift-default-selfhosted-jwt-secret-key-2026") baseURL := getEnv("BASE_URL", "http://localhost:"+port) allowReg := strings.ToLower(getEnv("ALLOW_REGISTRATION", "false")) == "true" debugVal := strings.ToLower(getEnv("DEBUG", "false")) debug := debugVal == "true" || debugVal == "1" || debugVal == "yes" || debugVal == "on" logLevel := strings.ToLower(getEnv("LOG_LEVEL", "info")) if debug { logLevel = "debug" } demoVal := strings.ToLower(getEnv("MINDA_DEMO", getEnv("MINDSIFT_DEMO", getEnv("DEMO_MODE", "false")))) demoMode := demoVal == "true" || demoVal == "1" || demoVal == "yes" || demoVal == "on" smtpHost := getEnv("SMTP_HOST", "") smtpPort := getEnv("SMTP_PORT", "587") smtpUser := getEnv("SMTP_USER", "") smtpPass := getEnv("SMTP_PASS", "") smtpFrom := getEnv("SMTP_FROM", "") smtpTLS := strings.ToLower(getEnv("SMTP_TLS", "true")) != "false" return &Config{ Port: port, DataDir: dataDir, DatabasePath: dbPath, JWTSecret: jwtSecret, BaseURL: baseURL, AllowRegistration: allowReg, LogLevel: logLevel, Debug: debug, DemoMode: demoMode, SMTPHost: smtpHost, SMTPPort: smtpPort, SMTPUser: smtpUser, SMTPPass: smtpPass, SMTPFrom: smtpFrom, SMTPTLS: smtpTLS, } } // SlogLevel parses Config.LogLevel into a standard slog.Level. func (c *Config) SlogLevel() slog.Level { switch strings.ToLower(strings.TrimSpace(c.LogLevel)) { case "debug": return slog.LevelDebug case "warn", "warning": return slog.LevelWarn case "error": return slog.LevelError default: return slog.LevelInfo } } func getEnv(key, fallback string) string { if val, ok := os.LookupEnv(key); ok && strings.TrimSpace(val) != "" { return strings.TrimSpace(val) } return fallback }