128 lines
3.9 KiB
Go
128 lines
3.9 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// Config holds all configuration for the application
|
|
type Config struct {
|
|
Server ServerConfig `mapstructure:"server"`
|
|
Database DatabaseConfig `mapstructure:"database"`
|
|
JWT JWTConfig `mapstructure:"jwt"`
|
|
WeChat WeChatConfig `mapstructure:"wechat"`
|
|
}
|
|
|
|
// ServerConfig holds all server related configuration
|
|
type ServerConfig struct {
|
|
Host string `mapstructure:"host"`
|
|
Port int `mapstructure:"port"`
|
|
ReadTimeout time.Duration `mapstructure:"read_timeout"`
|
|
WriteTimeout time.Duration `mapstructure:"write_timeout"`
|
|
ShutdownTimeout time.Duration `mapstructure:"shutdown_timeout"`
|
|
Timeout time.Duration `mapstructure:"timeout"` // Request processing timeout
|
|
}
|
|
|
|
// DatabaseConfig holds all database related configuration
|
|
type DatabaseConfig struct {
|
|
Driver string `mapstructure:"driver"`
|
|
DSN string `mapstructure:"dsn"`
|
|
MaxOpenConns int `mapstructure:"max_open_conns"`
|
|
MaxIdleConns int `mapstructure:"max_idle_conns"`
|
|
MaxLifetime time.Duration `mapstructure:"max_lifetime"`
|
|
SkipMigration bool `mapstructure:"skip_migration"`
|
|
}
|
|
|
|
// JWTConfig holds all JWT related configuration
|
|
type JWTConfig struct {
|
|
Secret string `mapstructure:"secret"`
|
|
ExpireDelta time.Duration `mapstructure:"expire_delta"`
|
|
RefreshDelta time.Duration `mapstructure:"refresh_delta"`
|
|
SigningMethod string `mapstructure:"signing_method"`
|
|
Issuer string `mapstructure:"issuer"`
|
|
Audience string `mapstructure:"audience"`
|
|
}
|
|
|
|
// WeChatConfig holds all WeChat related configuration
|
|
type WeChatConfig struct {
|
|
AppID string `mapstructure:"app_id"`
|
|
AppSecret string `mapstructure:"app_secret"`
|
|
}
|
|
|
|
// LoadConfig loads the configuration from file and environment variables
|
|
func LoadConfig() (*Config, error) {
|
|
// Set default values
|
|
setDefaults()
|
|
|
|
// Read config file
|
|
if err := viper.ReadInConfig(); err != nil {
|
|
return nil, fmt.Errorf("failed to read config file: %w", err)
|
|
}
|
|
|
|
var config Config
|
|
if err := viper.Unmarshal(&config); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
|
|
}
|
|
|
|
// Validate config
|
|
if err := validateConfig(&config); err != nil {
|
|
return nil, fmt.Errorf("invalid configuration: %w", err)
|
|
}
|
|
|
|
return &config, nil
|
|
}
|
|
|
|
// setDefaults sets default values for configuration
|
|
func setDefaults() {
|
|
// Server defaults
|
|
viper.SetDefault("server.port", 8080)
|
|
viper.SetDefault("server.read_timeout", "15s")
|
|
viper.SetDefault("server.write_timeout", "15s")
|
|
viper.SetDefault("server.shutdown_timeout", "5s")
|
|
viper.SetDefault("server.timeout", "30s") // Default request processing timeout
|
|
|
|
// Database defaults
|
|
viper.SetDefault("database.driver", "sqlite3")
|
|
viper.SetDefault("database.max_open_conns", 25)
|
|
viper.SetDefault("database.max_idle_conns", 25)
|
|
viper.SetDefault("database.max_lifetime", "5m")
|
|
viper.SetDefault("database.skip_migration", false)
|
|
|
|
// JWT defaults
|
|
viper.SetDefault("jwt.expire_delta", "24h")
|
|
viper.SetDefault("jwt.refresh_delta", "168h") // 7 days
|
|
viper.SetDefault("jwt.signing_method", "HS256")
|
|
viper.SetDefault("jwt.issuer", "otpm")
|
|
viper.SetDefault("jwt.audience", "otpm-client")
|
|
}
|
|
|
|
// validateConfig validates the configuration
|
|
func validateConfig(config *Config) error {
|
|
if config.Server.Port < 1 || config.Server.Port > 65535 {
|
|
return fmt.Errorf("invalid port number: %d", config.Server.Port)
|
|
}
|
|
|
|
if config.Database.Driver == "" {
|
|
return fmt.Errorf("database driver is required")
|
|
}
|
|
|
|
if config.Database.DSN == "" {
|
|
return fmt.Errorf("database DSN is required")
|
|
}
|
|
|
|
if config.JWT.Secret == "" {
|
|
return fmt.Errorf("JWT secret is required")
|
|
}
|
|
|
|
if config.WeChat.AppID == "" {
|
|
return fmt.Errorf("WeChat AppID is required")
|
|
}
|
|
|
|
if config.WeChat.AppSecret == "" {
|
|
return fmt.Errorf("WeChat AppSecret is required")
|
|
}
|
|
|
|
return nil
|
|
}
|