- The mapstructure library is no longer needed for direct duration parsing since we now store TTLs as string durations (e.g., "15m", "168h") and parse them on demand via helper methods. - This allows more flexible duration formats in configuration and moves the parsing responsibility to the JWT config struct itself.
85 lines
2.0 KiB
Go
85 lines
2.0 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"`
|
|
Path string `mapstructure:"path"`
|
|
}
|
|
|
|
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 string `mapstructure:"access_ttl"`
|
|
RefreshTTL string `mapstructure:"refresh_ttl"`
|
|
}
|
|
|
|
func (j JWTConfig) AccessDuration() time.Duration {
|
|
d, _ := time.ParseDuration(j.AccessTTL)
|
|
return d
|
|
}
|
|
|
|
func (j JWTConfig) RefreshDuration() time.Duration {
|
|
d, _ := time.ParseDuration(j.RefreshTTL)
|
|
return d
|
|
}
|
|
|
|
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))
|
|
}
|
|
|
|
if c.Database.Path == "" {
|
|
errs = append(errs, errors.New("database.path: must not be empty"))
|
|
}
|
|
|
|
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 _, err := time.ParseDuration(c.JWT.AccessTTL); err != nil {
|
|
errs = append(errs, fmt.Errorf("jwt.access_ttl: %w", err))
|
|
}
|
|
|
|
if _, err := time.ParseDuration(c.JWT.RefreshTTL); err != nil {
|
|
errs = append(errs, fmt.Errorf("jwt.refresh_ttl: %w", err))
|
|
}
|
|
|
|
return errors.Join(errs...)
|
|
}
|