freealberta/map/app/middleware/rateLimiter.js
2025-08-16 00:04:05 -06:00

88 lines
2.8 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, // Increased from 100 to 300 to accommodate auto-refresh and multiple users
keyGenerator,
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.'
});
module.exports = {
apiLimiter,
strictLimiter,
authLimiter,
tempUserLimiter,
conditionalTempLimiter,
adminLimiter
};