diff --git a/gulp/res/js/captcha.js b/gulp/res/js/captcha.js index 28b1dcf7..222819df 100644 --- a/gulp/res/js/captcha.js +++ b/gulp/res/js/captcha.js @@ -29,7 +29,7 @@ class CaptchaController { clearTimeout(this.refreshTimer); //this wont throw an error if its null, so no need to check const captchaAge = this.captchaAge(); if (captchaAge != null) { - console.log('Refreshing captcha in ', 300000-captchaAge) + console.log('Refreshing captcha in ', 300000-captchaAge); this.refreshTimer = setTimeout(() => { this.refreshCaptchas(); }, 300000-captchaAge); diff --git a/gulp/res/js/forms.js b/gulp/res/js/forms.js index 7a97867f..7ed38bf9 100644 --- a/gulp/res/js/forms.js +++ b/gulp/res/js/forms.js @@ -31,11 +31,22 @@ async function videoThumbnail(file) { }); } -function doModal(data, postcallback) { +function doModal(data, postcallback, loadcallback) { try { const modalHtml = modal({ modal: data }); let checkInterval; document.body.insertAdjacentHTML('afterbegin', modalHtml); + const modals = document.getElementsByClassName('modal'); + const modalBgs = document.getElementsByClassName('modal-bg'); + if (modals.length > 1) { + const latestModalIndex = parseInt(document.defaultView.getComputedStyle(modals[1], null).getPropertyValue('z-index')); + //from appeals, or holding enter. make sure they show up above the previous modal + modals[0].style.zIndex = latestModalIndex + 3; + modalBgs[0].style.zIndex = latestModalIndex + 2; + } + if (loadcallback != null) { + loadcallback(); + } document.getElementById('modalclose').onclick = () => { removeModal(); clearInterval(checkInterval); @@ -46,9 +57,9 @@ function doModal(data, postcallback) { }; const modalframe = document.getElementById('modalframe'); if (modalframe) { - //if theres a modal frame and user has default theme, style it if (localStorage.getItem('theme') === 'default') { modalframe.onload = () => { + //if theres a modal frame and user has default theme, style it const currentTheme = document.head.querySelector('#theme').href; modalframe.contentDocument.styleSheets[1].ownerNode.href = currentTheme; } @@ -64,7 +75,7 @@ function doModal(data, postcallback) { } } } catch(e) { - console.error(e) + console.error(e); } } @@ -202,8 +213,7 @@ class postFormHandler { postData.set('captcha', captchaResponse); } } - if (this.banned - || this.minimal + if (this.minimal || (postData instanceof URLSearchParams && postData.get('edit') === '1')) { return true; } else { @@ -251,9 +261,7 @@ class postFormHandler { if (xhr.responseURL && xhr.responseURL !== `${location.origin}${this.form.getAttribute('action')}`) { window.location = xhr.responseURL; - return; - } else if (xhr.responseText) { - // + return; //edits } } else { if (json.postId) { @@ -278,11 +286,7 @@ class postFormHandler { forceUpdate(); } } - //dont reset on edit, keep the new values in there. todo: add exceptions/better handling for this situation - const formAction = this.form.getAttribute('action'); if (this.resetOnSubmit) { -//formAction !== '/forms/editpost' -//!formAction.endsWith('/settings')) { this.reset(); } } else { @@ -301,15 +305,32 @@ class postFormHandler { if (captcha) { captcha.dispatchEvent(new Event('click')); } + } else if (json.bans) { + doModal(json, null, () => { + const modalBanned = document.getElementById('modalbanned'); + const modalBanForm = modalBanned.querySelector('form'); + const modalAppealHandler = new postFormHandler(modalBanForm); + for (let modalFormElement of modalAppealHandler.form.elements) { + //for ease of appeal, pre-check all the bans in this case. + if (modalFormElement.type === 'checkbox') { + modalFormElement.checked = true; + } + } + const appealCaptcha = modalAppealHandler.captchaField; + if (appealCaptcha) { + captchaController.setupCaptchaField(appealCaptcha); + } + }); + } else { + doModal(json, () => { + this.formSubmit(e); + }); } - doModal(json, () => { - this.formSubmit(e); - }); } else { -//for bans, post form to show TODO: make modal support bans json and send dynamicresponse from it (but what about appeals, w/ captcha, etc?) - this.clearFiles(); //dont resubmit files - this.banned = true; - this.form.dispatchEvent(new Event('submit')); + doModal({ + 'title': 'Error', + 'message': 'Something broke' + }); } } this.submit.value = this.originalSubmitText; diff --git a/lib/middleware/permission/bancheck.js b/lib/middleware/permission/bancheck.js index 05ce5e21..6bc6cbb9 100644 --- a/lib/middleware/permission/bancheck.js +++ b/lib/middleware/permission/bancheck.js @@ -22,10 +22,12 @@ module.exports = async (req, res, next) => { if (bans && bans.length > 0) { const unseenBans = bans.filter(b => !b.seen).map(b => b._id); await Bans.markSeen(unseenBans); //mark bans as seen - bans.forEach(ban => ban.seen = true); //mark seen as true in memory for user viewed ban page - //todo: make a dynamicresponse, handle in frontend modal. - return res.status(403).render('ban', { - bans: bans, + bans.forEach(ban => { + ban.ip.raw = null; + ban.seen = true + }); //mark seen as true in memory for user viewed ban page + return dynamicResponse(req, res, 403, 'ban', { + bans, }); } diff --git a/models/forms/editpost.js b/models/forms/editpost.js index 0771c2c3..368eeb54 100644 --- a/models/forms/editpost.js +++ b/models/forms/editpost.js @@ -69,7 +69,8 @@ todo: handle some more situations }; const insertedResult = await Bans.insertOne(ban); ban._id = insertedResult.insertedId; - return res.status(403).render('ban', { + ban.ip.raw = null; //for dynamicresponse + return dynamicResponse(req, res, 403, 'ban', { bans: [ban] }); } diff --git a/models/forms/makepost.js b/models/forms/makepost.js index f3c8d654..a6b92dd0 100644 --- a/models/forms/makepost.js +++ b/models/forms/makepost.js @@ -163,7 +163,8 @@ ${res.locals.numFiles > 0 ? req.files.file.map(f => f.name+'|'+(f.phash || '')). }; const insertedResult = await Bans.insertOne(ban); ban._id = insertedResult.insertedId; - return res.status(403).render('ban', { + ban.ip.raw = null; //for dynamicresponse + return dynamicResponse(req, res, 403, 'ban', { bans: [ban] }); } diff --git a/views/includes/banform.pug b/views/includes/banform.pug index 8cfbdd08..20dc3fba 100644 --- a/views/includes/banform.pug +++ b/views/includes/banform.pug @@ -4,7 +4,7 @@ form.form-post(action=`/forms/appeal`, enctype='application/x-www-form-urlencode +ban(ban, true) - const allowAppeal = bans.filter(ban => ban.allowAppeal === true && !ban.appeal).length > 0; if allowAppeal === true - h4.no-m-p Appeal bans: + h4.no-m-p Appeal: .form-wrapper.flexleft.mt-10 input(type='hidden' name='_csrf' value=csrf) .row diff --git a/views/mixins/ban.pug b/views/mixins/ban.pug index ea3b36c5..54923f5b 100644 --- a/views/mixins/ban.pug +++ b/views/mixins/ban.pug @@ -35,7 +35,7 @@ mixin ban(ban, banpage) else | ⨯ td - if ban.allowAppeal + if ban.allowAppeal && !ban.appeal | ✓ else | ⨯ diff --git a/views/mixins/modal.pug b/views/mixins/modal.pug index 1fda4475..428b255a 100644 --- a/views/mixins/modal.pug +++ b/views/mixins/modal.pug @@ -1,9 +1,15 @@ +include ../mixins/ban.pug mixin modal(data) .modal-bg(style=data.hidden?'display:none':'') .modal(id=(data.settings ? 'settingsmodal' : '') style=data.hidden?'display:none':'') .row p.bold #{data.title} a.close.postform-style#modalclose × + if data.bans + h1.board-title Banned! + .row#modalbanned + - const bans = data.bans + include ../includes/banform.pug if data.message || data.messages || data.error || data.errors .row ul.nomarks