From f40f917bc5b15c6ae1446426defaf480f7b3f2cc Mon Sep 17 00:00:00 2001 From: Hikari Date: Fri, 20 Feb 2026 18:35:21 -0800 Subject: [PATCH] feat: implement tiered rate limiting with admin bypass Update rate limiting to be more lenient for authenticated users and bypass limits entirely for admin users: - Unauthenticated users: 100 requests/minute (original limit) - Authenticated users: 500 requests/minute (5x increase) - Admin users: No rate limits (completely bypassed via allowList) This allows the admin to interact with the library without restrictions whilst still protecting against abuse from unauthenticated users. Authenticated users get a much more generous limit for better user experience. Uses @fastify/rate-limit's allowList and dynamic max options to implement the tiered system. --- api/src/app/plugins/rate-limit.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/api/src/app/plugins/rate-limit.ts b/api/src/app/plugins/rate-limit.ts index 8343a14..bafdfbf 100644 --- a/api/src/app/plugins/rate-limit.ts +++ b/api/src/app/plugins/rate-limit.ts @@ -12,8 +12,27 @@ import { AuditAction, AuditCategory } from "@library/shared-types"; const rateLimitPlugin: FastifyPluginAsync = async (app) => { await app.register(fastifyRateLimit, { - max: 100, + max: async (request) => { + // Try to get user from JWT + try { + await request.jwtVerify(); + // Authenticated users get higher limits + return 500; + } catch { + // Unauthenticated users get lower limits + return 100; + } + }, timeWindow: "1 minute", + allowList: async (request) => { + // Bypass rate limiting entirely for admin users + try { + await request.jwtVerify(); + return request.user?.isAdmin === true; + } catch { + return false; + } + }, errorResponseBuilder: (request) => { // Log rate limit exceeded event AuditService.log({