package config import ( "fmt" "os" "gopkg.in/yaml.v3" ) // Config holds application configuration type Config struct { Server *Server `yaml:"server"` Database *Database `yaml:"database"` Auth *Auth `yaml:"auth"` Providers map[string]map[string]string `yaml:"providers"` Debug bool `yaml:"debug"` } 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("server configuration is required") } if c.Database == nil { return fmt.Errorf("database configuration is required") } if c.Auth == nil { return fmt.Errorf("auth configuration is required") } if c.Providers == nil { return fmt.Errorf("at least one provider configuration is required") } return nil } // Server holds server configuration type Server struct { Host string `yaml:"host"` Port int `yaml:"port"` Tls *TlsConfig `yaml:"tls"` } func (c *Server) UnmarshalYAML(unmarshal func(interface{}) error) error { type plain Server err := unmarshal((*plain)(c)) if err != nil { return err } if c.Host == "" { return fmt.Errorf("host is required") } if c.Port == 0 { c.Port = 443 } if c.Tls == nil { return fmt.Errorf("TLS configuration is required") } return nil } // TlsConfig holds TLS configuration type TlsConfig struct { Enabled bool `yaml:"enabled"` CertFile string `yaml:"cert_file"` KeyFile string `yaml:"key_file"` } 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.KeyFile == "") && c.Enabled { return fmt.Errorf("TLS cert file is required") } return nil } // Database holds database configuration type Database struct { Type string `yaml:"type"` Sql *Sql `yaml:"sql"` } func (c *Database) UnmarshalYAML(unmarshal func(interface{}) error) error { type plain Database err := unmarshal((*plain)(c)) if err != nil { return err } if c.Type == "" { return fmt.Errorf("database type is required") } if c.Type != "sql" && c.Type != "memory" { return fmt.Errorf("unsupported database type: %s", c.Type) } if c.Type == "sql" && c.Sql == nil { return fmt.Errorf("SQL database configuration is required") } return nil } // Sql holds SQL database configuration type Sql struct { Host string `yaml:"host"` Port int `yaml:"port"` Username string `yaml:"username"` Password string `yaml:"password"` Name string `yaml:"name"` } func (c *Sql) UnmarshalYAML(unmarshal func(interface{}) error) error { type plain Sql err := unmarshal((*plain)(c)) if err != nil { return err } if c.Host == "" { return fmt.Errorf("host is required") } if c.Port == 0 { c.Port = 5432 // Default PostgreSQL port } if c.Username == "" { return fmt.Errorf("username is required") } if c.Password == "" { return fmt.Errorf("password is required") } if c.Name == "" { return fmt.Errorf("database name is required") } return nil } // Auth holds authentication configuration type Auth struct { PrivateKey string `yaml:"private_key"` TokenDuration int `yaml:"token_duration"` CleanupInterval int `yaml:"cleanup_interval"` } func (c *Auth) UnmarshalYAML(unmarshal func(interface{}) error) error { type plain Auth err := unmarshal((*plain)(c)) if err != nil { return err } if c.PrivateKey == "" { return fmt.Errorf("private key is required") } if c.TokenDuration == 0 { c.TokenDuration = 3600 // Default to 1 hour } if c.CleanupInterval == 0 { c.CleanupInterval = 3600 // Default to 1 hour } return nil } func Load(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 }