package main import ( "errors" "fmt" "net/url" "strings" "gardomatic.kleiax.de/internal/platform/environment" "gardomatic.kleiax.de/internal/platform/validate" "gardomatic.kleiax.de/internal/storage" "gardomatic.kleiax.de/internal/web" ) func configFromEnvironment() (web.Config, error) { port, err := environment.Int("GARDOMATIC_WEB_PORT", 4040) if err != nil { return web.Config{}, err } cookieSecure, err := environment.Bool("GARDOMATIC_COOKIE_SECURE", false) if err != nil { return web.Config{}, err } cfg := web.Config{Host: environment.String("GARDOMATIC_WEB_HOST", ""), Port: port, Env: environment.String("GARDOMATIC_ENV", "development"), APIBaseURL: environment.String("GARDOMATIC_API_BASE_URL", "http://localhost:4000"), DemoAccountEmail: strings.ToLower(strings.TrimSpace(environment.String("GARDOMATIC_DEMO_ACCOUNT_EMAIL", ""))), SessionCookieName: environment.String("GARDOMATIC_SESSION_COOKIE_NAME", "gardomatic_session"), CookieSecure: cookieSecure} var errs []error if cfg.Port < 1 || cfg.Port > 65535 { errs = append(errs, errors.New("GARDOMATIC_WEB_PORT must be between 1 and 65535")) } parsed, parseErr := url.ParseRequestURI(cfg.APIBaseURL) if parseErr != nil || parsed.Scheme == "" || parsed.Host == "" { errs = append(errs, fmt.Errorf("GARDOMATIC_API_BASE_URL must be an absolute HTTP URL")) } if cfg.Env == "production" && !cfg.CookieSecure { errs = append(errs, errors.New("GARDOMATIC_COOKIE_SECURE must be true in production")) } if cfg.DemoAccountEmail != "" { v := validate.New() if storage.ValidateEmail(v, cfg.DemoAccountEmail); !v.Valid() { errs = append(errs, errors.New("GARDOMATIC_DEMO_ACCOUNT_EMAIL must be a valid email address")) } } return cfg, errors.Join(errs...) }