separate ratelimits from captchas

merge-requests/208/head
fatchan 5 years ago
parent c7cd5eebbc
commit 848cc07d9f
  1. 36
      db/captchas.js
  2. 37
      db/ratelimits.js
  3. 10
      gulpfile.js
  4. 7
      helpers/captcha/captchaverify.js
  5. 8
      models/pages/captcha.js
  6. 2
      server.js

@ -1,15 +1,11 @@
'use strict';
const Mongo = require(__dirname+'/db.js')
, db = Mongo.client.db('jschan')
, captcha = db.collection('captcha')
, ratelimit = db.collection('ratelimit')
, db = Mongo.client.db('jschan').collection('captcha');
module.exports = {
captcha,
ratelimit,
db,
findOne: (id) => {
return captcha.findOne({ '_id': id });
@ -29,34 +25,8 @@ module.exports = {
});
},
resetQuota: (ip) => {
return ratelimit.deleteOne({ '_id': ip });
},
incrmentQuota: (ip) => {
return ratelimit.findOneAndUpdate(
{
'_id': ip
},
{
'$inc': {
'sequence_value': 1
},
'$setOnInsert': {
'expireAt': new Date()
}
},
{
'upsert': true
}
).then(r => { return r.value ? r.value.sequence_value : 0 });
},
deleteAll: () => {
return Promise.all([
captcha.deleteMany({}),
ratelimit.deleteMany({})
]);
return captcha.deleteMany({});
},
}

@ -0,0 +1,37 @@
'use strict';
const Mongo = require(__dirname+'/db.js')
, db = Mongo.client.db('jschan').collection('ratelimit');
module.exports = {
db,
resetQuota: (ip) => {
return db.deleteOne({ '_id': ip });
},
incrmentQuota: (ip, amount) => {
return db.findOneAndUpdate(
{
'_id': ip
},
{
'$inc': {
'sequence_value': amount
},
'$setOnInsert': {
'expireAt': new Date()
}
},
{
'upsert': true
}
).then(r => { return r.value ? r.value.sequence_value : 0 });
},
deleteAll: () => {
return ratelimit.deleteMany({});
},
}

@ -27,12 +27,14 @@ async function wipe() {
, Posts = require(__dirname+'/db/posts.js')
, Bans = require(__dirname+'/db/bans.js')
, Captchas = require(__dirname+'/db/captchas.js')
, Ratelimits = require(__dirname+'/db/ratelimits.js')
, Accounts = require(__dirname+'/db/accounts.js')
, Files = require(__dirname+'/db/files.js');
//wipe db shit
await Promise.all([
Captchas.deleteAll(),
Ratelimits.deleteAll(),
Accounts.deleteAll(),
Posts.deleteAll(),
Boards.deleteAll(),
@ -85,13 +87,13 @@ async function wipe() {
//add indexes - should profiled and changed at some point if necessary
, Boards.db.createIndex({ips: 1, pph:1, sequence_value:1})
, Bans.db.dropIndexes()
, Captchas.captcha.dropIndexes()
, Captchas.ratelimit.dropIndexes()
, Captchas.db.dropIndexes()
, Ratelimits.db.dropIndexes()
, Posts.db.dropIndexes()
, Files.db.createIndex({ 'count': 1 })
, Bans.db.createIndex({ "expireAt": 1 }, { expireAfterSeconds: 0 }) //custom expiry, i.e. it will expire when current date > than this date
, Captchas.captcha.createIndex({ "expireAt": 1 }, { expireAfterSeconds: 300 }) //captchas valid for 5 minutes
, Captchas.ratelimit.createIndex({ "expireAt": 1 }, { expireAfterSeconds: 60 }) //per minute captcha ratelimit
, Captchas.db.createIndex({ "expireAt": 1 }, { expireAfterSeconds: 300 }) //captchas valid for 5 minutes
, Ratelimits.db.createIndex({ "expireAt": 1 }, { expireAfterSeconds: 60 }) //per minute captcha ratelimit
, Posts.db.createIndex({ 'postId': 1,'board': 1,})
, Posts.db.createIndex({ 'board': 1, 'thread': 1, 'bumped': -1 })
, Posts.db.createIndex({ 'board': 1, 'reports.0': 1 }, { 'partialFilterExpression': { 'reports.0': { '$exists': true } } })

@ -1,7 +1,8 @@
'use strict';
const Captchas = require(__dirname+'/../../db/captchas.js')
, Mongo = require(__dirname+'/../../db/db.js')
, Ratelimits = require(__dirname+'/../../db/ratelimits.js')
, { ObjectId } = require(__dirname+'/../../db/db.js')
, remove = require('fs-extra').remove
, uploadDirectory = require(__dirname+'/../files/uploadDirectory.js');
@ -37,7 +38,7 @@ module.exports = async (req, res, next) => {
// try to get the captcha from the DB
let captcha;
try {
const captchaMongoId = Mongo.ObjectId(captchaId);
const captchaMongoId = ObjectId(captchaId);
captcha = await Captchas.findOneAndDelete(captchaMongoId, input);
} catch (err) {
return next(err);
@ -54,7 +55,7 @@ module.exports = async (req, res, next) => {
//it was correct, so delete the file, the cookie and reset their quota
res.clearCookie('captchaid');
await Promise.all([
Captchas.resetQuota(res.locals.ip),
Ratelimits.resetQuota(res.locals.ip),
remove(`${uploadDirectory}captcha/${captchaId}.jpg`)
]);

@ -1,15 +1,15 @@
'use strict';
const Captchas = require(__dirname+'/../../db/captchas.js')
const { Captchas, Ratelimits } = require(__dirname+'/../../db/ratelimits.js')
, generateCaptcha = require(__dirname+'/../../helpers/captcha/captchagenerate.js');
module.exports = async (req, res, next) => {
let captchaId;
try {
const ratelimit = await Captchas.incrmentQuota(res.locals.ip);
if (ratelimit > 12) { // 12 per minute = 1 per 5 seconds within a minute (with burst)
return res.status(429).redirect(`/img/ratelimit.png`);
const ratelimit = await Ratelimits.incrmentQuota(res.locals.ip, 10);
if (ratelimit > 100) {
return res.status(429).redirect('/img/ratelimit.png');
}
const text = Math.random().toString(36).substr(2,6);
captchaId = await Captchas.insertOne(text).then(r => r.insertedId); //get id of document as filename and captchaid

@ -14,7 +14,7 @@ const express = require('express')
, configs = require(__dirname+'/configs/main.json')
, refererRegex = new RegExp(configs.refererRegex)
, Mongo = require(__dirname+'/db/db.js')
, { createHash, randomBytes } = require('crypto');
, { createHash } = require('crypto');
(async () => {

Loading…
Cancel
Save