diff --git a/controllers/forms.js b/controllers/forms.js index a727fd3f..946f6206 100644 --- a/controllers/forms.js +++ b/controllers/forms.js @@ -7,6 +7,7 @@ const express = require('express') , Trips = require(__dirname+'/../db-models/trips.js') , Bans = require(__dirname+'/../db-models/bans.js') , banPoster = require(__dirname+'/../models/forms/ban-poster.js') + , removeBans = require(__dirname+'/../models/forms/removebans.js') , makePost = require(__dirname+'/../models/forms/make-post.js') , deletePosts = require(__dirname+'/../models/forms/delete-post.js') , spoilerPosts = require(__dirname+'/../models/forms/spoiler-post.js') @@ -94,7 +95,7 @@ router.post('/register', (req, res, next) => { }); // make new post -router.post('/board/:board', Boards.exists, banCheck, numberConverter, async (req, res, next) => { +router.post('/board/:board/post', Boards.exists, banCheck, numberConverter, async (req, res, next) => { let numFiles = 0; if (req.files && req.files.file) { @@ -143,11 +144,11 @@ router.post('/board/:board', Boards.exists, banCheck, numberConverter, async (re }); //report/delete/spoiler/ban -router.post('/board/:board/posts', Boards.exists, banCheck, numberConverter, async (req, res, next) => { +router.post('/board/:board/actions', Boards.exists, banCheck, numberConverter, async (req, res, next) => { const errors = []; - if (!req.body.checked || req.body.checked.length === 0 || req.body.checked.length > 10) { + if (!req.body.checkedposts || req.body.checkedposts.length === 0 || req.body.checkedposts.length > 10) { errors.push('Must select 1-10 posts') } if (req.body.password && req.body.password.length > 50) { @@ -179,7 +180,7 @@ router.post('/board/:board/posts', Boards.exists, banCheck, numberConverter, asy }) } - const posts = await Posts.getPosts(req.params.board, req.body.checked, true); + const posts = await Posts.getPosts(req.params.board, req.body.checkedposts, true); if (!posts || posts.length === 0) { return res.status(404).render('message', { 'title': 'Not found', @@ -190,7 +191,6 @@ router.post('/board/:board/posts', Boards.exists, banCheck, numberConverter, asy const messages = []; try { - if (req.body.global_ban) { messages.push((await banPoster(req, res, next, null, posts))); } else if (req.body.ban) { @@ -209,7 +209,6 @@ router.post('/board/:board/posts', Boards.exists, banCheck, numberConverter, asy messages.push((await dismissReports(req, res, next))); } } - } catch (err) { //something not right if (err.status) { @@ -229,10 +228,43 @@ router.post('/board/:board/posts', Boards.exists, banCheck, numberConverter, asy }); //unban -router.post('/board/:board/bans', Boards.exists, banCheck, hasPerms, numberConverter, async (req, res, next) => { +router.post('/board/:board/unban', Boards.exists, banCheck, hasPerms, numberConverter, async (req, res, next) => { + + //keep this for later in case i add other options to unbans + const errors = []; - //TODO: unbans + if (!req.body.checkedbans || req.body.checkedbans.length === 0 || req.body.checkedbans.length > 10) { + errors.push('Must select 1-10 bans') + } + + if (errors.length > 0) { + return res.status(400).render('message', { + 'title': 'Bad request', + 'errors': errors, + 'redirect': `/${req.params.board}/manage` + }); + } + + const messages = []; + try { + messages.push((await removeBans(req, res, next))); + } catch (err) { + //something not right + if (err.status) { + // return out special error + return res.status(err.status).render('message', err.message); + } + //some other error, use regular error handler + return next(err); + } + + return res.render('message', { + 'title': 'Success', + 'messages': messages, + 'redirect': `/${req.params.board}/manage` + }); }); module.exports = router; + diff --git a/db-models/bans.js b/db-models/bans.js index 80163324..21ef11bb 100644 --- a/db-models/bans.js +++ b/db-models/bans.js @@ -1,3 +1,4 @@ + 'use strict'; const Mongo = require(__dirname+'/../helpers/db.js') @@ -16,12 +17,34 @@ module.exports = { }).toArray(); }, + findMany: (board, ids) => { + return db.find({ + '_id': { + '$in': ids + }, + 'board': board + }).toArray(); + }, + + getAll: () => { // for a global ban manage page maybe? still TODO + return db.find({}).toArray(); + }, + getBoardBans: (board) => { return db.find({ 'board': board, }).toArray(); }, + removeMany: (board, ids) => { + return db.deleteMany({ + 'board': board, + '_id': { + '$in': ids + } + }) + }, + insertOne: (ban) => { return db.insertOne(ban); }, diff --git a/helpers/number-converter.js b/helpers/number-converter.js index 149ce2f4..e103ba83 100644 --- a/helpers/number-converter.js +++ b/helpers/number-converter.js @@ -6,9 +6,9 @@ module.exports = (req, res, next) => { if (req.body.thread) { req.body.thread = +req.body.thread; } - if (req.body.checked) { - //syntax casts all string to number - req.body.checked = req.body.checked.map(Number); + if (req.body.checkedposts) { + //syntax tries to convert all string to number + req.body.checkedposts = req.body.checkedposts.map(Number); } //and for params diff --git a/models/forms/ban-poster.js b/models/forms/ban-poster.js index 2893d406..30ac18fe 100644 --- a/models/forms/ban-poster.js +++ b/models/forms/ban-poster.js @@ -33,12 +33,7 @@ module.exports = async (req, res, next, board, checkedPosts) => { } }); - let bannedIps = 0; - try { - bannedIps = await Bans.insertMany(bans).then(result => result.insertedCount); - } catch (err) { - return next(err); - } + const bannedIps = await Bans.insertMany(bans).then(result => result.insertedCount); return `Banned ${bannedIps} ips`; diff --git a/models/forms/delete-post.js b/models/forms/delete-post.js index 12510c1d..d4360fdb 100644 --- a/models/forms/delete-post.js +++ b/models/forms/delete-post.js @@ -47,12 +47,7 @@ module.exports = async (req, res, next, checkedPosts) => { const allPosts = posts.concat(threadPosts) //delete posts from DB - let deletedPosts = 0; - try { - deletedPosts = await Posts.deleteMany(req.params.board, allPosts.map(x => x.postId)).then(result => result.deletedCount); - } catch (err) { - return next(err); - } + const deletedPosts = await Posts.deleteMany(req.params.board, allPosts.map(x => x.postId)).then(result => result.deletedCount); //get filenames from all the posts let fileNames = []; diff --git a/models/forms/dismiss-report.js b/models/forms/dismiss-report.js index e8bb8e0c..15d3b147 100644 --- a/models/forms/dismiss-report.js +++ b/models/forms/dismiss-report.js @@ -16,11 +16,7 @@ module.exports = async (req, res, next) => { }; } - try { - await Posts.dismissReports(req.params.board, req.body.checked); - } catch (err) { - return next(err); - } + await Posts.dismissReports(req.params.board, req.body.checkedposts); return `Dismissed report(s) successfully`; diff --git a/models/forms/edit-post.js b/models/forms/edit-post.js index c256881c..6b293bc2 100644 --- a/models/forms/edit-post.js +++ b/models/forms/edit-post.js @@ -1,35 +1,9 @@ 'use strict'; -const uuidv4 = require('uuid/v4') - , path = require('path') - , Posts = require(__dirname+'/../../db-models/posts.js') +const Posts = require(__dirname+'/../../db-models/posts.js'); -module.exports = async (req, res, next, numFiles) => { +module.exports = async (req, res, next) => { - // get the post that we are trying to edit - let post; - try { - post = await Posts.getPost(req.params.board, req.body.id, true); - } catch (err) { - return next(err); - } - - if (!thread || thread.thread != null) { - throw { - 'status': 400, - 'message': { - 'title': 'Bad request', - 'message': 'Post does not exist.', - 'redirect': redirect - } - }; - } - - // sticky, lock, sage, spoiler, etc - for (let i = 0; i < req.body.actions.length; i++) { - //TODO - } - - return ``; + throw new Error('Not implemented'); } diff --git a/models/forms/make-post.js b/models/forms/make-post.js index 10cf8950..b5b16c41 100644 --- a/models/forms/make-post.js +++ b/models/forms/make-post.js @@ -8,7 +8,7 @@ const uuidv4 = require('uuid/v4') , uploadDirectory = require(__dirname+'/../../helpers/uploadDirectory.js') , Posts = require(__dirname+'/../../db-models/posts.js') , getTripCode = require(__dirname+'/../../helpers/tripcode.js') - , getQuotes = require(__dirname+'/../../helpers/quotes.js') + , linkQuotes = require(__dirname+'/../../helpers/quotes.js') , simpleMarkdown = require(__dirname+'/../../helpers/markdown.js') , sanitize = require('sanitize-html') , sanitizeOptions = { @@ -149,7 +149,7 @@ module.exports = async (req, res, next, numFiles) => { let message = req.body.message; if (message && message.length > 0) { message = simpleMarkdown(req.params.board, req.body.thread, message); - message = await getQuotes(req.params.board, message); + message = await linkQuotes(req.params.board, message); message = sanitize(message, sanitizeOptions); } diff --git a/models/forms/removebans.js b/models/forms/removebans.js new file mode 100644 index 00000000..9293729a --- /dev/null +++ b/models/forms/removebans.js @@ -0,0 +1,13 @@ +'use strict'; + +const Bans = require(__dirname+'/../../db-models/bans.js') + , { ObjectId } = require('mongodb'); + +module.exports = async (req, res, next) => { + + const banIds = req.body.checkedbans.map(ObjectId); + const removedBans = await Bans.removeMany(req.params.board, banIds).then(result => result.deletedCount); + + return `Removed ${removedBans} bans`; + +} diff --git a/models/forms/report-post.js b/models/forms/report-post.js index 2778bc67..b745d264 100644 --- a/models/forms/report-post.js +++ b/models/forms/report-post.js @@ -12,11 +12,7 @@ module.exports = async (req, res, next) => { } //push the report to all checked posts - try { - await Posts.reportMany(req.params.board, req.body.checked, report); - } catch (err) { - return next(err); - } + await Posts.reportMany(req.params.board, req.body.checkedposts, report); //hooray! return `Reported post(s) successfully` diff --git a/models/forms/spoiler-post.js b/models/forms/spoiler-post.js index 04f17d25..088fa714 100644 --- a/models/forms/spoiler-post.js +++ b/models/forms/spoiler-post.js @@ -46,7 +46,7 @@ module.exports = async (req, res, next, checkedPosts) => { } - //filter by not spoilered + //filter by not spoilered. maybe i add filters with optiins in the controller where it gets the posts? posts = posts.filter(post => { return !post.spoiler }); @@ -62,12 +62,7 @@ module.exports = async (req, res, next, checkedPosts) => { } // spoiler posts - let spoileredPosts = 0; - try { - spoileredPosts = await Posts.spoilerMany(req.params.board, posts.map(x => x.postId)).then(result => result.modifiedCount); - } catch (err) { - return next(err); - } + const spoileredPosts = await Posts.spoilerMany(req.params.board, posts.map(x => x.postId)).then(result => result.modifiedCount); //hooray! return `Spoilered ${spoileredPosts} posts` diff --git a/static/css/style.css b/static/css/style.css index 0b04cbdc..3a5b8679 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -200,7 +200,7 @@ input textarea { margin: 0; } -.post-container { +.post-container, .ban { margin: 1px; padding: 2px; background: #D6DAF0; diff --git a/views/includes/postform.pug b/views/includes/postform.pug index d304b6a1..4384dd1d 100644 --- a/views/includes/postform.pug +++ b/views/includes/postform.pug @@ -1,20 +1,20 @@ section.form-wrapper - form.form-post(action='/forms/board/'+board._id, enctype='multipart/form-data', method='POST') - + form.form-post(action=`/forms/board/${board._id}/post`, enctype='multipart/form-data', method='POST') + input(type='hidden' name='_csrf' value=csrf) input(type='hidden' name='thread' value=thread != null ? thread.postId : null) - + input#title(type='text', name='subject', placeholder='subject' autocomplete='off' maxlength='50') - + input#name(type='text', name='name', placeholder='name' autocomplete='off' maxlength='50') input#name(type='text', name='email', placeholder='email' autocomplete='off' maxlength='50') - + input#password(type='password', name='password', placeholder='post password' autocomplete='off' maxlength='50') - + textarea#message(name='message', rows='8', cols='50', placeholder='message' autocomplete='off' maxlength='2000') - + span input#file(type='file', name='file' multiple) label @@ -22,4 +22,3 @@ section.form-wrapper | Spoiler input(type='submit', value='submit') - diff --git a/views/mixins/ban.pug b/views/mixins/ban.pug index b506ff61..c6043836 100644 --- a/views/mixins/ban.pug +++ b/views/mixins/ban.pug @@ -1,16 +1,18 @@ include ./post.pug mixin ban(ban) - if ban.board - div Board: #[a(href=`/${ban.board}`) /#{ban.board}/] - else - div Global ban. - div Reason: #{ban.reason} - div Issuer: #{ban.issuer} - div Date: #{ban.date} - div Expiry: #{ban.expireAt} - if ban.post - span Post: - section.thread - +post(ban.post, false) + .ban + input.post-check(type='checkbox', name='checkedbans[]' value=ban._id) + if ban.board + div Board: #[a(href=`/${ban.board}`) /#{ban.board}/] + else + div Global ban. + div Reason: #{ban.reason} + div Issuer: #{ban.issuer} + div Date: #{ban.date} + div Expiry: #{ban.expireAt} + if ban.post + span Post: + section.thread + +post(ban.post, false) diff --git a/views/mixins/post.pug b/views/mixins/post.pug index 16a6d6ef..ac90cab0 100644 --- a/views/mixins/post.pug +++ b/views/mixins/post.pug @@ -1,7 +1,7 @@ mixin post(post, truncate, showreports) article(id=post.postId class='post-container '+(post.thread ? '' : 'op')) header.post-info - input.post-check(type='checkbox', name='checked[]' value=post.postId) + input.post-check(type='checkbox', name='checkedposts[]' value=post.postId) if post.subject span.post-subject #{post.subject} if post.email @@ -16,7 +16,7 @@ mixin post(post, truncate, showreports) .post-files each file in post.files .post-file - .post-file-info + small.post-file-info span: a(href='/img/'+file.filename download=file.originalFilename) #{file.originalFilename} br span (#{file.sizeString} #{file.geometryString}) diff --git a/views/pages/board.pug b/views/pages/board.pug index b912c862..a1d39007 100644 --- a/views/pages/board.pug +++ b/views/pages/board.pug @@ -10,7 +10,7 @@ block content include ../includes/postform.pug .mode Posting mode: Thread [#[a.no-decoration(href=`/${board._id}/catalog`) Catalog]] hr(size=1) - form(action='/forms/board/'+board._id+'/posts' method='POST' enctype='application/x-www-form-urlencoded') + form(action='/forms/board/'+board._id+'/actions' method='POST' enctype='application/x-www-form-urlencoded') input(type='hidden' name='_csrf' value=csrf) if threads.length === 0 p No posts. diff --git a/views/pages/manage.pug b/views/pages/manage.pug index 447a1878..35fcc8a8 100644 --- a/views/pages/manage.pug +++ b/views/pages/manage.pug @@ -9,7 +9,7 @@ block content include ../includes/boardheader.pug hr(size=1) h4 Reports: - form(action=`/forms/board/${board._id}/posts` method='POST' enctype='application/x-www-form-urlencoded') + form(action=`/forms/board/${board._id}/actions` method='POST' enctype='application/x-www-form-urlencoded') input(type='hidden' name='_csrf' value=csrf) if posts.length === 0 p No reports. @@ -51,5 +51,5 @@ block content section.thread +ban(ban) hr(size=1) - //section.action-wrapper + section.action-wrapper input(type='submit', value='unban') diff --git a/views/pages/thread.pug b/views/pages/thread.pug index a047896e..f0fcfbf4 100644 --- a/views/pages/thread.pug +++ b/views/pages/thread.pug @@ -15,7 +15,7 @@ block content include ../includes/postform.pug .mode Posting mode: Reply [#[a.no-decoration(href=`/${board._id}`) Go Back]] hr(size=1) - form(action='/forms/board/'+board._id+'/posts' method='POST' enctype='application/x-www-form-urlencoded') + form(action=`/forms/board/${board._id}/actions` method='POST' enctype='application/x-www-form-urlencoded') input(type='hidden' name='_csrf' value=csrf) section.thread +post(thread)