'use strict' ;
const express = require ( 'express' )
, router = express . Router ( )
, { enableUserBoards } = require ( _ _dirname + '/../configs/main.json' )
, Boards = require ( _ _dirname + '/../db/boards.js' )
, Posts = require ( _ _dirname + '/../db/posts.js' )
, Bans = require ( _ _dirname + '/../db/bans.js' )
, Mongo = require ( _ _dirname + '/../db/db.js' )
, { remove } = require ( 'fs-extra' )
, upload = require ( 'express-fileupload' )
, path = require ( 'path' )
, alphaNumericRegex = /^[a-zA-Z0-9]+$/
, postFiles = upload ( {
createParentPath : true ,
safeFileNames : /[^\w-]+/g ,
preserveExtension : 4 ,
limits : {
fileSize : 10 * 1024 * 1024 ,
files : 3
} ,
abortOnLimit : true ,
useTempFiles : true ,
tempFileDir : path . join ( _ _dirname + '/../tmp/' )
} )
, bannerFiles = upload ( {
createParentPath : true ,
safeFileNames : /[^\w-]+/g ,
preserveExtension : 4 ,
limits : {
fileSize : 10 * 1024 * 1024 ,
files : 10
} ,
abortOnLimit : true ,
useTempFiles : true ,
tempFileDir : path . join ( _ _dirname + '/../tmp/' )
} )
, removeBans = require ( _ _dirname + '/../models/forms/removebans.js' )
, makePost = require ( _ _dirname + '/../models/forms/makepost.js' )
, deletePosts = require ( _ _dirname + '/../models/forms/deletepost.js' )
, deleteTempFiles = require ( _ _dirname + '/../helpers/files/deletetempfiles.js' )
, uploadBanners = require ( _ _dirname + '/../models/forms/uploadbanners.js' )
, deleteBanners = require ( _ _dirname + '/../models/forms/deletebanners.js' )
, loginAccount = require ( _ _dirname + '/../models/forms/login.js' )
, changePassword = require ( _ _dirname + '/../models/forms/changepassword.js' )
, changeBoardSettings = require ( _ _dirname + '/../models/forms/changeboardsettings.js' )
, registerAccount = require ( _ _dirname + '/../models/forms/register.js' )
, createBoard = require ( _ _dirname + '/../models/forms/create.js' )
, calcPerms = require ( _ _dirname + '/../helpers/checks/calcpermsmiddleware.js' )
, hasPerms = require ( _ _dirname + '/../helpers/checks/haspermsmiddleware.js' )
, spamCheck = require ( _ _dirname + '/../helpers/checks/spamcheck.js' )
, paramConverter = require ( _ _dirname + '/../helpers/paramconverter.js' )
, banCheck = require ( _ _dirname + '/../helpers/checks/bancheck.js' )
, isLoggedIn = require ( _ _dirname + '/../helpers/checks/isloggedin.js' )
, verifyCaptcha = require ( _ _dirname + '/../helpers/captcha/captchaverify.js' )
, actionHandler = require ( _ _dirname + '/../models/forms/actionhandler.js' )
, csrf = require ( _ _dirname + '/../helpers/checks/csrfmiddleware.js' )
, uploadDirectory = require ( _ _dirname + '/../helpers/files/uploadDirectory.js' )
, actionChecker = require ( _ _dirname + '/../helpers/checks/actionchecker.js' ) ;
// login to account
router . post ( '/login' , async ( req , res , next ) => {
const errors = [ ] ;
//check exist
if ( ! req . body . username || req . body . username . length <= 0 ) {
errors . push ( 'Missing username' ) ;
}
if ( ! req . body . password || req . body . password . length <= 0 ) {
errors . push ( 'Missing password' ) ;
}
//check too long
if ( req . body . username && req . body . username . length > 50 ) {
errors . push ( 'Username must be 50 characters or less' ) ;
}
if ( req . body . password && req . body . password . length > 100 ) {
errors . push ( 'Password must be 100 characters or less' ) ;
}
if ( errors . length > 0 ) {
return res . status ( 400 ) . render ( 'message' , {
'title' : 'Bad request' ,
'errors' : errors ,
'redirect' : '/login.html'
} )
}
try {
await loginAccount ( req , res , next ) ;
} catch ( err ) {
return next ( err ) ;
}
} ) ;
//change password
router . post ( '/changepassword' , verifyCaptcha , async ( req , res , next ) => {
const errors = [ ] ;
//check exist
if ( ! req . body . username || req . body . username . length <= 0 ) {
errors . push ( 'Missing username' ) ;
}
if ( ! req . body . password || req . body . password . length <= 0 ) {
errors . push ( 'Missing password' ) ;
}
if ( ! req . body . newpassword || req . body . newpassword . length <= 0 ) {
errors . push ( 'Missing new password' ) ;
}
if ( ! req . body . newpasswordconfirm || req . body . newpasswordconfirm . length <= 0 ) {
errors . push ( 'Missing new password confirmation' ) ;
}
//check too long
if ( req . body . username && req . body . username . length > 50 ) {
errors . push ( 'Username must be 50 characters or less' ) ;
}
if ( req . body . password && req . body . password . length > 100 ) {
errors . push ( 'Password must be 100 characters or less' ) ;
}
if ( req . body . newpassword && req . body . newpassword . length > 100 ) {
errors . push ( 'Password must be 100 characters or less' ) ;
}
if ( req . body . newpasswordconfirm && req . body . newpasswordconfirm . length > 100 ) {
errors . push ( 'Password confirmation must be 100 characters or less' ) ;
}
if ( req . body . newpassword != req . body . newpasswordconfirm ) {
errors . push ( 'New password and password confirmation must match' ) ;
}
if ( errors . length > 0 ) {
return res . status ( 400 ) . render ( 'message' , {
'title' : 'Bad request' ,
'errors' : errors ,
'redirect' : '/changepassword.html'
} )
}
try {
await changePassword ( req , res , next ) ;
} catch ( err ) {
return next ( err ) ;
}
} ) ;
//create board
router . post ( '/create' , csrf , isLoggedIn , verifyCaptcha , calcPerms , hasPerms ( 4 ) , ( req , res , next ) => {
if ( enableUserBoards === false && res . locals . permLevel !== 0 ) {
//only board admin can create boards when user board creation disabled
return res . status ( 400 ) . render ( 'message' , {
'title' : 'Bad request' ,
'error' : 'Board creation is only available to site administration' ,
'redirect' : '/'
} )
}
const errors = [ ] ;
//check exist
if ( ! req . body . uri || req . body . uri . length <= 0 ) {
errors . push ( 'Missing URI' ) ;
}
if ( ! req . body . name || req . body . name . length <= 0 ) {
errors . push ( 'Missing name' ) ;
}
if ( ! req . body . description || req . body . description . length <= 0 ) {
errors . push ( 'Missing description' ) ;
}
//other validation
if ( req . body . uri ) {
if ( req . body . uri . length > 50 ) {
errors . push ( 'URI must be 50 characters or less' ) ;
}
if ( alphaNumericRegex . test ( req . body . uri ) !== true ) {
errors . push ( 'URI must contain a-z 0-9 only' ) ;
}
}
if ( req . body . name && req . body . name . length > 50 ) {
errors . push ( 'Name must be 50 characters or less' ) ;
}
if ( req . body . description && req . body . description . length > 50 ) {
errors . push ( 'Description must be 50 characters or less' ) ;
}
if ( errors . length > 0 ) {
return res . status ( 400 ) . render ( 'message' , {
'title' : 'Bad request' ,
'errors' : errors ,
'redirect' : '/create.html'
} ) ;
}
createBoard ( req , res , next ) ;
} ) ;
//register account
router . post ( '/register' , verifyCaptcha , ( req , res , next ) => {
const errors = [ ] ;
//check exist
if ( ! req . body . username || req . body . username . length <= 0 ) {
errors . push ( 'Missing username' ) ;
}
if ( ! req . body . password || req . body . password . length <= 0 ) {
errors . push ( 'Missing password' ) ;
}
if ( ! req . body . passwordconfirm || req . body . passwordconfirm . length <= 0 ) {
errors . push ( 'Missing password confirmation' ) ;
}
//check
if ( req . body . username ) {
if ( req . body . username . length > 50 ) {
errors . push ( 'Username must be 50 characters or less' ) ;
}
if ( alphaNumericRegex . test ( req . body . username ) !== true ) {
errors . push ( 'Username must contain a-z 0-9 only' ) ;
}
}
if ( req . body . password && req . body . password . length > 100 ) {
errors . push ( 'Password must be 100 characters or less' ) ;
}
if ( req . body . passwordconfirm && req . body . passwordconfirm . length > 100 ) {
errors . push ( 'Password confirmation must be 100 characters or less' ) ;
}
if ( req . body . password != req . body . passwordconfirm ) {
errors . push ( 'Password and password confirmation must match' ) ;
}
if ( errors . length > 0 ) {
return res . status ( 400 ) . render ( 'message' , {
'title' : 'Bad request' ,
'errors' : errors ,
'redirect' : '/register.html'
} )
}
registerAccount ( req , res , next ) ;
} ) ;
// make new post
router . post ( '/board/:board/post' , Boards . exists , calcPerms , banCheck , postFiles , paramConverter , verifyCaptcha , async ( req , res , next ) => {
if ( req . files && req . files . file ) {
if ( Array . isArray ( req . files . file ) ) {
res . locals . numFiles = req . files . file . filter ( file => file . size > 0 ) . length ;
} else {
res . locals . numFiles = req . files . file . size > 0 ? 1 : 0 ;
req . files . file = [ req . files . file ] ;
}
res . locals . numFiles = Math . min ( res . locals . numFiles , res . locals . board . settings . maxFiles )
}
const errors = [ ] ;
// even if force file and message are off, the post must contain one of either.
if ( ! req . body . message && res . locals . numFiles === 0 ) {
errors . push ( 'Posts must include a message or file' ) ;
}
// check file, subject and message enforcement according to board settings
if ( ! req . body . subject || req . body . subject . length === 0 ) {
if ( ! req . body . thread && res . locals . board . settings . forceThreadSubject ) {
errors . push ( 'Threads must include a subject' ) ;
} //no option to force op subject, seems useless
}
if ( res . locals . board . settings . maxFiles !== 0 && res . locals . numFiles === 0 ) {
if ( ! req . body . thread && res . locals . board . settings . forceThreadFile ) {
errors . push ( 'Threads must include a file' ) ;
} else if ( res . locals . board . settings . forceReplyFile ) {
errors . push ( 'Posts must include a file' ) ;
}
}
if ( ! req . body . message || req . body . message . length === 0 ) {
if ( ! req . body . thread && res . locals . board . settings . forceThreadMessage ) {
errors . push ( 'Threads must include a message' ) ;
} else if ( res . locals . board . settings . forceReplyMessage ) {
errors . push ( 'Posts must include a message' ) ;
}
}
if ( req . body . message ) {
if ( req . body . message . length > 4000 ) {
errors . push ( 'Message must be 4000 characters or less' ) ;
} else if ( ! req . body . thread && req . body . message . length < res . locals . board . settings . minThreadMessageLength ) {
errors . push ( ` Thread messages must be at least ${ res . locals . board . settings . minMessageLength } characters long ` ) ;
} else if ( req . body . thread && req . body . message . length < res . locals . board . settings . minReplyMessageLength ) {
errors . push ( ` Reply messages must be at least ${ res . locals . board . settings . minMessageLength } characters long ` ) ;
}
}
// subject, email, name, password limited length
if ( req . body . name && req . body . name . length > 50 ) {
errors . push ( 'Name must be 50 characters or less' ) ;
}
if ( req . body . subject && req . body . subject . length > 50 ) {
errors . push ( 'Subject must be 50 characters or less' ) ;
}
if ( req . body . email && req . body . email . length > 50 ) {
errors . push ( 'Email must be 50 characters or less' ) ;
}
if ( req . body . password && req . body . password . length > 50 ) {
errors . push ( 'Password must be 50 characters or less' ) ;
}
if ( errors . length > 0 ) {
await deleteTempFiles ( req ) . catch ( e => console . error ) ;
return res . status ( 400 ) . render ( 'message' , {
'title' : 'Bad request' ,
'errors' : errors ,
'redirect' : ` / ${ req . params . board } ${ req . body . thread ? '/thread/' + req . body . thread + '.html' : '' } `
} ) ;
}
const flood = await spamCheck ( req , res ) ;
if ( flood ) {
deleteTempFiles ( req ) . catch ( e => console . error ) ;
return res . status ( 429 ) . render ( 'message' , {
'title' : 'Flood detected' ,
'message' : 'Please wait before making another post, or a post similar to another user' ,
'redirect' : ` / ${ req . params . board } ${ req . body . thread ? '/thread/' + req . body . thread + '.html' : '' } `
} ) ;
}
try {
await makePost ( req , res , next ) ;
} catch ( err ) {
await deleteTempFiles ( req ) . catch ( e => console . error ) ;
return next ( err ) ;
}
} ) ;
//board settings
router . post ( '/board/:board/settings' , csrf , Boards . exists , calcPerms , banCheck , isLoggedIn , hasPerms ( 2 ) , paramConverter , async ( req , res , next ) => {
const errors = [ ] ;
if ( req . body . description && ( req . body . description . length < 1 || req . body . description . length > 50 ) ) {
errors . push ( 'Board description must be 1-50 characters' ) ;
}
if ( req . body . announcements && ( req . body . announcements . length < 1 || req . body . announcements . length > 2000 ) ) {
errors . push ( 'Board announcements must be 1-2000 characters' ) ;
}
if ( req . body . name && ( req . body . name . length < 1 || req . body . name . length > 50 ) ) {
errors . push ( 'Board name must be 1-50 characters' ) ;
}
if ( req . body . default _name && ( req . body . default _name . length < 1 || req . body . default _name . length > 50 ) ) {
errors . push ( 'Anon name must be 1-50 characters' ) ;
}
if ( typeof req . body . reply _limit === 'number' && ( req . body . reply _limit < 1 || req . body . reply _limit > 1000 ) ) {
errors . push ( 'Reply Limit must be from 1-1000' ) ;
}
if ( typeof req . body . thread _limit === 'number' && ( req . body . thread _limit < 10 || req . body . thread _limit > 250 ) ) {
errors . push ( 'Threads Limit must be 10-250' ) ;
}
if ( typeof req . body . max _files === 'number' && ( req . body . max _files < 0 || req . body . max _files > 3 ) ) {
errors . push ( 'Max files must be 0-3' ) ;
}
if ( typeof req . body . min _thread _message _length === 'number' && ( req . body . min _thread _message _length < 0 || req . body . min _thread _message _length > 4000 ) ) {
errors . push ( 'Min thread message length must be 0-4000. 0 is disabled.' ) ;
}
if ( typeof req . body . min _reply _message _length === 'number' && ( req . body . min _reply _message _length < 0 || req . body . min _reply _message _length > 4000 ) ) {
errors . push ( 'Min reply message length must be 0-4000. 0 is disabled.' ) ;
}
if ( typeof req . body . captcha _mode === 'number' && ( req . body . captcha _mode < 0 || req . body . captcha _mode > 2 ) ) {
errors . push ( 'Invalid captcha mode.' ) ;
}
if ( typeof req . body . tph _trigger === 'number' && ( req . body . tph _trigger < 0 || req . body . tph _trigger > 10000 ) ) {
errors . push ( 'Invalid tph trigger threshold.' ) ;
}
if ( typeof req . body . tph _trigger _action === 'number' && ( req . body . tph _trigger _action < 0 || req . body . tph _trigger _action > 3 ) ) {
errors . push ( 'Invalid tph trigger action.' )
}
if ( typeof req . body . filter _mode === 'number' && ( req . body . filter _mode < 0 || req . body . filter _mode > 2 ) ) {
errors . push ( 'Invalid filter mode.' ) ;
}
if ( typeof req . body . ban _duration === 'number' && req . body . ban _duration <= 0 ) {
errors . push ( 'Invalid filter auto ban duration.' )
}
if ( errors . length > 0 ) {
return res . status ( 400 ) . render ( 'message' , {
'title' : 'Bad request' ,
'errors' : errors ,
'redirect' : ` / ${ req . params . board } /manage.html `
} )
}
try {
await changeBoardSettings ( req , res , next ) ;
} catch ( err ) {
return next ( err ) ;
}
} ) ;
//upload banners
router . post ( '/board/:board/addbanners' , bannerFiles , csrf , Boards . exists , calcPerms , banCheck , isLoggedIn , hasPerms ( 2 ) , paramConverter , async ( req , res , next ) => {
if ( req . files && req . files . file ) {
if ( Array . isArray ( req . files . file ) ) {
res . locals . numFiles = req . files . file . filter ( file => file . size > 0 ) . length ;
} else {
res . locals . numFiles = req . files . file . size > 0 ? 1 : 0 ;
req . files . file = [ req . files . file ] ;
}
}
const errors = [ ] ;
if ( res . locals . numFiles === 0 ) {
errors . push ( 'Must provide a file' ) ;
}
if ( res . locals . board . banners . length + res . locals . numFiles > 100 ) {
errors . push ( 'Number of uploads would exceed 100 banner limit' ) ;
}
if ( errors . length > 0 ) {
await deleteTempFiles ( req ) . catch ( e => console . error ) ;
return res . status ( 400 ) . render ( 'message' , {
'title' : 'Bad request' ,
'errors' : errors ,
'redirect' : ` / ${ req . params . board } /manage.html `
} )
}
try {
await uploadBanners ( req , res , next ) ;
} catch ( err ) {
await deleteTempFiles ( req ) . catch ( e => console . error ) ;
return next ( err ) ;
}
} ) ;
//delete banners
router . post ( '/board/:board/deletebanners' , csrf , Boards . exists , calcPerms , banCheck , isLoggedIn , hasPerms ( 2 ) , paramConverter , async ( req , res , next ) => {
const errors = [ ] ;
if ( ! req . body . checkedbanners || req . body . checkedbanners . length === 0 || req . body . checkedbanners . length > 10 ) {
errors . push ( 'Must select 1-10 banners to delete' ) ;
}
if ( errors . length > 0 ) {
return res . status ( 400 ) . render ( 'message' , {
'title' : 'Bad request' ,
'errors' : errors ,
'redirect' : ` / ${ req . params . board } /manage.html `
} )
}
for ( let i = 0 ; i < req . body . checkedbanners . length ; i ++ ) {
if ( ! res . locals . board . banners . includes ( req . body . checkedbanners [ i ] ) ) {
return res . status ( 400 ) . render ( 'message' , {
'title' : 'Bad request' ,
'message' : 'Invalid banners selected' ,
'redirect' : ` / ${ req . params . board } /manage.html `
} )
}
}
try {
await deleteBanners ( req , res , next ) ;
} catch ( err ) {
console . error ( err ) ;
return next ( err ) ;
}
} ) ;
//actions for a specific board
router . post ( '/board/:board/actions' , Boards . exists , calcPerms , banCheck , paramConverter , verifyCaptcha , boardActionController ) ; //Captcha on regular actions
router . post ( '/board/:board/modactions' , csrf , Boards . exists , calcPerms , banCheck , isLoggedIn , hasPerms ( 3 ) , paramConverter , boardActionController ) ; //CSRF for mod actions
async function boardActionController ( req , res , next ) {
const errors = [ ] ;
//make sure they checked 1-10 posts
if ( ! req . body . checkedposts || req . body . checkedposts . length === 0 || req . body . checkedposts . length > 10 ) {
errors . push ( 'Must select 1-10 posts' ) ;
}
res . locals . actions = actionChecker ( req ) ;
//make sure they selected at least 1 action
if ( ! res . locals . actions . anyValid ) {
errors . push ( 'No actions selected' ) ;
}
//check if they have permission to perform the actions
if ( res . locals . permLevel > res . locals . actions . authRequired ) {
errors . push ( 'No permission' ) ;
}
if ( res . locals . permLevel >= 4 ) {
if ( req . body . delete && ! res . locals . board . settings . userPostDelete ) {
errors . push ( 'Post deletion is disabled on this board' ) ;
}
if ( req . body . spoiler && ! res . locals . board . settings . userPostSpoiler ) {
errors . push ( 'File spoilers are disabled on this board' ) ;
}
if ( req . body . unlink _file && ! res . locals . board . settings . userPostUnlink ) {
errors . push ( 'File unlinking is disabled on this board' ) ;
}
}
//check that actions are valid
if ( req . body . password && req . body . password . length > 50 ) {
errors . push ( 'Password must be 50 characters or less' ) ;
}
if ( req . body . report _reason && req . body . report _reason . length > 50 ) {
errors . push ( 'Report must be 50 characters or less' ) ;
}
if ( req . body . ban _reason && req . body . ban _reason . length > 50 ) {
errors . push ( 'Ban reason must be 50 characters or less' ) ;
}
if ( ( req . body . report || req . body . global _report ) && ( ! req . body . report _reason || req . body . report _reason . length === 0 ) ) {
errors . push ( 'Reports must have a reason' ) ;
}
if ( errors . length > 0 ) {
return res . status ( 400 ) . render ( 'message' , {
'title' : 'Bad request' ,
'errors' : errors ,
'redirect' : ` / ${ req . params . board } / `
} )
}
res . locals . posts = await Posts . getPosts ( req . params . board , req . body . checkedposts , true ) ;
if ( ! res . locals . posts || res . locals . posts . length === 0 ) {
return res . status ( 404 ) . render ( 'message' , {
'title' : 'Not found' ,
'error' : 'Selected posts not found' ,
'redirect' : ` / ${ req . params . board } / `
} )
}
try {
await actionHandler ( req , res , next ) ;
} catch ( err ) {
console . error ( err ) ;
return next ( err ) ;
}
}
//global actions (global manage page)
router . post ( '/global/actions' , csrf , calcPerms , isLoggedIn , hasPerms ( 1 ) , paramConverter , globalActionController ) ;
async function globalActionController ( req , res , next ) {
const errors = [ ] ;
//make sure they checked 1-10 posts
if ( ! req . body . globalcheckedposts || req . body . globalcheckedposts . length === 0 || req . body . globalcheckedposts . length > 10 ) {
errors . push ( 'Must select 1-10 posts' )
}
res . locals . actions = actionChecker ( req ) ;
//make sure they have any global actions, and that they only selected global actions
if ( ! res . locals . actions . anyGlobal || res . locals . actions . anyValid > res . locals . actions . anyGlobal ) {
errors . push ( 'Invalid actions selected' ) ;
}
//check that actions are valid
if ( req . body . password && req . body . password . length > 50 ) {
errors . push ( 'Password must be 50 characters or less' ) ;
}
if ( req . body . ban _reason && req . body . ban _reason . length > 50 ) {
errors . push ( 'Ban reason must be 50 characters or less' ) ;
}
//return the errors
if ( errors . length > 0 ) {
return res . status ( 400 ) . render ( 'message' , {
'title' : 'Bad request' ,
'errors' : errors ,
'redirect' : '/globalmanage.html'
} )
}
//get posts with global ids only
res . locals . posts = await Posts . globalGetPosts ( req . body . globalcheckedposts , true ) ;
if ( ! res . locals . posts || res . locals . posts . length === 0 ) {
return res . status ( 404 ) . render ( 'message' , {
'title' : 'Not found' ,
'errors' : 'Selected posts not found' ,
'redirect' : '/globalmanage.html'
} )
}
try {
await actionHandler ( req , res , next ) ;
} catch ( err ) {
console . error ( err ) ;
return next ( err ) ;
}
}
//unban
router . post ( '/board/:board/unban' , csrf , Boards . exists , calcPerms , banCheck , isLoggedIn , hasPerms ( 3 ) , paramConverter , async ( req , res , next ) => {
//keep this for later in case i add other options to unbans
const errors = [ ] ;
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.html `
} ) ;
}
const messages = [ ] ;
try {
messages . push ( ( await removeBans ( req , res , next ) ) ) ;
} catch ( err ) {
return next ( err ) ;
}
return res . render ( 'message' , {
'title' : 'Success' ,
'messages' : messages ,
'redirect' : ` / ${ req . params . board } /manage.html `
} ) ;
} ) ;
//delete board
router . post ( '/board/:board/deleteboard' , csrf , Boards . exists , calcPerms , banCheck , isLoggedIn , hasPerms ( 2 ) , async ( req , res , next ) => {
const errors = [ ] ;
if ( ! req . body . confirm ) {
errors . push ( 'Missing confirmation' ) ;
}
if ( ! req . body . uri || req . body . uri !== req . params . board ) {
errors . push ( 'URI does not match' )
}
if ( errors . length > 0 ) {
return res . status ( 400 ) . render ( 'message' , {
'title' : 'Bad request' ,
'errors' : errors ,
'redirect' : ` / ${ req . params . board } /manage.html `
} ) ;
}
try {
//todo: move this to separate model file
// could be slow, might also wanna use projection to just get the files and other info necessary for deleteposts model
await Boards . deleteOne ( res . locals . board . _id ) ;
const allPosts = await Posts . allBoardPosts ( res . locals . board . _id ) ;
if ( allPosts . length > 0 ) {
await deletePosts ( allPosts , res . locals . board . _id , true ) ;
}
await Bans . deleteBoard ( res . locals . board . _id ) ;
await remove ( ` ${ uploadDirectory } html/ ${ req . params . board } / ` )
} catch ( err ) {
return next ( err ) ;
}
return res . render ( 'message' , {
'title' : 'Success' ,
'message' : 'Board deleted' ,
'redirect' : '/'
} ) ;
} ) ;
router . post ( '/global/unban' , csrf , calcPerms , isLoggedIn , hasPerms ( 1 ) , paramConverter , async ( req , res , next ) => {
const errors = [ ] ;
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' : ` /globalmanage.html `
} ) ;
}
const messages = [ ] ;
try {
messages . push ( ( await removeBans ( req , res , next ) ) ) ;
} catch ( err ) {
return next ( err ) ;
}
return res . render ( 'message' , {
'title' : 'Success' ,
'messages' : messages ,
'redirect' : ` /globalmanage.html `
} ) ;
} ) ;
router . post ( '/newcaptcha' , async ( req , res , next ) => {
res . clearCookie ( 'captchaid' ) ;
return res . redirect ( '/captcha.html' ) ;
} ) ;
module . exports = router ;