feat(auth): named rate limiters (skip in tests)

This commit is contained in:
2026-05-20 22:52:42 +02:00
parent 0b62aad7d8
commit c9d593984d
3 changed files with 50 additions and 0 deletions

28
package-lock.json generated
View File

@@ -3796,6 +3796,24 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/express-rate-limit": {
"version": "8.5.2",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.5.2.tgz",
"integrity": "sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==",
"license": "MIT",
"dependencies": {
"ip-address": "^10.2.0"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/express-rate-limit"
},
"peerDependencies": {
"express": ">= 4.11"
}
},
"node_modules/express/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -4309,6 +4327,15 @@
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"license": "ISC"
},
"node_modules/ip-address": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
"integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
"license": "MIT",
"engines": {
"node": ">= 12"
}
},
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -7907,6 +7934,7 @@
"cookie-parser": "^1.4.7",
"drizzle-orm": "^0.33.0",
"express": "^4.19.0",
"express-rate-limit": "^8.5.2",
"multer": "^1.4.5-lts.1",
"nodemailer": "^8.0.7",
"xlsx": "^0.18.5",

View File

@@ -22,6 +22,7 @@
"cookie-parser": "^1.4.7",
"drizzle-orm": "^0.33.0",
"express": "^4.19.0",
"express-rate-limit": "^8.5.2",
"multer": "^1.4.5-lts.1",
"nodemailer": "^8.0.7",
"xlsx": "^0.18.5",

View File

@@ -0,0 +1,21 @@
import rateLimit from 'express-rate-limit';
const fifteenMin = 15 * 60 * 1000;
function makeLimiter(max: number, codeMessage = 'Too many attempts, please try again later') {
return rateLimit({
windowMs: fifteenMin,
limit: max,
standardHeaders: 'draft-7',
legacyHeaders: false,
skip: () => process.env.NODE_ENV === 'test',
handler: (_req, res) => {
res.status(429).json({ error: { code: 'RATE_LIMITED', message: codeMessage } });
},
});
}
export const loginLimiter = makeLimiter(10);
export const registerLimiter = makeLimiter(5);
export const forgotPasswordLimiter = makeLimiter(5);
export const tokenLimiter = makeLimiter(20);