backend barebone done, big chunk of work done
CI / Go (build + vet + test) (push) Canceled after 0s
CI / Web (build + lint) (push) Canceled after 0s

This commit is contained in:
vantablackTea
2026-09-27 19:42:49 +03:00
parent 1a669c948a
commit c79a3cfe68
36 changed files with 2607 additions and 17 deletions
+10
View File
@@ -20,6 +20,10 @@ type Config struct {
// AllowedOrigins is a comma-separated list of CORS origins
// allowed to call the API from a browser.
AllowedOrigins []string
// DatabaseURL is the PostgreSQL DSN.
DatabaseURL string
// JWTSecret signs access tokens. Must be set in production.
JWTSecret string
}
// Load reads configuration from the environment, falling back to
@@ -29,6 +33,8 @@ func Load() (*Config, error) {
HTTPAddr: fromEnv("MESSENGER_HTTP_ADDR", ":8080"),
StaticDir: os.Getenv("MESSENGER_STATIC_DIR"),
Environment: fromEnv("MESSENGER_ENV", "development"),
DatabaseURL: fromEnv("MESSENGER_DATABASE_URL", "postgres://messenger:messenger@localhost:5432/messenger?sslmode=disable"),
JWTSecret: fromEnv("MESSENGER_JWT_SECRET", "dev-secret-change-me"),
}
for _, origin := range strings.Split(fromEnv("MESSENGER_ALLOWED_ORIGINS", ""), ",") {
@@ -43,6 +49,10 @@ func Load() (*Config, error) {
return nil, fmt.Errorf("MESSENGER_ENV must be one of development|staging|production, got %q", cfg.Environment)
}
if cfg.Environment == "production" && cfg.JWTSecret == "dev-secret-change-me" {
return nil, fmt.Errorf("MESSENGER_JWT_SECRET must be set in production")
}
return cfg, nil
}
@@ -24,6 +24,7 @@ func TestLoadFromEnv(t *testing.T) {
t.Setenv("MESSENGER_HTTP_ADDR", ":9000")
t.Setenv("MESSENGER_ENV", "production")
t.Setenv("MESSENGER_ALLOWED_ORIGINS", "https://a.example, https://b.example")
t.Setenv("MESSENGER_JWT_SECRET", "prod-secret-at-least-32-chars-long!!")
cfg, err := Load()
if err != nil {
@@ -38,6 +39,9 @@ func TestLoadFromEnv(t *testing.T) {
if len(cfg.AllowedOrigins) != 2 || cfg.AllowedOrigins[1] != "https://b.example" {
t.Errorf("AllowedOrigins = %v, want [https://a.example https://b.example]", cfg.AllowedOrigins)
}
if cfg.DatabaseURL == "" {
t.Error("DatabaseURL = empty, want default DSN")
}
}
func TestLoadInvalidEnv(t *testing.T) {
@@ -47,3 +51,12 @@ func TestLoadInvalidEnv(t *testing.T) {
t.Fatal("Load() error = nil, want validation error")
}
}
func TestLoadRequiresJWTSecretInProduction(t *testing.T) {
t.Setenv("MESSENGER_ENV", "production")
t.Setenv("MESSENGER_JWT_SECRET", "")
if _, err := Load(); err == nil {
t.Fatal("Load() error = nil, want missing JWT secret error")
}
}