mods spoiler override and improved delete/spoiler/dismiss handling

merge-requests/208/head
fatchan 5 years ago
parent c79112a35e
commit 09a729a3c9
  1. 7
      controllers/forms.js
  2. 15
      db-models/posts.js
  3. 99
      models/forms/delete-post.js
  4. 78
      models/forms/spoiler-post.js
  5. 9
      views/includes/deletefooter.pug
  6. 2
      views/includes/postform.pug
  7. 4
      views/pages/manage.pug

@ -7,6 +7,7 @@ const express = require('express')
, Trips = require(__dirname+'/../db-models/trips.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')
, reportPosts = require(__dirname+'/../models/forms/report-post.js')
, dismissReports = require(__dirname+'/../models/forms/dismiss-report.js')
, loginAccount = require(__dirname+'/../models/forms/login.js')
@ -151,7 +152,7 @@ router.post('/board/:board/posts', Boards.exists, numberConverter, (req, res, ne
if (req.body.reason && req.body.reason.length > 50) {
errors.push('Report must be 50 characters or less');
}
if (!(req.body.report || req.body.delete || req.body.dismiss)) {
if (!(req.body.report || req.body.delete || req.body.dismiss || req.body.spoiler)) {
errors.push('Must select an action')
}
if (req.body.report && (!req.body.reason || req.body.reason.length === 0)) {
@ -170,7 +171,9 @@ router.post('/board/:board/posts', Boards.exists, numberConverter, (req, res, ne
reportPosts(req, res);
} else if (req.body.delete) {
deletePosts(req, res);
} else {
} else if (req.body.spoiler) {
spoilerPosts(req, res);
} else if (req.body.dismiss) {
dismissReports(req, res);
}

@ -255,6 +255,21 @@ module.exports = {
},
spoilerMany: (board, ids) => {
return db.updateMany({
'postId': {
'$in': ids
},
'board': board
}, {
'$set': {
'spoiler': true
}
});
},
deleteAll: (board) => {
return db.deleteMany({
'board': board

@ -6,7 +6,7 @@ const path = require('path')
, unlink = util.promisify(fs.unlink)
, uploadDirectory = require(__dirname+'/../../helpers/uploadDirectory.js')
, hasPerms = require(__dirname+'/../../helpers/has-perms.js')
, Posts = require(__dirname+'/../../db-models/posts.js');
, Posts = require(__dirname+'/../../db-models/posts.js');
module.exports = async (req, res) => {
@ -19,6 +19,14 @@ module.exports = async (req, res) => {
return res.status(500).render('error');
}
if (!posts || posts.length === 0) {
return res.status(400).render('message', {
'title': 'Bad requests',
'message': 'No posts found',
'redirect': `/${req.params.board}`
});
}
//if user is not logged in OR if lgoged in but not authed, filter the posts by passwords that are not null
if (!hasPerms(req, res)) {
// filter posts by password only if NOT board moderator or owner
@ -28,60 +36,57 @@ module.exports = async (req, res) => {
&& post.password.length > 0
&& post.password == req.body.password
});
if (posts.length === 0) {
return res.status(403).render('message', {
'title': 'Forbidden',
'message': 'Password did not match any selected posts',
'redirect': `/${req.params.board}`
});
}
}
if (posts.length > 0) {
const threadIds = posts.filter(x => x.thread == null).map(x => x.postId);
const threadIds = posts.filter(x => x.thread == null).map(x => x.postId);
//get posts from all threads
let threadPosts = []
await Promise.all(threadIds.map(async id => {
const currentThreadPosts = await Posts.getThreadPosts(req.params.board, id);
threadPosts = threadPosts.concat(currentThreadPosts);
return;
}))
//combine them all into one array
const allPosts = posts.concat(threadPosts)
//delete posts from DB
let deletedPosts = 0;
try {
const result = await Posts.deleteMany(req.params.board, allPosts.map(x => x.postId));
deletedPosts = result.deletedCount;
} catch (err) {
console.error(err);
return res.status(500).render('error');
}
//get posts from all threads
let threadPosts = []
await Promise.all(threadIds.map(async id => {
const currentThreadPosts = await Posts.getThreadPosts(req.params.board, id);
threadPosts = threadPosts.concat(currentThreadPosts);
return;
}))
//get filenames from all the posts
let fileNames = [];
allPosts.forEach(post => {
fileNames = fileNames.concat(post.files.map(x => x.filename))
})
//combine them all into one array
const allPosts = posts.concat(threadPosts)
//delete all the files using the filenames
await Promise.all(fileNames.map(async filename => {
//dont question it.
return Promise.all([
unlink(uploadDirectory + filename),
unlink(uploadDirectory + 'thumb-' + filename)
])
}));
//delete posts from DB
let deletedPosts = 0;
try {
const result = await Posts.deleteMany(req.params.board, allPosts.map(x => x.postId));
deletedPosts = result.deletedCount;
} catch (err) {
console.error(err);
return res.status(500).render('error');
}
//hooray!
return res.render('message', {
'title': 'Success',
'message': `Deleted ${threadIds.length} threads and ${deletedPosts} posts`,
'redirect': `/${req.params.board}`
});
//get filenames from all the posts
let fileNames = [];
allPosts.forEach(post => {
fileNames = fileNames.concat(post.files.map(x => x.filename))
})
}
//delete all the files using the filenames
await Promise.all(fileNames.map(async filename => {
//dont question it.
return Promise.all([
unlink(uploadDirectory + filename),
unlink(uploadDirectory + 'thumb-' + filename)
])
}));
return res.status(403).render('message', {
'title': 'Forbidden',
'message': 'Password did not match any selected posts',
//hooray!
return res.render('message', {
'title': 'Success',
'message': `Deleted ${threadIds.length} threads and ${deletedPosts} posts`,
'redirect': `/${req.params.board}`
});

@ -0,0 +1,78 @@
'use strict';
const path = require('path')
, util = require('util')
, fs = require('fs')
, unlink = util.promisify(fs.unlink)
, uploadDirectory = require(__dirname+'/../../helpers/uploadDirectory.js')
, hasPerms = require(__dirname+'/../../helpers/has-perms.js')
, Posts = require(__dirname+'/../../db-models/posts.js');
module.exports = async (req, res) => {
//get all posts that were checked
let posts;
try {
posts = await Posts.getPosts(req.params.board, req.body.checked, true); //admin arument true, fetches passwords and salts
} catch (err) {
console.error(err);
return res.status(500).render('error');
}
if (!posts || posts.length === 0) {
return res.status(400).render('message', {
'title': 'Bad requests',
'message': 'No posts found',
'redirect': `/${req.params.board}`
});
}
//if user is not logged in OR if lgoged in but not authed, filter the posts by passwords that are not null
if (!hasPerms(req, res)) {
//filter by password
posts = posts.filter(post => {
return post.password != null
&& post.password.length > 0
&& post.password == req.body.password
});
if (posts.length === 0) {
return res.status(403).render('message', {
'title': 'Forbidden',
'message': 'Password did not match any selected posts',
'redirect': `/${req.params.board}`
});
}
}
//filter by not spoilered
posts = posts.filter(post => {
return !post.spoiler
});
if (posts.length === 0) {
return res.status(409).render('message', {
'title': 'Conflict',
'message': 'Selected posts are already spoilered',
'redirect': `/${req.params.board}`
});
}
// spoiler posts
let spoileredPosts = 0;
try {
const result = await Posts.spoilerMany(req.params.board, posts.map(x => x.postId));
spoileredPosts = result.modifiedCount;
} catch (err) {
console.error(err);
return res.status(500).render('error');
}
//hooray!
return res.render('message', {
'title': 'Success',
'message': `Spoilered ${spoileredPosts} posts`,
'redirect': `/${req.params.board}`
});
}

@ -3,10 +3,13 @@ section.action-wrapper
label
input.post-check(type='checkbox', name='delete' value=1)
| Delete
input#password(type='password', name='password', placeholder='deletion password' autocomplete='off')
label
input.post-check(type='checkbox', name='spoiler' value=1)
| Spoiler
input#password(type='password', name='password', placeholder='post password' autocomplete='off')
span
label
input.post-check(type='checkbox', name='report' value=1)
| Report
input#report(type='text', name='reason', placeholder='report reason' autocomplete='off')
| Report
input#report(type='text', name='reason', placeholder='reason' autocomplete='off')
input(type='submit', value='submit')

@ -11,7 +11,7 @@ section.form-wrapper
input#name(type='text', name='email', placeholder='email' autocomplete='off' maxlength='50')
input#password(type='password', name='password', placeholder='password (for deletion)' 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')

@ -22,6 +22,10 @@ block content
label
input.post-check(type='checkbox', name='delete' value=1)
| Delete
span
label
input.post-check(type='checkbox', name='spoiler' value=1)
| Spoiler
span
label
input.post-check(type='checkbox', name='dismiss' value=1)

Loading…
Cancel
Save