start work on blockbypass

merge-requests/208/head
fatchan 4 years ago
parent 53144641c4
commit 84971cd274
  1. 8
      configs/main.js.example
  2. 24
      controllers/forms.js
  3. 3
      controllers/pages.js
  4. 35
      db/bypass.js
  5. 1
      db/index.js
  6. 15
      gulp/res/js/modal.js
  7. 13
      gulpfile.js
  8. 52
      helpers/checks/blockbypass.js
  9. 5
      helpers/checks/dnsbl.js
  10. 4
      helpers/tasks.js
  11. 22
      models/forms/blockbypass.js
  12. 16
      models/pages/blockbypass.js
  13. 1
      models/pages/index.js
  14. 10
      views/mixins/modal.pug
  15. 15
      views/pages/bypass.pug

@ -50,6 +50,14 @@ module.exports = {
cacheTime: 3600 //in seconds, idk whats a good value
},
//block bypasses
blockBypass: {
enabled: false,
expireAfterUses: 40, //however many (attempted) posts per block bypass captcha
expireAfterTime: 86400000, //expiry in ms regardless if the limit was reached, default 1 day
bypassDnsbl: false,
},
//cache templates in memory. disable only if editing templates and doing dev work
cacheTemplates: true,

@ -15,6 +15,7 @@ const express = require('express')
, csrf = require(__dirname+'/../helpers/checks/csrfmiddleware.js')
, sessionRefresh = require(__dirname+'/../helpers/sessionrefresh.js')
, dnsblCheck = require(__dirname+'/../helpers/checks/dnsbl.js')
, blockBypassCheck = require(__dirname+'/../helpers/checks/blockbypass.js')
, dynamicResponse = require(__dirname+'/../helpers/dynamic.js')
, uploadLimitFunction = (req, res, next) => {
return dynamicResponse(req, res, 413, 'message', {
@ -71,16 +72,21 @@ const express = require('express')
, globalSettingsController = require(__dirname+'/forms/globalsettings.js')
, createBoardController = require(__dirname+'/forms/create.js')
, makePostController = require(__dirname+'/forms/makepost.js')
, newcaptcha = require(__dirname+'/../models/forms/newcaptcha.js')
, newCaptcha = require(__dirname+'/../models/forms/newcaptcha.js')
, blockBypass = require(__dirname+'/../models/forms/blockbypass.js')
//make new post
router.post('/board/:board/post', dnsblCheck, sessionRefresh, Boards.exists, calcPerms, banCheck, postFiles, paramConverter, verifyCaptcha, numFiles, makePostController);
//router.post('/board/:board/modpost', dnsblCheck, sessionRefresh, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(3), postFiles, paramConverter, csrf, numFiles, makePostController); //mod post has token instead of captcha
router.post('/board/:board/post', sessionRefresh, Boards.exists, calcPerms, banCheck, postFiles,
paramConverter, verifyCaptcha, numFiles, blockBypassCheck, dnsblCheck, makePostController);
/*router.post('/board/:board/modpost', sessionRefresh, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(3), postFiles,
paramConverter, csrf, numFiles, blockBypassCheck, dnsblCheck, makePostController); */ //mod post has token instead of captcha
//post actions
router.post('/board/:board/actions', sessionRefresh, Boards.exists, calcPerms, banCheck, paramConverter, verifyCaptcha, actionController); //public, with captcha
router.post('/board/:board/modactions', sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(3), paramConverter, actionController); //board manage page
router.post('/global/actions', sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(1), paramConverter, globalActionController); //global manage page
//appeal ban
router.post('/appeal', sessionRefresh, paramConverter, verifyCaptcha, appealController);
//board management forms
router.post('/board/:board/transfer', sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(2), paramConverter, transferController);
@ -97,19 +103,17 @@ router.post('/global/deletenews', sessionRefresh, csrf, calcPerms, isLoggedIn, h
router.post('/global/editaccounts', sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(0), paramConverter, editAccountsController); //account editing
router.post('/global/settings', sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(0), paramConverter, globalSettingsController); //global settings
//create board
router.post('/create', sessionRefresh, isLoggedIn, verifyCaptcha, calcPerms, hasPerms(4), createBoardController);
//accounts
router.post('/login', loginController);
router.post('/register', verifyCaptcha, registerController);
router.post('/changepassword', verifyCaptcha, changePasswordController);
//appeal ban
router.post('/appeal', sessionRefresh, paramConverter, verifyCaptcha, appealController);
//create board
router.post('/create', sessionRefresh, isLoggedIn, verifyCaptcha, calcPerms, hasPerms(4), createBoardController);
//removes captcha cookie, for refreshing for noscript users
router.post('/newcaptcha', newcaptcha);
router.post('/newcaptcha', newCaptcha);
//solve captcha for block bypass
router.post('/blockbypass', verifyCaptcha, blockBypass);
module.exports = router;

@ -15,7 +15,7 @@ const express = require('express')
, { manageReports, manageBanners, manageSettings, manageBans } = require(__dirname+'/../models/pages/manage/')
, { globalManageSettings, globalManageReports, globalManageBans,
globalManageRecent, globalManageAccounts, globalManageNews, globalManageLogs } = require(__dirname+'/../models/pages/globalmanage/')
, { changePassword, home, register, login, logout, create,
, { changePassword, blockBypass, home, register, login, logout, create,
board, catalog, banners, randombanner, news, captchaPage,
captcha, thread, modlog, modloglist, account, boardlist } = require(__dirname+'/../models/pages/');
@ -61,6 +61,7 @@ router.get('/globalmanage/settings.html', sessionRefresh, isLoggedIn, calcPerms,
//captcha
router.get('/captcha', captcha); //get captcha image and cookie
router.get('/captcha.html', captchaPage); //iframed for noscript users
router.get('/bypass.html', blockBypass); //block bypass page
//accounts
router.get('/account.html', sessionRefresh, isLoggedIn, account); //page showing boards you are mod/owner of, links to password rese, logout, etc

@ -0,0 +1,35 @@
'use strict';
const Mongo = require(__dirname+'/db.js')
, { blockBypass } = require(__dirname+'/../configs/main.js')
, db = Mongo.client.db('jschan').collection('bypass');
module.exports = {
db,
checkBypass: (id) => {
return db.findOneAndUpdate({
'_id': id,
'uses': {
'$lte': blockBypass.expireAfterUses
}
}, {
'$inc': {
'uses': 1,
}
}).then(r => r.value);
},
getBypass: () => {
return db.insertOne({
'uses': 0,
'expireAt': new Date(Date.now() + blockBypass.expireAfterTime)
}).then(r => { return r.insertedId });
},
deleteAll: () => {
return db.deleteMany({});
},
}

@ -13,5 +13,6 @@ module.exports = {
News: require(__dirname+'/news.js'),
Ratelimits: require(__dirname+'/ratelimits.js'),
Modlogs: require(__dirname+'/modlogs.js'),
Bypass: require(__dirname+'/bypass.js'),
}

@ -4,9 +4,9 @@ var pug_has_own_property=Object.prototype.hasOwnProperty;
var pug_match_html=/["&<>]/;
function pug_style(r){if(!r)return"";if("object"==typeof r){var t="";for(var e in r)pug_has_own_property.call(r,e)&&(t=t+e+":"+r[e]+";");return t}return r+""}function modal(locals) {var pug_html = "", pug_mixins = {}, pug_interp;;var locals_for_with = (locals || {});(function (modal) {pug_mixins["modal"] = pug_interp = function(data){
var block = (this && this.block), attributes = (this && this.attributes) || {};
pug_html = pug_html + "\u003Cdiv" + (" class=\"modal-bg\""+pug_attr("style", pug_style(data.hidden?'display:none':''), true, false)) + "\u003E\u003C\u002Fdiv\u003E\u003Cdiv" + (" class=\"modal\""+pug_attr("style", pug_style(data.hidden?'display:none':''), true, false)) + "\u003E\u003Cdiv class=\"row\"\u003E\u003Cp class=\"bold\"\u003E" + (pug_escape(null == (pug_interp = data.title) ? "" : pug_interp)) + "\u003C\u002Fp\u003E\u003Ca class=\"close postform-style\" id=\"modalclose\"\u003EX\u003C\u002Fa\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E";
pug_html = pug_html + "\u003Cdiv" + (" class=\"modal-bg\""+pug_attr("style", pug_style(data.hidden?'display:none':''), true, false)) + "\u003E\u003C\u002Fdiv\u003E\u003Cdiv" + (" class=\"modal\""+pug_attr("style", pug_style(data.hidden?'display:none':''), true, false)) + "\u003E\u003Cdiv class=\"row\"\u003E\u003Cp class=\"bold\"\u003E" + (pug_escape(null == (pug_interp = data.title) ? "" : pug_interp)) + "\u003C\u002Fp\u003E\u003Ca class=\"close postform-style\" id=\"modalclose\"\u003EX\u003C\u002Fa\u003E\u003C\u002Fdiv\u003E";
if (data.message || data.messages || data.error || data.errors) {
pug_html = pug_html + "\u003Cul class=\"nomarks\"\u003E";
pug_html = pug_html + "\u003Cdiv class=\"row\"\u003E\u003Cul class=\"nomarks\"\u003E";
if (data.message) {
pug_html = pug_html + "\u003Cli\u003E" + (pug_escape(null == (pug_interp = data.message) ? "" : pug_interp)) + "\u003C\u002Fli\u003E";
}
@ -53,11 +53,14 @@ pug_html = pug_html + "\u003Cli\u003E" + (pug_escape(null == (pug_interp = error
}).call(this);
}
pug_html = pug_html + "\u003C\u002Ful\u003E";
pug_html = pug_html + "\u003C\u002Ful\u003E\u003C\u002Fdiv\u003E";
if (data.link) {
pug_html = pug_html + "\u003Cdiv class=\"row\"\u003E\u003Ca" + (pug_attr("href", data.link, true, false)+" target=\"_blank\"") + "\u003E" + (pug_escape(null == (pug_interp = data.link) ? "" : pug_interp)) + "\u003C\u002Fa\u003E\u003C\u002Fdiv\u003E";
}
}
else
if (data.settings) {
pug_html = pug_html + "\u003Cdiv class=\"form-wrapper flexleft mt-10\"\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ETheme\u003C\u002Fdiv\u003E\u003Cselect id=\"theme-setting\"\u003E\u003Coption value=\"default\"\u003Edefault\u003C\u002Foption\u003E";
pug_html = pug_html + "\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"form-wrapper flexleft mt-10\"\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ETheme\u003C\u002Fdiv\u003E\u003Cselect id=\"theme-setting\"\u003E\u003Coption value=\"default\"\u003Edefault\u003C\u002Foption\u003E";
// iterate data.settings.themes
;(function(){
var $$obj = data.settings.themes;
@ -95,8 +98,8 @@ pug_html = pug_html + "\u003Coption" + (pug_attr("value", theme, true, false)) +
}
}).call(this);
pug_html = pug_html + "\u003C\u002Fselect\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ELive posts\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"live-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ENotifications\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"notification-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003EScroll to new posts\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"scroll-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ELocal time\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"localtime-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003E24h time\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"24hour-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003EShow relative time\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"relative-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003EHide Thumbnails\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"hideimages-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ERecursive Post Hide\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"hiderecursive-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003EVideo\u002FAudio Volume\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"volume-setting\" type=\"range\" min=\"0\" max=\"100\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ELoop audio\u002Fvideo\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"loop-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003EUnlimit expand height\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"heightlimit-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ECrisp image rendering\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"crispimages-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003EPost Password\u003C\u002Fdiv\u003E\u003Cinput id=\"postpassword-setting\" type=\"password\" name=\"postpassword\"\u002F\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ECustom CSS\u003C\u002Fdiv\u003E\u003Ctextarea id=\"customcss-setting\"\u003E\u003C\u002Ftextarea\u003E\u003C\u002Fdiv\u003E\u003C\u002Fdiv\u003E";
pug_html = pug_html + "\u003C\u002Fselect\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ELive posts\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"live-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ENotifications\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"notification-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003EScroll to new posts\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"scroll-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ELocal time\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"localtime-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003E24h time\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"24hour-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003EShow relative time\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"relative-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003EHide Thumbnails\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"hideimages-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ERecursive Post Hide\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"hiderecursive-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003EVideo\u002FAudio Volume\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"volume-setting\" type=\"range\" min=\"0\" max=\"100\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ELoop audio\u002Fvideo\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"loop-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003EUnlimit expand height\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"heightlimit-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ECrisp image rendering\u003C\u002Fdiv\u003E\u003Clabel class=\"postform-style ph-5\"\u003E\u003Cinput id=\"crispimages-setting\" type=\"checkbox\"\u002F\u003E\u003C\u002Flabel\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003EPost Password\u003C\u002Fdiv\u003E\u003Cinput id=\"postpassword-setting\" type=\"password\" name=\"postpassword\"\u002F\u003E\u003C\u002Fdiv\u003E\u003Cdiv class=\"row\"\u003E\u003Cdiv class=\"label\"\u003ECustom CSS\u003C\u002Fdiv\u003E\u003Ctextarea id=\"customcss-setting\"\u003E\u003C\u002Ftextarea\u003E\u003C\u002Fdiv\u003E\u003C\u002Fdiv\u003E\u003C\u002Fdiv\u003E";
}
pug_html = pug_html + "\u003C\u002Fdiv\u003E\u003C\u002Fdiv\u003E";
pug_html = pug_html + "\u003C\u002Fdiv\u003E";
};
pug_mixins["modal"](modal);}.call(this,"modal" in locals_for_with?locals_for_with.modal:typeof modal!=="undefined"?modal:undefined));;return pug_html;}

@ -50,8 +50,9 @@ async function wipe() {
await db.createCollection('poststats');
await db.createCollection('ratelimit');
await db.createCollection('webring');
await db.createCollection('bypass');
const { Webring, Boards, Posts, Captchas, Ratelimits, Accounts, Files, Stats, Modlogs, Bans } = require(__dirname+'/db/');
const { Webring, Boards, Posts, Captchas, Ratelimits, Accounts, Files, Stats, Modlogs, Bans, Bypass } = require(__dirname+'/db/');
//wipe db shit
await Promise.all([
@ -65,7 +66,8 @@ async function wipe() {
Bans.deleteAll(),
Files.deleteAll(),
Stats.deleteAll(),
Modlogs.deleteAll()
Modlogs.deleteAll(),
Bypass.deleteAll(),
]);
//add indexes - should profiled and changed at some point if necessary
@ -84,9 +86,10 @@ async function wipe() {
await Modlogs.db.createIndex({ 'board': 1 })
await Files.db.createIndex({ 'count': 1 })
await Bans.db.createIndex({ 'ip': 1 , 'board': 1 })
await Bans.db.createIndex({ "expireAt": 1 }, { expireAfterSeconds: 0 }) //custom expiry, i.e. it will expire when current date > than this date
await Captchas.db.createIndex({ "expireAt": 1 }, { expireAfterSeconds: 300 }) //captchas valid for 5 minutes
await Ratelimits.db.createIndex({ "expireAt": 1 }, { expireAfterSeconds: 60 }) //per minute captcha ratelimit
await Bans.db.createIndex({ 'expireAt': 1 }, { expireAfterSeconds: 0 }) //custom expiry, i.e. it will expire when current date > than this date
await Bypass.db.createIndex({ 'expireAt': 1 }, { expireAfterSeconds: 0 })
await Captchas.db.createIndex({ 'expireAt': 1 }, { expireAfterSeconds: 300 }) //captchas valid for 5 minutes
await Ratelimits.db.createIndex({ 'expireAt': 1 }, { expireAfterSeconds: 60 }) //per minute captcha ratelimit
await Posts.db.createIndex({ 'postId': 1,'board': 1,})
await Posts.db.createIndex({ 'board': 1, 'thread': 1, 'bumped': -1 })
await Posts.db.createIndex({ 'board': 1, 'reports.0': 1 }, { 'partialFilterExpression': { 'reports.0': { '$exists': true } } })

@ -0,0 +1,52 @@
'use strict';
const { Bypass } = require(__dirname+'/../../db/')
, { ObjectId } = require(__dirname+'/../../db/db.js')
, { blockBypass } = require(__dirname+'/../../configs/main.js')
, dynamicResponse = require(__dirname+'/../dynamic.js');
module.exports = async (req, res, next) => {
if (!blockBypass.enabled) {
return next();
}
//check if blockbypass exists and right length
const bypassId = req.cookies.bypassid;
if (!bypassId || bypassId.length !== 24) {
return dynamicResponse(req, res, 403, 'message', {
'title': 'Forbidden',
'message': 'Missing or invalid block bypass',
'redirect': '/bypass.html',
'link': '/bypass.html',
});
}
//try to get bypass from db and make sure uses < maxUses
let bypass;
try {
const bypassMongoId = ObjectId(bypassId);
bypass = await Bypass.checkBypass(bypassMongoId);
} catch (err) {
return next(err);
}
if (!bypass) {
return dynamicResponse(req, res, 403, 'message', {
'title': 'Forbidden',
'message': 'Invalid or expired block bypass',
'redirect': '/bypass.html',
'link': '/bypass.html',
});
} else if (bypass.uses >= blockBypass.expireAfterUses) {
return dynamicResponse(req, res, 403, 'message', {
'title': 'Forbidden',
'message': 'Block bypass exceeded max uses',
'redirect': '/bypass.html',
'link': '/bypass.html',
});
}
return next();
}

@ -2,12 +2,13 @@
const cache = require(__dirname+'/../../redis.js')
, dynamicResponse = require(__dirname+'/../dynamic.js')
, { dnsbl } = require(__dirname+'/../../configs/main.js')
, { dnsbl, blockBypass } = require(__dirname+'/../../configs/main.js')
, { batch } = require('dnsbl');
module.exports = async (req, res, next) => {
if (dnsbl.enabled && dnsbl.blacklists.length > 0) {
if (dnsbl.enabled && dnsbl.blacklists.length > 0 //if dnsbl enabled and has more than 0 blacklists
&& (!res.locals.bypass || !blockBypass.bypassDnsbl)) { //and there is no valid block bypass, or they do not bypass dnsbl
const ip = req.headers['x-real-ip'] || req.connection.remoteAddress;
let isBlacklisted = await cache.get(`blacklisted:${ip}`);
if (isBlacklisted === null) { //not cached

@ -226,6 +226,10 @@ module.exports = {
return render('register.html', 'register.pug');
},
buildBypass: () => {
return render('bypass.html', 'bypass.pug');
},
buildCreate: () => {
return render('create.html', 'create.pug');
},

@ -0,0 +1,22 @@
'use strict';
const { Bypass } = require(__dirname+'/../../db/')
, { secureCookies, blockBypass } = require(__dirname+'/../../configs/main.js')
, production = process.env.NODE_ENV === 'production';
module.exports = async (req, res, next) => {
const bypassId = await Bypass.getBypass();
return res
.cookie('bypassid', bypassId.toString(), {
'maxAge': blockBypass.expireAfterTime,
'secure': production && secureCookies,
'sameSite': 'strict'
})
.render('message', {
'title': 'Success',
'message': 'Completed block bypass, you may go back and make your post.',
});
}

@ -0,0 +1,16 @@
'use strict';
const { buildBypass } = require(__dirname+'/../../helpers/tasks.js');
module.exports = async (req, res, next) => {
let html;
try {
html = await buildBypass();
} catch (err) {
return next(err);
}
return res.send(html);
}

@ -2,6 +2,7 @@
module.exports = {
changePassword: require(__dirname+'/changepassword.js'),
blockBypass: require(__dirname+'/blockbypass.js'),
register: require(__dirname+'/register.js'),
account: require(__dirname+'/account.js'),
home: require(__dirname+'/home.js'),

@ -4,8 +4,8 @@ mixin modal(data)
.row
p.bold #{data.title}
a.close.postform-style#modalclose X
.row
if data.message || data.messages || data.error || data.errors
if data.message || data.messages || data.error || data.errors
.row
ul.nomarks
if data.message
li #{data.message}
@ -17,7 +17,11 @@ mixin modal(data)
if data.errors
each error in data.errors
li #{error}
else if data.settings
if data.link
.row
a(href=data.link target='_blank') #{data.link}
else if data.settings
.row
.form-wrapper.flexleft.mt-10
.row
.label Theme

@ -0,0 +1,15 @@
extends ../layout.pug
block head
script(src='/js/all.js')
title Block Bypass
block content
h1.board-title Block Bypass
.form-wrapper.flex-center.mv-10
form.form-post(action='/forms/blockbypass' method='POST')
.row
.label Captcha
span.col
include ../includes/captcha.pug
input(type='submit', value='Submit')
Loading…
Cancel
Save