Files
mygo/internal/config/config.go
Huxley f4212cddf0 Change config JWT duration fields to time.Duration
- fix: The AccessTTL and RefreshTTL fields in JWTConfig now use
  time.Duration type directly instead of string with ParseDuration
  methods. The config validation now checks for positive durations
  rather than parsing strings.
2026-04-29 17:02:49 +08:00

107 lines
2.9 KiB
Go

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...)
}