From f5f96e6f9ff9a5eafc7738e13b8c5120aedafd39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20=C4=B0pek?= Date: Fri, 20 Mar 2026 22:32:26 +0300 Subject: [PATCH] feat(rate-limit): add environment variable to disable rate limiting for local testing --- .env.example | 3 +++ lib/rate-limit.ts | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/.env.example b/.env.example index c899c45..c926e43 100644 --- a/.env.example +++ b/.env.example @@ -59,6 +59,9 @@ SMTP_FROM="noreply@openframe.dev" # ============================================================================ # development | production | test NODE_ENV="development" +# Disable all app-level rate limiting for local testing. Leave unset to keep rate limiting enabled. +# Accepted truthy values: "true", "1", "yes", "on" +# DISABLE_RATE_LIMIT="true" # Admin emails for accessing the /admin panel (comma separated list) # e.g., "yusuf@example.com,admin@example.com" ADMIN_EMAILS="" diff --git a/lib/rate-limit.ts b/lib/rate-limit.ts index 2b2109c..b1b113a 100644 --- a/lib/rate-limit.ts +++ b/lib/rate-limit.ts @@ -18,6 +18,13 @@ interface RateLimitResult { resetAt: Date; } +const TRUTHY_ENV_VALUES = new Set(['1', 'true', 'yes', 'on']); + +function isRateLimitDisabled(): boolean { + const rawValue = process.env.DISABLE_RATE_LIMIT?.trim().toLowerCase(); + return rawValue !== undefined && TRUTHY_ENV_VALUES.has(rawValue); +} + // Industry-standard rate limit defaults per action export const RATE_LIMIT_CONFIGS: Record = { // Auth — strict to prevent brute force / credential stuffing @@ -73,6 +80,15 @@ export async function checkRateLimit( config?: RateLimitConfig ): Promise { const { windowMs, maxRequests } = config || RATE_LIMIT_CONFIGS[action] || RATE_LIMIT_CONFIGS.api; + + if (isRateLimitDisabled()) { + return { + allowed: true, + remaining: maxRequests, + resetAt: new Date(Date.now() + windowMs), + }; + } + const windowSeconds = Math.floor(windowMs / 1000); // Validate inputs before passing to query — defence in depth.