package config import ( "fmt" "os" "git.linuxforward.com/byom/byom-core/logger" "gopkg.in/yaml.v3" ) type Config struct { Server *Server `yaml:"server"` Database *Database `yaml:"database"` Log *Log `yaml:"log"` Jwt *Jwt `yaml:"jwt"` Smtp *Smtp `yaml:"smtp"` Oauth2 *Oauth2 `yaml:"oauth2"` Hook *Hook `yaml:"hook"` } func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { type plain Config err := unmarshal((*plain)(c)) if err != nil { return err } if c.Server == nil { return fmt.Errorf("api config is required") } return nil } type Server struct { ListeningPort int `yaml:"listening_port"` TlsConfig *TlsConfig `yaml:"tls"` Opts []string `yaml:"opts"` CorsOrigins []string `yaml:"cors_origins"` RequestTimeout int `yaml:"request_timeout"` // in seconds } func (c *Server) UnmarshalYAML(unmarshal func(interface{}) error) error { type plain Server err := unmarshal((*plain)(c)) if err != nil { return err } if c.ListeningPort == 0 { c.ListeningPort = 8443 } if c.TlsConfig == nil { return fmt.Errorf("tls is required") } if c.TlsConfig.Enabled && (c.CorsOrigins == nil || len(c.CorsOrigins) == 0) { return fmt.Errorf("cors_origins must be set when TLS is enabled") } return nil } type TlsConfig struct { Enabled bool `yaml:"enabled"` CertFile string `yaml:"cert"` KeyFile string `yaml:"key"` } func (c *TlsConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { type plain TlsConfig err := unmarshal((*plain)(c)) if err != nil { return err } if c.CertFile == "" && c.Enabled { return fmt.Errorf("tls cert is required") } if c.KeyFile == "" && c.Enabled { return fmt.Errorf("tls key is required") } return nil } type Smtp struct { Host string `yaml:"host"` Port int `yaml:"port"` User string `yaml:"user"` Pass string `yaml:"pass"` } func (c *Smtp) UnmarshalYAML(unmarshal func(interface{}) error) error { type plain Smtp err := unmarshal((*plain)(c)) if err != nil { return err } // if c.Host == "" { // return fmt.Errorf("smtp host is required") // } // if c.Port == 0 { // c.Port = 587 // } // if c.User == "" { // return fmt.Errorf("smtp user is required") // } // if c.Pass == "" { // return fmt.Errorf("smtp pass is required") // } return nil } type Database struct { Path string `yaml:"path"` LogMode bool `yaml:"log_mode"` MaxOpenConns int `yaml:"max_open_conns"` MaxIdleConns int `yaml:"max_idle_conns"` ConnMaxLifetime int `yaml:"conn_max_lifetime"` Pragma []string `yaml:"pragma"` } func (c *Database) UnmarshalYAML(unmarshal func(interface{}) error) error { type plain Database err := unmarshal((*plain)(c)) if err != nil { return err } if c.Path == "" { return fmt.Errorf("database path is required") } if c.MaxOpenConns == 0 { c.MaxOpenConns = 10 } if c.MaxIdleConns == 0 { c.MaxIdleConns = 5 } if c.ConnMaxLifetime == 0 { c.ConnMaxLifetime = 300 } return nil } type Jwt struct { JwtSecret string `yaml:"jwt_secret"` } func (c *Jwt) UnmarshalYAML(unmarshal func(interface{}) error) error { type plain Jwt err := unmarshal((*plain)(c)) if err != nil { return err } if c.JwtSecret == "" { return fmt.Errorf("jwt secret is required") } return nil } type Oauth2 struct { ClientID string `yaml:"client_id"` ClientSecret string `yaml:"client_secret"` RedirectURL string `yaml:"redirect_url"` AuthURL string `yaml:"auth_url"` TokenURL string `yaml:"token_url"` UserInfoURL string `yaml:"user_info_url"` } func (c *Oauth2) UnmarshalYAML(unmarshal func(interface{}) error) error { type plain Oauth2 err := unmarshal((*plain)(c)) if err != nil { return err } if c.ClientID == "" { return fmt.Errorf("client id is required") } if c.ClientSecret == "" { return fmt.Errorf("client secret is required") } if c.RedirectURL == "" { return fmt.Errorf("redirect url is required") } if c.AuthURL == "" { return fmt.Errorf("auth url is required") } if c.TokenURL == "" { return fmt.Errorf("token url is required") } if c.UserInfoURL == "" { return fmt.Errorf("user info url is required") } return nil } type Log struct { Level string `yaml:"level"` NoColor bool `yaml:"no_color"` ForceColors bool `yaml:"force_colors"` InJson bool `yaml:"in_json"` FilterComponents []string `yaml:"filter_components"` } func (c *Log) UnmarshalYAML(unmarshal func(interface{}) error) error { type plain Log err := unmarshal((*plain)(c)) if err != nil { return err } return logger.Configure(c.Level, c.NoColor, c.ForceColors, c.InJson) } type Hook struct { BaseURL string `yaml:"base_url"` Domain string `yaml:"domain"` SecretKey string `yaml:"secret_key"` } func ReadConfig(configPath string) (*Config, error) { cnf := &Config{} b, err := os.ReadFile(configPath) if err != nil { return nil, err } err = yaml.Unmarshal(b, cnf) if err != nil { return nil, err } return cnf, nil }