added custom ban duration for bans, no duration is perma references #2

merge-requests/208/head
fatchan 5 years ago
parent 1009051949
commit 9d83260d22
  1. 36
      helpers/paramconverter.js
  2. 4
      models/forms/actionhandler.js
  3. 23
      models/forms/banposter.js
  4. 159
      package-lock.json
  5. 5
      package.json
  6. 4
      views/includes/actionfooter.pug
  7. 4
      views/includes/actionfooter_globalmanage.pug
  8. 4
      views/includes/actionfooter_manage.pug
  9. 4
      views/mixins/ban.pug

@ -3,7 +3,15 @@
const Mongo = require(__dirname+'/../db/db.js')
, allowedArrays = new Set(['checkedposts', 'globalcheckedposts', 'checkedbans', 'checkedbanners']) //only these can be arrays, since express bodyparser will output arrays
, trimFields = ['message', 'name', 'subject', 'email', 'password', 'default_name', 'report_reason', 'ban_reason'] //trim if we dont want filed with whitespace
, numberFields = ['reply_limit', 'max_files', 'thread_limit', 'thread', 'min_message_length']; //convert these to numbers before they hit our routes
, numberFields = ['reply_limit', 'max_files', 'thread_limit', 'thread', 'min_message_length'] //convert these to numbers before they hit our routes
, banDurationRegex = /^(?<years>[\d]+y)?(?<months>[\d]+m)?(?<weeks>[\d]+w)?(?<days>[\d]+d)?(?<hours>[\d]+h)?$/
, banDurations = { //times in millisecond, to be added to date for ban duration
'years': 31536000000,
'months': 2592000000,
'weeks': 604800000,
'days': 86400000,
'hours': 3600000
};
module.exports = (req, res, next) => {
@ -46,7 +54,31 @@ module.exports = (req, res, next) => {
req.body.globalcheckedposts = req.body.globalcheckedposts.map(Mongo.ObjectId)
}
//thread id
//ban duration convert to ban time in ms
if (req.body.ban_duration) {
const matches = req.body.ban_duration.match(banDurationRegex);
if (matches && matches.groups) {
const groups = matches.groups;
let banDuration = 0;
const groupKeys = Object.keys(groups);
for (let i = 0; i < groupKeys.length; i++) {
const key = groupKeys[i];
if (!groups[key]) {
continue;
}
const mult = +groups[key].substring(0,groups[key].length-1); //remove the d, m, y, etc from end of the value
if (Number.isSafeInteger(mult) //if the multiplier is safe int
&& Number.isSafeInteger(mult*banDurations[key]) //and multiplying it is safe int
&& Number.isSafeInteger((mult*banDurations[key])+banDuration)) { //and adding it to the total is safe
banDuration += mult*banDurations[key];
}
}
req.body.ban_duration = banDuration;
} else {
req.body.ban_duration = null;
}
}
if (req.params.id) {
req.params.id = +req.params.id;
}

@ -50,13 +50,13 @@ module.exports = async (req, res, next) => {
try {
// if getting global banned, board ban doesnt matter
if (req.body.global_ban) {
const { message, action, query } = await banPoster(req, res, next, null, res.locals.posts);
const { message, action, query } = await banPoster(req, res, next);
if (action) {
combinedQuery[action] = { ...combinedQuery[action], ...query}
}
messages.push(message);
} else if (req.body.ban) {
const { message, action, query } = await banPoster(req, res, next, req.params.board, res.locals.posts);
const { message, action, query } = await banPoster(req, res, next);
if (action) {
combinedQuery[action] = { ...combinedQuery[action], ...query}
}

@ -2,27 +2,32 @@
const Bans = require(__dirname+'/../../db/bans.js')
module.exports = async (req, res, next, board, posts) => {
module.exports = async (req, res, next) => {
const bans = posts.map(post => {
const banDate = new Date();
const banExpiry = new Date(req.body.ban_duration ? banDate.getTime() + req.body.ban_duration : 8640000000000000);
const banReason = req.body.ban_reason || 'No reason specified';
const banBoard = req.body.global_ban ? null : req.params.board;
const bans = res.locals.posts.map(post => {
return {
'ip': post.ip,
'reason': req.body.ban_reason || 'No reason specified',
'board': board,
'reason': banReason,
'board': banBoard,
'post': req.body.preserve_post ? post : null,
'issuer': req.session.user.username,
'date': new Date(),
'expireAt': new Date((new Date).getTime() + (72*1000*60*60)) // 72h ban
'date': banDate,
'expireAt': banExpiry
}
});
const bannedIps = await Bans.insertMany(bans).then(result => result.insertedCount);
const numBans = await Bans.insertMany(bans).then(result => result.insertedCount);
return {
message:`Banned ${bannedIps} ips`,
message: `Added ${numBans} bans`,
action:'$set',
query: {
'banmessage': req.body.ban_reason || ''
'banmessage': req.body.ban_reason || null
}
};

159
package-lock.json generated

@ -624,14 +624,6 @@
}
}
},
"basic-auth": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
"integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
"requires": {
"safe-buffer": "5.1.2"
}
},
"bcrypt": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-3.0.6.tgz",
@ -800,11 +792,6 @@
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
"integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
},
"camelize": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
"integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
},
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
@ -1158,11 +1145,6 @@
"safe-buffer": "5.1.2"
}
},
"content-security-policy-builder": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-2.0.0.tgz",
"integrity": "sha512-j+Nhmj1yfZAikJLImCvPJFE29x/UuBi+/MWqggGGc515JKaZrjuei2RhULJmy0MsstW3E3htl002bwmBNMKr7w=="
},
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
@ -1271,11 +1253,6 @@
"assert-plus": "^1.0.0"
}
},
"dasherize": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz",
"integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg="
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@ -1459,11 +1436,6 @@
}
}
},
"dns-prefetch-control": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz",
"integrity": "sha1-YN20V3dOF48flBXwyrsOhbCzALI="
},
"doctypes": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz",
@ -1500,11 +1472,6 @@
"domelementtype": "1"
}
},
"dont-sniff-mimetype": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz",
"integrity": "sha1-WTKJDcn04vGeXrAqIAJuXl78j1g="
},
"duplexify": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
@ -1720,11 +1687,6 @@
"homedir-polyfill": "^1.0.1"
}
},
"expect-ct": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/expect-ct/-/expect-ct-0.2.0.tgz",
"integrity": "sha512-6SK3MG/Bbhm8MsgyJAylg+ucIOU71/FzyFalcfu5nY19dH8y/z0tBJU0wrNBXD4B27EoQtqPF/9wqH0iYAd04g=="
},
"express": {
"version": "4.17.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
@ -1934,11 +1896,6 @@
"dev": true,
"optional": true
},
"feature-policy": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.3.0.tgz",
"integrity": "sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ=="
},
"fill-range": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
@ -2110,11 +2067,6 @@
"map-cache": "^0.2.2"
}
},
"frameguard": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.1.0.tgz",
"integrity": "sha512-TxgSKM+7LTA6sidjOiSZK9wxY0ffMPY3Wta//MqwmX0nZuEHc8QrkV8Fh3ZhMJeiH+Uyh/tcaarImRy8u77O7g=="
},
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
@ -3174,56 +3126,6 @@
}
}
},
"helmet": {
"version": "3.18.0",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-3.18.0.tgz",
"integrity": "sha512-TsKlGE5UVkV0NiQ4PllV9EVfZklPjyzcMEMjWlyI/8S6epqgRT+4s4GHVgc25x0TixsKvp3L7c91HQQt5l0+QA==",
"requires": {
"depd": "2.0.0",
"dns-prefetch-control": "0.1.0",
"dont-sniff-mimetype": "1.0.0",
"expect-ct": "0.2.0",
"feature-policy": "0.3.0",
"frameguard": "3.1.0",
"helmet-crossdomain": "0.3.0",
"helmet-csp": "2.7.1",
"hide-powered-by": "1.0.0",
"hpkp": "2.0.0",
"hsts": "2.2.0",
"ienoopen": "1.1.0",
"nocache": "2.1.0",
"referrer-policy": "1.2.0",
"x-xss-protection": "1.1.0"
},
"dependencies": {
"depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
}
}
},
"helmet-crossdomain": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/helmet-crossdomain/-/helmet-crossdomain-0.3.0.tgz",
"integrity": "sha512-YiXhj0E35nC4Na5EPE4mTfoXMf9JTGpN4OtB4aLqShKuH9d2HNaJX5MQoglO6STVka0uMsHyG5lCut5Kzsy7Lg=="
},
"helmet-csp": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.7.1.tgz",
"integrity": "sha512-sCHwywg4daQ2mY0YYwXSZRsgcCeerUwxMwNixGA7aMLkVmPTYBl7gJoZDHOZyXkqPrtuDT3s2B1A+RLI7WxSdQ==",
"requires": {
"camelize": "1.0.0",
"content-security-policy-builder": "2.0.0",
"dasherize": "2.0.0",
"platform": "1.3.5"
}
},
"hide-powered-by": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz",
"integrity": "sha1-SoWtZYgfYoV/xwr3F0oRhNzM4ys="
},
"homedir-polyfill": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
@ -3239,26 +3141,6 @@
"integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
"dev": true
},
"hpkp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz",
"integrity": "sha1-EOFCJk52IVpdMMROxD3mTe5tFnI="
},
"hsts": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/hsts/-/hsts-2.2.0.tgz",
"integrity": "sha512-ToaTnQ2TbJkochoVcdXYm4HOCliNozlviNsg+X2XQLQvZNI/kCHR9rZxVYpJB3UPcHz80PgxRyWQ7PdU1r+VBQ==",
"requires": {
"depd": "2.0.0"
},
"dependencies": {
"depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
}
}
},
"htmlparser2": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
@ -3304,11 +3186,6 @@
"safer-buffer": ">= 2.1.2 < 3"
}
},
"ienoopen": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.1.0.tgz",
"integrity": "sha512-MFs36e/ca6ohEKtinTJ5VvAJ6oDRAYFdYXweUnGY9L9vcoqFOU4n2ZhmJ0C4z/cwGZ3YIQRSB3XZ1+ghZkY5NQ=="
},
"ignore-walk": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz",
@ -4139,18 +4016,6 @@
"require_optional": "~1.0.0"
}
},
"morgan": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz",
"integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==",
"requires": {
"basic-auth": "~2.0.0",
"debug": "2.6.9",
"depd": "~1.1.2",
"on-finished": "~2.3.0",
"on-headers": "~1.0.1"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@ -4230,11 +4095,6 @@
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
"dev": true
},
"nocache": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz",
"integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q=="
},
"node-pre-gyp": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz",
@ -4680,11 +4540,6 @@
"pinkie": "^2.0.0"
}
},
"platform": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz",
"integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q=="
},
"plugin-error": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz",
@ -5040,11 +4895,6 @@
"resolve": "^1.1.6"
}
},
"referrer-policy": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.2.0.tgz",
"integrity": "sha512-LgQJIuS6nAy1Jd88DCQRemyE3mS+ispwlqMk3b0yjZ257fI1v9c+/p6SD5gP5FGyXUIgrNOAfmyioHwZtYv2VA=="
},
"regenerator-runtime": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
@ -6140,7 +5990,9 @@
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
"dev": true,
"optional": true
},
"v8flags": {
"version": "3.1.3",
@ -6348,11 +6200,6 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"x-xss-protection": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.1.0.tgz",
"integrity": "sha512-rx3GzJlgEeZ08MIcDsU2vY2B1QEriUKJTSiNHHUIem6eg9pzVOr2TL3Y4Pd6TMAM5D5azGjcxqI62piITBDHVg=="
},
"xtend": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",

@ -16,13 +16,10 @@
"fluent-ffmpeg": "^2.1.2",
"fs": "0.0.1-security",
"fs-extra": "^7.0.1",
"helmet": "^3.18.0",
"mongodb": "^3.2.7",
"morgan": "^1.9.1",
"path": "^0.12.7",
"pug": "^2.0.3",
"sanitize-html": "^1.20.1",
"uuid": "^3.3.2"
"sanitize-html": "^1.20.1"
},
"devDependencies": {
"del": "^4.1.1",

@ -51,7 +51,9 @@ details.toggle-label
input.post-check(type='checkbox', name='preserve_post' value=1)
| Show Post In Ban
label
input#report(type='text', name='ban_reason', placeholder='ban reason' autocomplete='off')
input(type='text', name='ban_reason', placeholder='ban reason' autocomplete='off')
label
input(type='text', name='ban_duration', placeholder='ban duration e.g. 7d' autocomplete='off')
.actions
h4.no-m-p Captcha:
iframe.captcha(src='/captcha.html' width=200 height=110 scrolling='no')

@ -24,5 +24,7 @@ details.toggle-label
input.post-check(type='checkbox', name='preserve_post' value=1)
| Show Post In Ban
label
input#ban_reason(type='text', name='ban_reason', placeholder='ban reason' autocomplete='off')
input(type='text', name='ban_reason', placeholder='ban reason' autocomplete='off')
label
input(type='text', name='ban_duration', placeholder='ban duration e.g. 7d' autocomplete='off')
input(type='submit', value='submit')

@ -35,5 +35,7 @@ details.toggle-label
input.post-check(type='checkbox', name='preserve_post' value=1)
| Show Post In Ban
label
input#ban_reason(type='text', name='ban_reason', placeholder='ban reason' autocomplete='off')
input(type='text', name='ban_reason', placeholder='ban reason' autocomplete='off')
label
input(type='text', name='ban_duration', placeholder='ban duration e.g. 7d' autocomplete='off')
input(type='submit', value='submit')

@ -5,13 +5,15 @@ mixin ban(ban, showcheck)
if showcheck
input.post-check(type='checkbox', name='checkedbans[]' value=ban._id)
span
| You were banned
| Banned
if ban.board
| from #[a(href=`/${ban.board}/`) /#{ban.board}/]
else
| globally
| for: #{ban.reason}
div Issued by: #{ban.issuer}
//todo: hash ips
div Issued against: #{ban.ip}
div Banned: #{ban.date.toLocaleString()}
div Expires: #{ban.expireAt.toLocaleString()}
if ban.post

Loading…
Cancel
Save