Backend (Go): - Config: CORS, RabbitMQ, rate limit, main config updates - Routes: core, distribution, tracks routing changes - Middleware: rate limiter, endpoint limiter, response cache hardening - Handlers: distribution, search handler fixes - Workers: job worker improvements - Upload validator and logging config additions - New migrations: products, orders, performance indexes - Seed tooling and data Stream Server (Rust): - Audio processing, config, routes, simple stream server updates - Dockerfile improvements Infrastructure: - docker-compose.yml updates - nginx-rtmp config changes - Makefile improvements (config, dev, high, infra) - Root package.json and lock file updates - .env.example updates Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
132 lines
3.9 KiB
Go
132 lines
3.9 KiB
Go
package config
|
|
|
|
import (
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
// getCookieSecure détermine si les cookies doivent être Secure
|
|
// Auto-detect: secure en production, insecure en développement
|
|
// Peut être forcé via COOKIE_SECURE=true/false
|
|
func getCookieSecure(env string) bool {
|
|
cookieSecureEnv := getEnv("COOKIE_SECURE", "")
|
|
if cookieSecureEnv != "" {
|
|
return getEnvBool("COOKIE_SECURE", false)
|
|
}
|
|
// Auto-detect: secure en production, insecure en développement
|
|
return (env == EnvProduction)
|
|
}
|
|
|
|
// getCookieSameSite détermine la politique SameSite pour les cookies
|
|
// strict par défaut pour sécurité maximale, lax en développement local
|
|
func getCookieSameSite(env string) string {
|
|
cookieSameSite := getEnv("COOKIE_SAME_SITE", "strict")
|
|
if env == EnvDevelopment && cookieSameSite == "strict" {
|
|
// En dev local, utiliser "lax" pour permettre le domaine local (APP_DOMAIN)
|
|
return "lax"
|
|
}
|
|
return cookieSameSite
|
|
}
|
|
|
|
// GetCookieSameSite retourne la valeur http.SameSite correspondante
|
|
func (c *Config) GetCookieSameSite() http.SameSite {
|
|
switch c.CookieSameSite {
|
|
case "lax":
|
|
return http.SameSiteLaxMode
|
|
case "none":
|
|
return http.SameSiteNoneMode
|
|
default:
|
|
return http.SameSiteStrictMode
|
|
}
|
|
}
|
|
|
|
// ShouldUseSecureCookies détermine si les cookies doivent être Secure
|
|
// Prend en compte la configuration explicite et l'environnement
|
|
func (c *Config) ShouldUseSecureCookies() bool {
|
|
return c.CookieSecure
|
|
}
|
|
|
|
// devDefaultCORSOrigins returns origins always allowed in development/staging.
|
|
// Generated from APP_DOMAIN so that changing the domain propagates everywhere.
|
|
func devDefaultCORSOrigins(appDomain string) []string {
|
|
return []string{
|
|
"http://" + appDomain,
|
|
"http://" + appDomain + ":3000",
|
|
"http://" + appDomain + ":5173",
|
|
"http://" + appDomain + ":18080",
|
|
}
|
|
}
|
|
|
|
// mergeCORSOrigins merges custom with base and deduplicates (order: base then custom).
|
|
func mergeCORSOrigins(base, custom []string) []string {
|
|
seen := make(map[string]bool)
|
|
out := make([]string, 0, len(base)+len(custom))
|
|
for _, o := range base {
|
|
if !seen[o] {
|
|
seen[o] = true
|
|
out = append(out, o)
|
|
}
|
|
}
|
|
for _, o := range custom {
|
|
if !seen[o] {
|
|
seen[o] = true
|
|
out = append(out, o)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
// getCORSOrigins charge les origines CORS avec defaults sécurisés selon l'environnement (P0-SECURITY)
|
|
// - development/staging: si CORS_ALLOWED_ORIGINS est défini, on le fusionne avec les defaults (APP_DOMAIN)
|
|
// pour que $APP_DOMAIN:5173 reste autorisé même avec une config partielle
|
|
// - production: CORS_ALLOWED_ORIGINS obligatoire, pas de merge
|
|
// - test: liste vide par défaut
|
|
func getCORSOrigins(env string, appDomain string) []string {
|
|
custom := getEnvStringSlice("CORS_ALLOWED_ORIGINS", nil)
|
|
|
|
switch env {
|
|
case EnvProduction:
|
|
if len(custom) > 0 {
|
|
return custom
|
|
}
|
|
return []string{}
|
|
case EnvTest:
|
|
if len(custom) > 0 {
|
|
return custom
|
|
}
|
|
return []string{}
|
|
case EnvDevelopment, EnvStaging:
|
|
base := devDefaultCORSOrigins(appDomain)
|
|
if len(custom) > 0 {
|
|
return mergeCORSOrigins(base, custom)
|
|
}
|
|
return base
|
|
default:
|
|
return []string{"http://" + appDomain + ":3000", "http://" + appDomain + ":5173"}
|
|
}
|
|
}
|
|
|
|
// getOAuthAllowedRedirectDomains returns the whitelist of domains allowed for OAuth redirect (v0.902).
|
|
// If OAUTH_ALLOWED_REDIRECT_DOMAINS is set, use it. Otherwise derive from CORSOrigins or FrontendURL.
|
|
func getOAuthAllowedRedirectDomains(env string, explicit []string, corsOrigins []string, frontendURL string) []string {
|
|
if len(explicit) > 0 {
|
|
return explicit
|
|
}
|
|
if len(corsOrigins) > 0 {
|
|
return corsOrigins
|
|
}
|
|
if frontendURL != "" {
|
|
if u, err := url.Parse(frontendURL); err == nil {
|
|
origin := strings.TrimSuffix(u.String(), "/")
|
|
if u.Scheme != "" && u.Host != "" {
|
|
return []string{origin}
|
|
}
|
|
}
|
|
}
|
|
// Dev fallback
|
|
if env == EnvDevelopment || env == EnvStaging {
|
|
return []string{"http://localhost:5173", "http://localhost:3000", "http://127.0.0.1:5173", "http://127.0.0.1:3000"}
|
|
}
|
|
return []string{}
|
|
}
|