diff --git a/cmd/server/main.go b/cmd/server/main.go index 65709ed..d8bb75c 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -67,7 +67,12 @@ func main() { e.Use(ratelimit.RequestTracingMiddleware(cfg)) // Rate limiter for auth endpoints - rateLimiter := ratelimit.NewRateLimiter(ratelimit.DefaultRateLimiterConfig()) + rateLimiterConfig := ratelimit.RateLimiterConfig{ + Enabled: cfg.RateLimitEnabled, + RequestsPerMinute: cfg.RequestsPerMinute, + CleanupInterval: 5 * time.Minute, + } + rateLimiter := ratelimit.NewRateLimiter(rateLimiterConfig) rateLimitMiddleware := ratelimit.RateLimiterMiddleware(rateLimiter) // Auth routes (no auth required, but rate limited) diff --git a/docker-compose.yml b/docker-compose.yml index 3b37876..3d26850 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -34,6 +34,9 @@ services: DATABASE_NAME: bookmann JWT_SECRET: ${JWT_SECRET} SERVER_PORT: 8765 + TEST_MODE: ${TEST_MODE:-false} + RATE_LIMIT_ENABLED: ${RATE_LIMIT_ENABLED:-true} + REQUESTS_PER_MINUTE: ${REQUESTS_PER_MINUTE:-10} ports: - "8765:8765" depends_on: diff --git a/internal/config/config.go b/internal/config/config.go index a99cd1f..310c8a7 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -3,29 +3,36 @@ package config import ( "fmt" "os" + "strconv" ) type Config struct { - ServerPort string - JWTSecret string - UploadPath string - DatabaseHost string - DatabasePort string - DatabaseUser string - DatabasePassword string - DatabaseName string + ServerPort string + JWTSecret string + UploadPath string + DatabaseHost string + DatabasePort string + DatabaseUser string + DatabasePassword string + DatabaseName string + TestMode bool + RateLimitEnabled bool + RequestsPerMinute int } func LoadConfig() *Config { return &Config{ - ServerPort: getEnv("SERVER_PORT", "8080"), - DatabaseHost: getEnv("DATABASE_HOST", "localhost"), - DatabasePort: getEnv("DATABASE_PORT", "5432"), - DatabaseUser: getEnv("DATABASE_USER", "postgres"), - DatabasePassword: getEnv("DATABASE_PASSWORD", "password"), - DatabaseName: getEnv("DATABASE_NAME", "bookmann"), - JWTSecret: getEnv("JWT_SECRET", "your-secret-key"), - UploadPath: getEnv("UPLOAD_PATH", "./uploads"), + ServerPort: getEnv("SERVER_PORT", "8080"), + DatabaseHost: getEnv("DATABASE_HOST", "localhost"), + DatabasePort: getEnv("DATABASE_PORT", "5432"), + DatabaseUser: getEnv("DATABASE_USER", "postgres"), + DatabasePassword: getEnv("DATABASE_PASSWORD", "password"), + DatabaseName: getEnv("DATABASE_NAME", "bookmann"), + JWTSecret: getEnv("JWT_SECRET", "your-secret-key"), + UploadPath: getEnv("UPLOAD_PATH", "./uploads"), + TestMode: getEnvBool("TEST_MODE", false), + RateLimitEnabled: getEnvBool("RATE_LIMIT_ENABLED", true), + RequestsPerMinute: getEnvInt("REQUESTS_PER_MINUTE", 10), } } @@ -40,3 +47,23 @@ func getEnv(key, defaultValue string) string { } return defaultValue } + +func getEnvBool(key string, defaultValue bool) bool { + if value := os.Getenv(key); value != "" { + boolVal, err := strconv.ParseBool(value) + if err == nil { + return boolVal + } + } + return defaultValue +} + +func getEnvInt(key string, defaultValue int) int { + if value := os.Getenv(key); value != "" { + intVal, err := strconv.Atoi(value) + if err == nil { + return intVal + } + } + return defaultValue +} diff --git a/internal/middleware/rate_limiter.go b/internal/middleware/rate_limiter.go index efc251c..d2f2069 100644 --- a/internal/middleware/rate_limiter.go +++ b/internal/middleware/rate_limiter.go @@ -10,6 +10,7 @@ import ( // RateLimiterConfig defines rate limiting configuration type RateLimiterConfig struct { + Enabled bool RequestsPerMinute int CleanupInterval time.Duration } @@ -17,6 +18,7 @@ type RateLimiterConfig struct { // DefaultRateLimiterConfig returns sensible defaults func DefaultRateLimiterConfig() RateLimiterConfig { return RateLimiterConfig{ + Enabled: true, RequestsPerMinute: 10, CleanupInterval: 5 * time.Minute, } @@ -98,6 +100,11 @@ func (rl *RateLimiter) Allow(ip string) bool { func RateLimiterMiddleware(rl *RateLimiter) echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { + // If rate limiting is disabled, skip checks + if !rl.config.Enabled { + return next(c) + } + // Get client IP ip := c.RealIP() if ip == "" {