104 lines
3.2 KiB
JavaScript
104 lines
3.2 KiB
JavaScript
const rateLimit = require('express-rate-limit');
|
|
const config = require('../config');
|
|
|
|
// Helper to extract real IP with Cloudflare support
|
|
const keyGenerator = (req) => {
|
|
return req.headers['cf-connecting-ip'] ||
|
|
req.headers['x-forwarded-for']?.split(',')[0] ||
|
|
req.ip;
|
|
};
|
|
|
|
// General API rate limiter
|
|
const apiLimiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
max: 300, // Already increased
|
|
keyGenerator,
|
|
skip: (req) => {
|
|
// Skip rate limiting for authenticated users (or increase their limit)
|
|
return req.session?.authenticated === true;
|
|
},
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
trustProxy: true, // Explicitly trust proxy
|
|
message: 'Too many requests, please try again later.'
|
|
});
|
|
|
|
// Strict limiter for write operations
|
|
const strictLimiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000,
|
|
max: 20,
|
|
keyGenerator,
|
|
trustProxy: true, // Explicitly trust proxy
|
|
message: 'Too many write operations, please try again later.'
|
|
});
|
|
|
|
// Auth-specific limiter with admin bypass capability
|
|
const authLimiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000,
|
|
max: config.isProduction ? 30 : 50, // Increased from 10 to 30 for production
|
|
keyGenerator,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
trustProxy: true, // Explicitly trust proxy
|
|
message: 'Too many login attempts, please try again later.',
|
|
skipSuccessfulRequests: true,
|
|
skip: (req, res) => {
|
|
// Skip rate limiting for authenticated admin users on certain admin endpoints
|
|
return req.session?.isAdmin && req.path?.includes('/admin');
|
|
}
|
|
});
|
|
|
|
// Temp user rate limiter - stricter but allows for auto-refresh
|
|
const tempUserLimiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
max: 50, // Allow more requests to accommodate auto-refresh (every 30 seconds = ~30 requests per 15 min)
|
|
keyGenerator,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
trustProxy: true,
|
|
message: JSON.stringify({
|
|
success: false,
|
|
error: 'Rate limit exceeded for temporary account. Please contact an administrator for full access.',
|
|
isRateLimit: true
|
|
})
|
|
});
|
|
|
|
// Conditional rate limiter that applies stricter limits to temp users
|
|
const conditionalTempLimiter = (req, res, next) => {
|
|
if (req.session?.userType === 'temp') {
|
|
return tempUserLimiter(req, res, next);
|
|
}
|
|
return apiLimiter(req, res, next);
|
|
};
|
|
|
|
// Admin-friendly limiter for admin operations
|
|
const adminLimiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
max: 200, // High limit for admin operations
|
|
keyGenerator,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
trustProxy: true,
|
|
message: 'Rate limit exceeded for admin operations. Please try again later.'
|
|
});
|
|
|
|
// Public signup rate limiter - prevent spam signups
|
|
const publicSignupLimiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
max: 5, // Max 5 signups per IP per 15 minutes
|
|
keyGenerator,
|
|
message: 'Too many signup attempts. Please try again later.',
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
trustProxy: true
|
|
});
|
|
|
|
module.exports = {
|
|
apiLimiter,
|
|
strictLimiter,
|
|
authLimiter,
|
|
tempUserLimiter,
|
|
conditionalTempLimiter,
|
|
adminLimiter,
|
|
publicSignupLimiter
|
|
}; |