151 lines
3.8 KiB
JavaScript
151 lines
3.8 KiB
JavaScript
const rateLimit = require('express-rate-limit');
|
|
const logger = require('../config/logger');
|
|
|
|
/**
|
|
* Create a custom rate limit handler
|
|
*/
|
|
const createRateLimitHandler = (req, res) => {
|
|
logger.logSecurityEvent('Rate limit exceeded', req);
|
|
|
|
res.status(429).json({
|
|
status: 'error',
|
|
message: 'Too many requests from this IP, please try again later.',
|
|
retryAfter: res.getHeader('Retry-After')
|
|
});
|
|
};
|
|
|
|
/**
|
|
* General API rate limiter
|
|
* 100 requests per 15 minutes per IP
|
|
*/
|
|
const apiLimiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
max: 100, // Limit each IP to 100 requests per windowMs
|
|
message: 'Too many requests from this IP, please try again after 15 minutes',
|
|
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
|
|
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
|
|
handler: createRateLimitHandler,
|
|
skip: (req) => {
|
|
// Skip rate limiting for health check endpoint
|
|
return req.path === '/health';
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Strict rate limiter for authentication endpoints
|
|
* 5 requests per 15 minutes per IP
|
|
*/
|
|
const authLimiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
max: 5, // Limit each IP to 5 requests per windowMs
|
|
message: 'Too many authentication attempts, please try again after 15 minutes',
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
handler: createRateLimitHandler,
|
|
skipSuccessfulRequests: false // Count all requests, including successful ones
|
|
});
|
|
|
|
/**
|
|
* Rate limiter for login attempts
|
|
* More restrictive - 5 attempts per 15 minutes
|
|
*/
|
|
const loginLimiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000,
|
|
max: 5,
|
|
message: 'Too many login attempts, please try again after 15 minutes',
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
handler: createRateLimitHandler,
|
|
skipFailedRequests: false // Count both successful and failed attempts
|
|
});
|
|
|
|
/**
|
|
* Rate limiter for registration
|
|
* 3 registrations per hour per IP
|
|
*/
|
|
const registerLimiter = rateLimit({
|
|
windowMs: 60 * 60 * 1000, // 1 hour
|
|
max: 3,
|
|
message: 'Too many accounts created from this IP, please try again after an hour',
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
handler: createRateLimitHandler
|
|
});
|
|
|
|
/**
|
|
* Rate limiter for password reset
|
|
* 3 requests per hour per IP
|
|
*/
|
|
const passwordResetLimiter = rateLimit({
|
|
windowMs: 60 * 60 * 1000,
|
|
max: 3,
|
|
message: 'Too many password reset attempts, please try again after an hour',
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
handler: createRateLimitHandler
|
|
});
|
|
|
|
/**
|
|
* Rate limiter for quiz creation
|
|
* 30 quizzes per hour per user
|
|
*/
|
|
const quizLimiter = rateLimit({
|
|
windowMs: 60 * 60 * 1000,
|
|
max: 30,
|
|
message: 'Too many quizzes started, please try again later',
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
handler: createRateLimitHandler
|
|
});
|
|
|
|
/**
|
|
* Rate limiter for admin operations
|
|
* 100 requests per 15 minutes
|
|
*/
|
|
const adminLimiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000,
|
|
max: 100,
|
|
message: 'Too many admin requests, please try again later',
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
handler: createRateLimitHandler
|
|
});
|
|
|
|
/**
|
|
* Rate limiter for guest session creation
|
|
* 5 guest sessions per hour per IP
|
|
*/
|
|
const guestSessionLimiter = rateLimit({
|
|
windowMs: 60 * 60 * 1000,
|
|
max: 5,
|
|
message: 'Too many guest sessions created, please try again later',
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
handler: createRateLimitHandler
|
|
});
|
|
|
|
/**
|
|
* Rate limiter for API documentation
|
|
* Prevent abuse of documentation endpoint
|
|
*/
|
|
const docsLimiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000,
|
|
max: 50,
|
|
message: 'Too many requests to documentation, please try again later',
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
handler: createRateLimitHandler
|
|
});
|
|
|
|
module.exports = {
|
|
apiLimiter,
|
|
authLimiter,
|
|
loginLimiter,
|
|
registerLimiter,
|
|
passwordResetLimiter,
|
|
quizLimiter,
|
|
adminLimiter,
|
|
guestSessionLimiter,
|
|
docsLimiter
|
|
};
|