cubash-archive/routes/thread.js

194 lines
4.9 KiB
JavaScript

let express = require('express')
let router = express.Router()
const auth = require('../lib/auth')
const Errors = require('../lib/errors.js')
let { User, Thread, Notification, Category, Post, Ban, Report, Sequelize } = require('../models')
let pagination = require('../lib/pagination.js')
const rateLimit = require("express-rate-limit");
const postLimiter = rateLimit({
windowMs: 60000,
max: 10,
message: "{\"errors\":[{\"name\":\"rateLimit\",\"message\":\"You may only make 10 requests to this endpoint per minute.\",\"status\":429}]}"
});
router.get('/:thread_id', async(req, res, next) => {
try {
let { from, limit } = pagination.getPaginationProps(req.query)
let thread = await Thread.findByPk(req.params.thread_id, {
include: Thread.includeOptions(from, limit)
})
if(!thread) throw Errors.invalidParameter('id', 'thread does not exist')
let meta = thread.getMeta(limit)
res.json(Object.assign( thread.toJSON(), { meta } ))
} catch (e) { next(e) }
})
//Only logged in routes
router.all('*', auth, (req, res, next) => {
if(req.userData.loggedIn) {
next()
} else {
res.status(401)
res.json({
errors: [Errors.requestNotAuthorized]
})
}
})
router.post('/', postLimiter, auth, async(req, res, next) => {
let validationErrors = []
try {
await Ban.ReadOnlyMode(req.userData.UserId)
let category = await Category.findOne({ where: {
value: req.body.category
}})
if (req.body.category == "ALL") throw Errors.selectCategory
if (req.body.category == "") throw Errors.selectCategory
if (!category) throw Errors.invalidCategory
if (category.locked && !req.userData.admin) throw Errors.lockedCategory
let user = await User.findOne({ where: {
username: req.userData.username
}})
if(!user.emailVerified) {
throw Errors.verifyEmail
}
let thread = await Thread.create({
name: req.body.name
})
await thread.increment('postsCount')
await thread.setCategory(category)
await thread.setUser(user)
user = await User.findOne({ where: {
username: req.userData.username
}})
if(req.body.replyingToId) {
let replyingToPost1 = Post.findByPk(
req.body.replyingToId, { include: [Thread, { model: User, attributes: ['username'] }] }
)
console.log(replyingToPost1)
replyingToPost = await Post.getReplyingToPost(
req.body.replyingToId, thread, replyingToPost1
)
var post = await Post.create({ content: req.body.content, postNumber: thread.postsCount })
await post.setReplyingTo(replyingToPost)
await replyingToPost.addReplies(post)
let replyNotification = await Notification.createPostNotification({
usernameTo: replyingToPost.User.username,
userFrom: user,
type: 'reply',
post: post
})
await replyNotification.emitNotificationMessage(
req.app.get('io-users'),
req.app.get('io')
)
} else {
var post = await Post.create({ content: req.body.content, postNumber: thread.postsCount })
}
await post.setUser(user)
await post.setThread(thread)
res.json(await thread.reload({
include: [
{ model: User, attributes: ['username', 'createdAt', 'updatedAt', 'id'] },
Category
]
}))
req.app.get('io').to('index').emit('new thread', {
name: category.name,
value: category.value
})
} catch (e) { next(e) }
})
//Only admin routes
router.all('*', auth, async(req, res, next) => {
let user = await User.findOne({ where: {
username: req.userData.username
}})
if(!user) throw Errors.requestNotAuthorized
if(req.userData.admin && user.admin) {
next()
} else {
res.status(401)
res.json({
errors: [Errors.sessionAdminProtection]
})
}
})
router.delete('/:thread_id', auth, async(req, res, next) => {
try {
let thread = await Thread.findByPk(req.params.thread_id)
if(!thread) {
throw Errors.sequelizeValidation(Sequelize, {
error: 'invalid thread id',
value: req.params.thread_id
})
} else {
//Find all posts with reports and get reports
//Then delete those reports
//Temporary fix because cascade is not working
let posts = await Post.findAll({
where: {
ThreadId: thread.id
},
include: [Report]
})
let reports = posts
.map(post => post.Reports)
.reduce((a, b) => a.concat(b), [])
let destroyPromises = reports.map(report => report.destroy())
await Promise.all(destroyPromises)
await Post.destroy({ where: { ThreadId: thread.id } })
await thread.destroy()
res.json({ success: true })
}
} catch (e) { next(e) }
})
router.put('/:thread_id', auth, async(req, res, next) => {
try {
let thread = await Thread.findByPk(req.params.thread_id)
if(!thread) {
res.status(400)
res.json({ errors:
[Errors.invalidParameter('threadId', 'thread does not exist')]
})
} else {
if(req.body.locked) {
await thread.update({ locked: true })
} else {
await thread.update({ locked: false })
}
res.json({ success: true })
}
} catch (e) { next(e) }
})
module.exports = router