package config import ( "fmt" "os" "time" "github.com/pelletier/go-toml/v2" ) type Config struct { Server ServerConfig `toml:"server"` Web WebConfig `toml:"web"` Database DatabaseConfig `toml:"database"` Auth AuthConfig `toml:"auth"` WebAuthn WebAuthnConfig `toml:"webauthn"` Log LogConfig `toml:"log"` } type ServerConfig struct { ListenAddr string `toml:"listen_addr"` GRPCAddr string `toml:"grpc_addr"` TLSCert string `toml:"tls_cert"` TLSKey string `toml:"tls_key"` } type WebConfig struct { ListenAddr string `toml:"listen_addr"` BaseURL string `toml:"base_url"` } type DatabaseConfig struct { Path string `toml:"path"` } type AuthConfig struct { TokenTTL string `toml:"token_ttl"` Argon2Memory uint32 `toml:"argon2_memory"` Argon2Time uint32 `toml:"argon2_time"` Argon2Threads uint8 `toml:"argon2_threads"` } func (a AuthConfig) TokenDuration() (time.Duration, error) { return time.ParseDuration(a.TokenTTL) } type WebAuthnConfig struct { RPDisplayName string `toml:"rp_display_name"` RPID string `toml:"rp_id"` RPOrigins []string `toml:"rp_origins"` } type LogConfig struct { Level string `toml:"level"` } func Load(path string) (*Config, error) { data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("read config: %w", err) } var cfg Config if err := toml.Unmarshal(data, &cfg); err != nil { return nil, fmt.Errorf("parse config: %w", err) } if err := cfg.validate(); err != nil { return nil, fmt.Errorf("config validation: %w", err) } return &cfg, nil } func (c *Config) validate() error { if c.Database.Path == "" { return fmt.Errorf("database.path is required") } if c.Server.TLSCert == "" || c.Server.TLSKey == "" { return fmt.Errorf("server.tls_cert and server.tls_key are required") } return nil }