szabadpalya/api/internal/config/config.go

66 lines
1.9 KiB
Go

// Package config reads the process environment once, at startup, so that a
// missing setting fails the boot rather than the first request that needs it.
package config
import (
"fmt"
"os"
"strings"
)
type Config struct {
DatabaseURL string
// BaseURL is the public origin. It decides whether the session cookie is
// marked Secure and what host magic links point at, so it must be the real
// external URL in production, not the listen address.
BaseURL string
Addr string
SessionKey []byte
AdminEmails []string
// WebDir holds the built frontend: index.html is never served from here,
// only the hashed assets and the Vite manifest the shell reads.
WebDir string
Dev bool
}
func Load() (*Config, error) {
c := &Config{
DatabaseURL: os.Getenv("DATABASE_URL"),
BaseURL: envOr("BASE_URL", "http://localhost:3000"),
Addr: envOr("ADDR", ":3000"),
WebDir: envOr("WEB_DIR", "./web"),
Dev: os.Getenv("APP_ENV") == "development",
}
if c.DatabaseURL == "" {
return nil, fmt.Errorf("DATABASE_URL environment variable is missing")
}
secret := os.Getenv("SESSION_SECRET")
if secret == "" {
return nil, fmt.Errorf("SESSION_SECRET environment variable is missing (openssl rand -base64 32)")
}
c.SessionKey = []byte(secret)
for _, e := range strings.Split(os.Getenv("ADMIN_EMAILS"), ",") {
if e = strings.ToLower(strings.TrimSpace(e)); e != "" {
c.AdminEmails = append(c.AdminEmails, e)
}
}
c.BaseURL = strings.TrimRight(c.BaseURL, "/")
return c, nil
}
// Secure reports whether cookies may carry the Secure flag. Setting it on a
// plain-HTTP origin would make the browser drop the cookie silently, which
// looks exactly like a broken login.
func (c *Config) Secure() bool { return strings.HasPrefix(c.BaseURL, "https://") }
func envOr(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}