Skip to content

Commit afac2e9

Browse files
authored
Limit voting (#2094)
* Recent vote flooding has occurred. Limit this to curtail it. Closes #2093
1 parent 03fbe64 commit afac2e9

2 files changed

Lines changed: 37 additions & 1 deletion

File tree

models/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@
7272
"dev": 5,
7373
"pro": 15
7474
},
75+
"waitVoteCapMin": {
76+
"dev": 1,
77+
"pro": 30
78+
},
79+
7580

7681
"NOTE2": "Requires DB migration for changing below settings",
7782

routes.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,37 @@ var listSameQRateLimiter = rateLimit({
494494
}
495495
});
496496

497+
var waitVoteCapMin = isDev ? settings.waitVoteCapMin.dev: settings.waitVoteCapMin.pro;
498+
var voteCapLimiter = rateLimit({
499+
store: (isDev ? undefined : new MongoStore({
500+
uri: appendUrlLeaf(limiter, '/voteCapLimiter'),
501+
resetExpireDateOnChange: true, // Rolling
502+
expireTimeMs: waitVoteCapMin * 60 * 1000 // n minutes for mongo store
503+
})),
504+
windowMs: waitVoteCapMin * 60 * 1000, // n minutes for all stores
505+
max: 3, // limit each IP to n requests per windowMs for memory store or expireTimeMs for mongo store
506+
handler: function (aReq, aRes, aNext, aOptions) {
507+
statusCodePage(aReq, aRes, aNext, {
508+
statusCode: 429,
509+
statusMessage: 'Too many requests.',
510+
suppressNavigation: true,
511+
isCustomView: true,
512+
statusData: {
513+
isListView: true,
514+
retryAfter: waitAuthCapMin * 60 + (isDev ? fudgeSec : fudgeMin)
515+
}
516+
});
517+
},
518+
skip: function (aReq, aRes) {
519+
var authedUser = aReq.session.user;
520+
521+
if (authedUser && authedUser.isMod) {
522+
this.store.resetKey(this.keyGenerator);
523+
return true;
524+
}
525+
}
526+
});
527+
497528

498529
module.exports = function (aApp) {
499530
//--- Middleware
@@ -600,7 +631,7 @@ module.exports = function (aApp) {
600631
aApp.route('/mod/removed/:id').head(statusTMR).get(authentication.validateUser, moderation.removedItemPage);
601632

602633
// Vote route
603-
aApp.route(/^\/vote\/(scripts|libs)\/((.+?)(?:\/(.+))?)$/).post(authentication.validateUser, vote.vote);
634+
aApp.route(/^\/vote\/(scripts|libs)\/((.+?)(?:\/(.+))?)$/).post(voteCapLimiter, authentication.validateUser, vote.vote);
604635

605636
// Flag route
606637
aApp.route(/^\/flag\/(users|scripts|libs)\/((.+?)(?:\/(.+))?)$/).post(authentication.validateUser, flag.flag);

0 commit comments

Comments
 (0)