package config import ( "crypto/rand" "fmt" "math/big" "time" "github.com/spf13/viper" ) type Config struct { Server ServerConfig Database DatabaseConfig Stripe StripeConfig OVH OVHConfig Mailer MailerConfig Logging LoggingConfig JWT JWT } type ServerConfig struct { Address string Port int ReadTimeout time.Duration WriteTimeout time.Duration IdleTimeout time.Duration Tls TlsConfig } type DatabaseConfig struct { DSN string } type StripeConfig struct { APIKey string `mapstructure:"api_key" env:"STRIPE_API_KEY"` EndpointSecret string `mapstructure:"endpoint_secret" env:"STRIPE_WEBHOOK_SECRET"` } type OVHConfig struct { Endpoint string AppKey string AppSecret string ConsumerKey string } type MailerConfig struct { Identity string Username string Password string Host string Port string From string } type TlsConfig struct { CertFile string KeyFile string } type LoggingConfig struct { Level string Format string } type JWT struct { Secret string } func Load() (*Config, error) { viper.SetConfigName("config") viper.SetConfigType("yaml") viper.AddConfigPath(".") viper.AddConfigPath("/etc/byom/") // Set defaults viper.SetDefault("server.port", 8080) viper.SetDefault("server.readTimeout", "15s") viper.SetDefault("server.writeTimeout", "15s") viper.SetDefault("server.idleTimeout", "60s") viper.SetDefault("database.dsn", ".trash/trash.db") //generate random secret for jwt secret, err := GenerateRandomString(256) if err != nil { return nil, fmt.Errorf("error generating random string: %w", err) } viper.SetDefault("jwt.secret", secret) // Environment variables viper.AutomaticEnv() viper.SetEnvPrefix("BYOM") // Bind environment variables viper.BindEnv("stripe.api_key", "STRIPE_API_KEY") viper.BindEnv("stripe.endpoint_secret", "STRIPE_WEBHOOK_SECRET") // Set defaults if needed viper.SetDefault("stripe.api_key", "") viper.SetDefault("stripe.endpoint_secret", "") if err := viper.ReadInConfig(); err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); !ok { return nil, fmt.Errorf("error reading config: %w", err) } } var config Config if err := viper.Unmarshal(&config); err != nil { return nil, fmt.Errorf("error unmarshaling config: %w", err) } return &config, nil } func GenerateRandomString(n int) (string, error) { const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ret := make([]byte, n) for i := 0; i < n; i++ { num, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters)))) if err != nil { return "", err } ret[i] = letters[num.Int64()] } return string(ret), nil }