mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-03 18:22:57 +00:00
326 lines
9.4 KiB
Go
326 lines
9.4 KiB
Go
package config
|
|
|
|
import (
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/joho/godotenv"
|
|
)
|
|
|
|
// Config holds all configuration for the application
|
|
type Config struct {
|
|
// App settings
|
|
AppEnv string
|
|
Port string
|
|
Debug bool
|
|
Premium bool
|
|
|
|
// Database settings
|
|
DatabaseURL string
|
|
MaxIdleConnections int
|
|
MaxOpenConnections int
|
|
ConnMaxLifetime time.Duration
|
|
|
|
// JWT settings
|
|
JWTSecret string
|
|
JWTExpiration time.Duration
|
|
|
|
// Server settings
|
|
ReadTimeout time.Duration
|
|
WriteTimeout time.Duration
|
|
IdleTimeout time.Duration
|
|
// Security
|
|
ContentSecurityPolicy string
|
|
|
|
// File upload settings
|
|
UploadDir string
|
|
MaxUploadSize int64
|
|
AllowedMimeTypes []string
|
|
|
|
// Email settings
|
|
SMTPHost string
|
|
SMTPPort int
|
|
SMTPUser string
|
|
SMTPPassword string
|
|
SMTPFrom string
|
|
SMTPFromName string
|
|
SMTPEncryption string
|
|
SMTPAuth bool
|
|
SMTPSkipVerify bool
|
|
|
|
// Email templates
|
|
EmailTemplateDir string
|
|
|
|
// Contact settings
|
|
ContactEmail string
|
|
AdminEmail string
|
|
// Admin access token (optional) to allow token-based admin access
|
|
AdminAccessToken string
|
|
|
|
// Newsletter settings
|
|
NewsletterEnabled bool
|
|
|
|
// CORS settings
|
|
AllowedOrigins []string
|
|
|
|
// External services
|
|
ScraperBaseURL string
|
|
FrontendBaseURL string
|
|
PublicAPIBaseURL string
|
|
ZoneramaAPIBase string
|
|
|
|
// Umami Analytics
|
|
UmamiURL string
|
|
UmamiUsername string
|
|
UmamiPassword string
|
|
UmamiWebsiteID string
|
|
|
|
ErrorIngestURL string
|
|
ErrorIngestToken string
|
|
|
|
// Antivirus (optional)
|
|
ClamAVEnabled bool
|
|
ClamAVHost string
|
|
ClamAVPort int
|
|
|
|
// Feature flags
|
|
RembgEnabled bool
|
|
// Club data mode: "auto" (FACR integration) or "manual" (no FACR/http scraping)
|
|
ClubDataMode string
|
|
|
|
// E-shop settings
|
|
EshopEnabled bool
|
|
EshopFrontendURL string
|
|
EshopAPIURL string
|
|
|
|
// Stripe (E-shop payments)
|
|
StripeEnabled bool
|
|
StripeSecretKey string
|
|
StripePublishableKey string
|
|
StripeWebhookSecret string
|
|
StripeCurrency string
|
|
StripeReturnURL string
|
|
|
|
// Revolut (E-shop payments)
|
|
RevolutEnabled bool
|
|
RevolutEnvironment string
|
|
RevolutAPIKey string
|
|
RevolutPublicKey string
|
|
RevolutWebhookSecret string
|
|
RevolutReturnURL string
|
|
RevolutWebhookURL string
|
|
|
|
// Packeta / Zasilkovna
|
|
PacketaAPIPassword string
|
|
PacketaWidgetAPIKey string
|
|
PacketaEshopName string
|
|
PacketaEnv string
|
|
|
|
// DeepSeek AI Support
|
|
DeepSeekAPIKey string
|
|
DeepSeekBaseURL string
|
|
}
|
|
|
|
var AppConfig *Config
|
|
|
|
// LoadConfig loads the configuration from environment variables
|
|
func LoadConfig() {
|
|
// Load .env file if it exists
|
|
_ = godotenv.Load()
|
|
|
|
AppConfig = &Config{
|
|
// App settings
|
|
AppEnv: getEnv("APP_ENV", "development"),
|
|
Port: getEnv("PORT", "8080"),
|
|
Debug: getEnvAsBool("DEBUG", true),
|
|
Premium: getEnvAsBool("PREMIUM", false),
|
|
|
|
// Database settings
|
|
DatabaseURL: getEnv("DATABASE_URL", "postgres://postgres:postgres@localhost:5432/fotbal_club?sslmode=disable"),
|
|
MaxIdleConnections: getEnvAsInt("DB_MAX_IDLE_CONNS", 10),
|
|
MaxOpenConnections: getEnvAsInt("DB_MAX_OPEN_CONNS", 100),
|
|
ConnMaxLifetime: time.Duration(getEnvAsInt("DB_CONN_MAX_LIFETIME", 60)) * time.Minute,
|
|
|
|
// JWT settings
|
|
JWTSecret: getEnv("JWT_SECRET", "default-secret-key-change-in-production"),
|
|
JWTExpiration: time.Duration(getEnvAsInt("JWT_EXPIRATION_HOURS", 24)) * time.Hour,
|
|
|
|
// Server settings
|
|
ReadTimeout: time.Duration(getEnvAsInt("READ_TIMEOUT", 5)) * time.Second,
|
|
WriteTimeout: time.Duration(getEnvAsInt("WRITE_TIMEOUT", 10)) * time.Second,
|
|
IdleTimeout: time.Duration(getEnvAsInt("IDLE_TIMEOUT", 120)) * time.Second,
|
|
|
|
// Security
|
|
ContentSecurityPolicy: getEnv("CONTENT_SECURITY_POLICY", "default-src 'self' data: blob: https: http:; img-src * data: blob:; style-src 'self' 'unsafe-inline' https: http:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https: http:; connect-src *; frame-ancestors 'self';"),
|
|
|
|
// File upload settings
|
|
UploadDir: getEnv("UPLOAD_DIR", "./uploads"),
|
|
MaxUploadSize: int64(getEnvAsInt("MAX_UPLOAD_SIZE", 20)) * 1024 * 1024, // 20MB default
|
|
AllowedMimeTypes: []string{
|
|
// Images
|
|
"image/jpeg",
|
|
"image/png",
|
|
"image/gif",
|
|
"image/webp",
|
|
"image/svg+xml",
|
|
// Documents
|
|
"application/pdf",
|
|
"application/msword", // .doc
|
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document", // .docx
|
|
"application/vnd.ms-excel", // .xls
|
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // .xlsx
|
|
"application/vnd.ms-powerpoint", // .ppt
|
|
"application/vnd.openxmlformats-officedocument.presentationml.presentation", // .pptx
|
|
// Text
|
|
"text/plain",
|
|
// Archives
|
|
"application/zip",
|
|
"application/x-zip-compressed",
|
|
"application/x-rar-compressed",
|
|
"application/vnd.rar",
|
|
},
|
|
|
|
// Email settings
|
|
SMTPHost: getEnv("SMTP_HOST", "smtp.example.com"),
|
|
SMTPPort: getEnvAsInt("SMTP_PORT", 587),
|
|
SMTPUser: getEnv("SMTP_USER", ""),
|
|
SMTPPassword: getEnv("SMTP_PASSWORD", ""),
|
|
SMTPFrom: getEnv("SMTP_FROM", "noreply@fotbal-club.cz"),
|
|
SMTPFromName: getEnv("SMTP_FROM_NAME", "Fotbal Club"),
|
|
SMTPEncryption: getEnv("SMTP_ENCRYPTION", "tls"),
|
|
SMTPAuth: getEnvAsBool("SMTP_AUTH", true),
|
|
SMTPSkipVerify: getEnvAsBool("SMTP_SKIP_VERIFY", false),
|
|
|
|
// Email templates - using absolute path to templates
|
|
EmailTemplateDir: getEnv("EMAIL_TEMPLATE_DIR", filepath.Join("templates", "emails")),
|
|
|
|
// Contact settings
|
|
ContactEmail: getEnv("CONTACT_EMAIL", "help@tdvorak.dev"),
|
|
AdminEmail: getEnv("ADMIN_EMAIL", "help@tdvorak.dev"),
|
|
AdminAccessToken: getEnv("ADMIN_ACCESS_TOKEN", ""),
|
|
|
|
// Newsletter settings
|
|
NewsletterEnabled: getEnvAsBool("NEWSLETTER_ENABLED", true),
|
|
|
|
// CORS settings
|
|
AllowedOrigins: []string{
|
|
"http://localhost:3000",
|
|
"http://localhost:8080",
|
|
},
|
|
|
|
// External services
|
|
ScraperBaseURL: getEnv("FACR_SCRAPER_BASE_URL", "http://localhost:8081"),
|
|
FrontendBaseURL: getEnv("FRONTEND_BASE_URL", "http://localhost:3000"),
|
|
PublicAPIBaseURL: getEnv("PUBLIC_API_BASE_URL", "http://localhost:8080/api/v1"),
|
|
ZoneramaAPIBase: getEnv("ZONERAMA_API_BASE", "https://zonerama.tdvorak.dev"),
|
|
|
|
// Umami Analytics
|
|
UmamiURL: getEnv("UMAMI_URL", ""),
|
|
UmamiUsername: getEnv("UMAMI_USERNAME", ""),
|
|
UmamiPassword: getEnv("UMAMI_PASSWORD", ""),
|
|
UmamiWebsiteID: getEnv("UMAMI_WEBSITE_ID", ""),
|
|
|
|
ErrorIngestURL: getEnv("ERROR_INGEST_URL", ""),
|
|
ErrorIngestToken: getEnv("ERROR_INGEST_TOKEN", ""),
|
|
|
|
// Antivirus (optional)
|
|
ClamAVEnabled: getEnvAsBool("CLAMAV_ENABLED", false),
|
|
ClamAVHost: getEnv("CLAMAV_HOST", "127.0.0.1"),
|
|
ClamAVPort: getEnvAsInt("CLAMAV_PORT", 3310),
|
|
|
|
// Feature flags
|
|
RembgEnabled: getEnvAsBool("REMBG_ENABLED", true),
|
|
// Club data mode: auto (FACR integration) or manual (no FACR/http scraping)
|
|
ClubDataMode: strings.ToLower(strings.TrimSpace(getEnv("CLUB_DATA_MODE", "auto"))),
|
|
|
|
// E-shop settings
|
|
EshopEnabled: getEnvAsBool("ESHOP_ENABLED", false),
|
|
EshopFrontendURL: getEnv("ESHOP_FRONTEND_URL", ""),
|
|
EshopAPIURL: getEnv("ESHOP_API_URL", ""),
|
|
|
|
// Stripe (E-shop payments)
|
|
StripeEnabled: getEnvAsBool("STRIPE_ENABLED", false),
|
|
StripeSecretKey: getEnv("STRIPE_SECRET_KEY", ""),
|
|
StripePublishableKey: getEnv("STRIPE_PUBLISHABLE_KEY", ""),
|
|
StripeWebhookSecret: getEnv("STRIPE_WEBHOOK_SECRET", ""),
|
|
StripeCurrency: getEnv("STRIPE_CURRENCY", "CZK"),
|
|
StripeReturnURL: getEnv("STRIPE_RETURN_URL", ""),
|
|
|
|
// Revolut (E-shop payments)
|
|
RevolutEnabled: getEnvAsBool("REVOLUT_ENABLED", false),
|
|
RevolutEnvironment: getEnv("REVOLUT_ENVIRONMENT", "sandbox"),
|
|
RevolutAPIKey: getEnv("REVOLUT_API_KEY", ""),
|
|
RevolutPublicKey: getEnv("REVOLUT_PUBLIC_KEY", ""),
|
|
RevolutWebhookSecret: getEnv("REVOLUT_WEBHOOK_SECRET", ""),
|
|
RevolutReturnURL: getEnv("REVOLUT_RETURN_URL", ""),
|
|
RevolutWebhookURL: getEnv("REVOLUT_WEBHOOK_URL", ""),
|
|
|
|
// Packeta / Zasilkovna
|
|
PacketaAPIPassword: getEnv("PACKETA_API_PASSWORD", ""),
|
|
PacketaWidgetAPIKey: getEnv("PACKETA_WIDGET_API_KEY", ""),
|
|
PacketaEshopName: getEnv("PACKETA_ESHP_NAME", "MyClubEshop"),
|
|
PacketaEnv: getEnv("PACKETA_ENV", "test"),
|
|
|
|
// DeepSeek AI Support (used by e-shop support chat)
|
|
DeepSeekAPIKey: getEnv("DEEPSEEK_API_KEY", ""),
|
|
DeepSeekBaseURL: getEnv("DEEPSEEK_BASE_URL", "https://api.deepseek.com"),
|
|
}
|
|
|
|
// Override allowed origins if specified in environment (comma-separated)
|
|
if origins := os.Getenv("ALLOWED_ORIGINS"); origins != "" {
|
|
parts := strings.Split(origins, ",")
|
|
var list []string
|
|
for _, p := range parts {
|
|
v := strings.TrimSpace(p)
|
|
if v != "" {
|
|
list = append(list, v)
|
|
}
|
|
}
|
|
if len(list) > 0 {
|
|
AppConfig.AllowedOrigins = list
|
|
}
|
|
}
|
|
}
|
|
|
|
func getEnv(key, defaultValue string) string {
|
|
value := os.Getenv(key)
|
|
if value == "" {
|
|
return defaultValue
|
|
}
|
|
return value
|
|
}
|
|
|
|
func getEnvAsInt(key string, defaultValue int) int {
|
|
valueStr := os.Getenv(key)
|
|
if valueStr == "" {
|
|
return defaultValue
|
|
}
|
|
|
|
value, err := strconv.Atoi(valueStr)
|
|
if err != nil {
|
|
log.Printf("Invalid value for %s: %v. Using default: %d", key, err, defaultValue)
|
|
return defaultValue
|
|
}
|
|
|
|
return value
|
|
}
|
|
|
|
func getEnvAsBool(key string, defaultValue bool) bool {
|
|
valueStr := os.Getenv(key)
|
|
if valueStr == "" {
|
|
return defaultValue
|
|
}
|
|
|
|
value, err := strconv.ParseBool(valueStr)
|
|
if err != nil {
|
|
log.Printf("Invalid boolean value for %s: %v. Using default: %t", key, err, defaultValue)
|
|
return defaultValue
|
|
}
|
|
|
|
return value
|
|
}
|