feat: add configurable test mode and rate limiting

- Add TestMode, RateLimitEnabled, RequestsPerMinute to Config
- Add getEnvBool() and getEnvInt() helper functions
- Update rate limiter to support enabled/disabled state
- Pass test environment variables through docker-compose
- Configure rate limiter dynamically in main.go

This allows disabling rate limiting for integration testing while
maintaining security in production environments.
This commit is contained in:
2026-01-29 13:33:18 -05:00
parent ce0e448e58
commit 4b8cb58c84
4 changed files with 59 additions and 17 deletions
+6 -1
View File
@@ -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)
+3
View File
@@ -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:
+27
View File
@@ -3,6 +3,7 @@ package config
import (
"fmt"
"os"
"strconv"
)
type Config struct {
@@ -14,6 +15,9 @@ type Config struct {
DatabaseUser string
DatabasePassword string
DatabaseName string
TestMode bool
RateLimitEnabled bool
RequestsPerMinute int
}
func LoadConfig() *Config {
@@ -26,6 +30,9 @@ func LoadConfig() *Config {
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
}
+7
View File
@@ -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 == "" {