- Move ci-test.sh and setup.sh to scripts/ - Trim docs/src/zig-cli.md to current structure - Replace hardcoded secrets with placeholders in configs - Update .gitignore to block .env*, secrets/, keys, build artifacts - Slim README.md to reflect current CLI/TUI split - Add cleanup trap to ci-test.sh - Ensure no secrets are committed
149 lines
3.8 KiB
Go
149 lines
3.8 KiB
Go
package api
|
|
|
|
import (
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/jfraeys/fetch_ml/internal/auth"
|
|
"github.com/jfraeys/fetch_ml/internal/config"
|
|
"github.com/jfraeys/fetch_ml/internal/logging"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// ServerConfig holds all server configuration
|
|
type ServerConfig struct {
|
|
BasePath string `yaml:"base_path"`
|
|
Auth auth.Config `yaml:"auth"`
|
|
Server ServerSection `yaml:"server"`
|
|
Security SecurityConfig `yaml:"security"`
|
|
Redis RedisConfig `yaml:"redis"`
|
|
Database DatabaseConfig `yaml:"database"`
|
|
Logging logging.Config `yaml:"logging"`
|
|
Resources config.ResourceConfig `yaml:"resources"`
|
|
}
|
|
|
|
// ServerSection holds server-specific configuration
|
|
type ServerSection struct {
|
|
Address string `yaml:"address"`
|
|
TLS TLSConfig `yaml:"tls"`
|
|
}
|
|
|
|
// TLSConfig holds TLS configuration
|
|
type TLSConfig struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
CertFile string `yaml:"cert_file"`
|
|
KeyFile string `yaml:"key_file"`
|
|
}
|
|
|
|
// SecurityConfig holds security-related configuration
|
|
type SecurityConfig struct {
|
|
RateLimit RateLimitConfig `yaml:"rate_limit"`
|
|
IPWhitelist []string `yaml:"ip_whitelist"`
|
|
FailedLockout LockoutConfig `yaml:"failed_login_lockout"`
|
|
}
|
|
|
|
// RateLimitConfig holds rate limiting configuration
|
|
type RateLimitConfig struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
RequestsPerMinute int `yaml:"requests_per_minute"`
|
|
BurstSize int `yaml:"burst_size"`
|
|
}
|
|
|
|
// LockoutConfig holds failed login lockout configuration
|
|
type LockoutConfig struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
MaxAttempts int `yaml:"max_attempts"`
|
|
LockoutDuration string `yaml:"lockout_duration"`
|
|
}
|
|
|
|
// RedisConfig holds Redis connection configuration
|
|
type RedisConfig struct {
|
|
Addr string `yaml:"addr"`
|
|
Password string `yaml:"password"`
|
|
DB int `yaml:"db"`
|
|
URL string `yaml:"url"`
|
|
}
|
|
|
|
// DatabaseConfig holds database connection configuration
|
|
type DatabaseConfig struct {
|
|
Type string `yaml:"type"`
|
|
Connection string `yaml:"connection"`
|
|
Host string `yaml:"host"`
|
|
Port int `yaml:"port"`
|
|
Username string `yaml:"username"`
|
|
Password string `yaml:"password"`
|
|
Database string `yaml:"database"`
|
|
}
|
|
|
|
// LoadServerConfig loads and validates server configuration
|
|
func LoadServerConfig(path string) (*ServerConfig, error) {
|
|
resolvedConfig, err := config.ResolveConfigPath(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cfg, err := loadConfigFromFile(resolvedConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cfg.Resources.ApplyDefaults()
|
|
return cfg, nil
|
|
}
|
|
|
|
// loadConfigFromFile loads configuration from a YAML file
|
|
func loadConfigFromFile(path string) (*ServerConfig, error) {
|
|
data, err := secureFileRead(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var cfg ServerConfig
|
|
if err := yaml.Unmarshal(data, &cfg); err != nil {
|
|
return nil, err
|
|
}
|
|
return &cfg, nil
|
|
}
|
|
|
|
// secureFileRead safely reads a file
|
|
func secureFileRead(path string) ([]byte, error) {
|
|
// This would use the fileutil.SecureFileRead function
|
|
// For now, implement basic file reading
|
|
return os.ReadFile(path)
|
|
}
|
|
|
|
// EnsureLogDirectory creates the log directory if needed
|
|
func (c *ServerConfig) EnsureLogDirectory() error {
|
|
if c.Logging.File == "" {
|
|
return nil
|
|
}
|
|
|
|
logDir := filepath.Dir(c.Logging.File)
|
|
log.Printf("Creating log directory: %s", logDir)
|
|
return os.MkdirAll(logDir, 0750)
|
|
}
|
|
|
|
// BuildAuthConfig creates the auth configuration
|
|
func (c *ServerConfig) BuildAuthConfig() *auth.Config {
|
|
if !c.Auth.Enabled {
|
|
return nil
|
|
}
|
|
|
|
log.Printf("Authentication enabled with %d API keys", len(c.Auth.APIKeys))
|
|
return &c.Auth
|
|
}
|
|
|
|
// Validate performs basic configuration validation
|
|
func (c *ServerConfig) Validate() error {
|
|
// Add validation logic here
|
|
if c.Server.Address == "" {
|
|
c.Server.Address = ":8080"
|
|
}
|
|
|
|
if c.BasePath == "" {
|
|
c.BasePath = "/tmp/ml-experiments"
|
|
}
|
|
|
|
return nil
|
|
}
|