Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | 17x 17x 276x 17x 414x 1x 17x 1x 17x 49x 6x 6x 17x | /**
* Rate limiting middleware — per-user (uid) limits for API abuse prevention.
*
* Uses in-memory store (no external deps, fits Oracle free tier's 1GB RAM).
* Three tiers: general API, write-heavy routes, and sensitive operations.
*/
const { rateLimit } = require('express-rate-limit');
const log = require('../utils/log');
// Key by authenticated user ID (falls back to IP for unauthenticated requests)
const keyGenerator = (req) => req.auth?.uid || req.ip;
// General API rate limit: 200 requests per minute per user
// Admin users are exempt — the admin panel legitimately makes many parallel
// API calls (logs, alerts, economy, search) across multiple tabs.
const generalLimiter = rateLimit({
windowMs: 60 * 1000,
limit: 200,
standardHeaders: 'draft-7',
legacyHeaders: false,
keyGenerator,
validate: false,
skip: (req) => req.auth?.token?.admin === true,
handler: (req, res) => {
res.status(429).json({ error: 'Too many requests, please try again later' });
},
});
// Write-heavy routes (messages, gifts, gacha): 30 per minute per user
const writeLimiter = rateLimit({
windowMs: 60 * 1000,
limit: 30,
standardHeaders: 'draft-7',
legacyHeaders: false,
keyGenerator,
validate: false,
handler: (req, res) => {
res.status(429).json({ error: 'Too many requests, slow down' });
},
});
// Sensitive operations (appeals, reports, purchases): 5 per minute per user
// Admin users are exempt — admin panel tests legitimately create reports/appeals.
const sensitiveLimiter = rateLimit({
windowMs: 60 * 1000,
limit: 5,
standardHeaders: 'draft-7',
legacyHeaders: false,
keyGenerator,
validate: false,
skip: (req) => req.auth?.token?.admin === true,
handler: (req, res) => {
log.warn('rateLimit', 'Sensitive rate limit hit', {
uid: req.auth?.uid,
ip: req.ip,
path: req.originalUrl,
});
res.status(429).json({ error: 'Rate limit exceeded for this operation' });
},
});
module.exports = { generalLimiter, writeLimiter, sensitiveLimiter };
|