bunker-admin a77306fac2 Initial v2 commit: complete rebuild with unified API + React admin
Phase 1-14 complete:
- Unified Express.js API (TypeScript, Prisma ORM, PostgreSQL 16)
- React Admin GUI (Vite + Ant Design + Zustand)
- JWT auth with refresh tokens
- Influence: Campaigns, Representatives, Responses, Email Queue
- Map: Locations, Cuts, Shifts, Canvassing System
- NAR data import infrastructure (2025 format)
- Listmonk newsletter integration
- Landing page builder (GrapesJS)
- MkDocs + Code Server integration
- Volunteer portal with GPS tracking
- Monitoring stack (Prometheus, Grafana, Alertmanager)
- Pangolin tunnel integration

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 10:05:04 -07:00

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
};