import { test } from "node:test"; import assert from "node:assert/strict"; import path from "node:path"; import { fileURLToPath } from "node:url"; import dotenv from "dotenv"; import getPool from "../lib/server/db"; import { ApiError } from "../lib/server/errors"; import { enforceAuthRateLimit, enforceUserWriteRateLimit } from "../lib/server/rate-limit"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const envLoaded = dotenv.config({ path: path.resolve(__dirname, "../../../.env") }); const hasDb = Boolean(process.env.DATABASE_URL); async function ensureRateLimitTable() { const pool = getPool(); await pool.query(` create table if not exists rate_limits( key text primary key, window_start timestamptz not null, count integer not null default 0, updated_at timestamptz not null default now() ) `); } test("auth rate limit blocks when threshold is exceeded", async t => { if (!hasDb) { t.skip("DATABASE_URL not set"); return; } if (envLoaded.error) t.diagnostic(String(envLoaded.error)); await ensureRateLimitTable(); const pool = getPool(); const marker = Date.now(); const ip = `test-ip-${marker}`; const identifier = `rate_limit_${marker}@example.com`; try { await enforceAuthRateLimit({ route: "login", ip, identifier, ipLimit: 1, identifierLimit: 1, windowMs: 60_000 }); await assert.rejects( () => enforceAuthRateLimit({ route: "login", ip, identifier, ipLimit: 1, identifierLimit: 1, windowMs: 60_000 }), (error: unknown) => error instanceof ApiError && error.code === "RATE_LIMITED" ); } finally { await pool.query("delete from rate_limits where key like $1 or key like $2", [ `auth:login:ip:${ip}%`, `auth:login:identifier:${identifier}%` ]); } }); test("user write rate limit blocks when threshold is exceeded", async t => { if (!hasDb) { t.skip("DATABASE_URL not set"); return; } if (envLoaded.error) t.diagnostic(String(envLoaded.error)); await ensureRateLimitTable(); const pool = getPool(); const userId = 987654; const scope = `test_scope_${Date.now()}`; try { await enforceUserWriteRateLimit({ userId, scope, limit: 1, windowMs: 60_000 }); await assert.rejects( () => enforceUserWriteRateLimit({ userId, scope, limit: 1, windowMs: 60_000 }), (error: unknown) => error instanceof ApiError && error.code === "RATE_LIMITED" ); } finally { await pool.query("delete from rate_limits where key = $1", [ `write:user:${userId}:scope:${scope}` ]); } });