package config import ( "errors" "fmt" "net" "time" ) type Config struct { Server ServerConfig `mapstructure:"server"` Database DatabaseConfig `mapstructure:"database"` Storage StorageConfig `mapstructure:"storage"` JWT JWTConfig `mapstructure:"jwt"` } type ServerConfig struct { Host string `mapstructure:"host"` Port int `mapstructure:"port"` } type DatabaseConfig struct { Driver string `mapstructure:"driver"` SQLite SQLiteConfig `mapstructure:"sqlite"` Postgres PostgresConfig `mapstructure:"postgres"` } type SQLiteConfig struct { Path string `mapstructure:"path"` } type PostgresConfig struct { Host string `mapstructure:"host"` Port int `mapstructure:"port"` User string `mapstructure:"user"` Password string `mapstructure:"password"` DBName string `mapstructure:"dbname"` SSLMode string `mapstructure:"sslmode"` } type StorageConfig struct { Driver string `mapstructure:"driver"` Local LocalStorageConfig `mapstructure:"local"` } type LocalStorageConfig struct { Path string `mapstructure:"path"` } type JWTConfig struct { Secret string `mapstructure:"secret"` AccessTTL time.Duration `mapstructure:"access_ttl"` RefreshTTL time.Duration `mapstructure:"refresh_ttl"` } func (c *Config) Validate() error { var errs []error if c.Server.Port < 1 || c.Server.Port > 65535 { errs = append(errs, fmt.Errorf("server.port: %d out of range [1, 65535]", c.Server.Port)) } if addr := net.ParseIP(c.Server.Host); c.Server.Host != "" && addr == nil { errs = append(errs, fmt.Errorf("server.host: %q is not a valid IP address", c.Server.Host)) } switch c.Database.Driver { case "sqlite3": if c.Database.SQLite.Path == "" { errs = append(errs, errors.New("database.sqlite.path: must not be empty")) } case "postgres": if c.Database.Postgres.Host == "" { errs = append(errs, errors.New("database.postgres.host: must not be empty")) } if c.Database.Postgres.Port < 1 || c.Database.Postgres.Port > 65535 { errs = append(errs, fmt.Errorf("database.postgres.port: %d out of range [1, 65535]", c.Database.Postgres.Port)) } if c.Database.Postgres.User == "" { errs = append(errs, errors.New("database.postgres.user: must not be empty")) } if c.Database.Postgres.DBName == "" { errs = append(errs, errors.New("database.postgres.dbname: must not be empty")) } default: errs = append(errs, fmt.Errorf("database.driver: %q is not supported (use sqlite3 or postgres)", c.Database.Driver)) } if c.Storage.Local.Path == "" { errs = append(errs, errors.New("storage.local.path: must not be empty")) } if c.JWT.Secret == "" { errs = append(errs, errors.New("jwt.secret: must not be empty")) } if c.JWT.AccessTTL <= 0 { errs = append(errs, errors.New("jwt.access_ttl: must be positive")) } if c.JWT.RefreshTTL <= 0 { errs = append(errs, errors.New("jwt.refresh_ttl: must be positive")) } return errors.Join(errs...) }