cubash-archive/routes/post.js

199 lines
5.1 KiB
JavaScript

let express = require('express')
let router = express.Router()
const auth = require('../lib/auth')
const Errors = require('../lib/errors')
let { User, Thread, Post, Notification, Ban, Sequelize, sequelize } = require('../models')
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}]}"
});
const likeLimiter = rateLimit({
windowMs: 60000,
max: 25,
message: "{\"errors\":[{\"name\":\"rateLimit\",\"message\":\"You may only make 25 requests to this endpoint per minute.\",\"status\":429}]}"
});
router.get('/:post_id', async(req, res, next) => {
try {
let post = await Post.findByPk(req.params.post_id, { include: Post.includeOptions() })
if(!post) throw Errors.sequelizeValidation(Sequelize, {
error: 'post does not exist',
path: 'id'
})
res.json(post.toJSON())
} catch (e) { next(e) }
})
router.all('*', auth, (req, res, next) => {
if(req.userData.loggedIn) {
next()
} else {
res.status(401)
res.json({
errors: [Errors.requestNotAuthorized]
})
}
})
router.put('/:post_id/like', likeLimiter, auth, async(req, res, next) => {
try {
let post = await Post.findByPk(req.params.post_id)
let user = await User.findOne({ where: { username: req.userData.username }})
if(!post) throw Errors.invalidParameter('id', 'post does not exist')
if(post.UserId === user.id) throw Errors.cannotLikeOwnPost
await post.addLikes(user)
res.json({ success: true })
} catch (e) { next(e) }
})
router.delete('/:post_id/like', likeLimiter, auth, async(req, res, next) => {
try {
let post = await Post.findByPk(req.params.post_id)
let user = await User.findOne({ where: { username: req.userData.username }})
if(!post) throw Errors.invalidParameter('id', 'post does not exist')
await post.removeLikes(user)
res.json({ success: true })
} catch (e) { next(e) }
})
router.post('/', postLimiter, auth, async(req, res, next) => {
let thread, replyingToPost, post, uniqueMentions = []
let queryObj = {
attributes: {include: ['emailVerified']},
where: {username: req.userData.username}
}
let user = await User.findOne(queryObj)
try {
//Will throw an error if banned
await Ban.ReadOnlyMode(req.userData.UserId)
if(req.body.mentions) {
uniqueMentions = Notification.filterMentions(req.body.mentions)
}
if(!user.emailVerified) {
throw Errors.verifyEmail
}
thread = await Thread.findOne({ where: {
id: req.body.threadId
}})
user = await User.findOne({ where: {
username: req.userData.username
}})
if(thread.locked) throw Errors.threadLocked
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
)
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 {
post = await Post.create({ content: req.body.content, postNumber: thread.postsCount })
}
await post.setUser(user)
await post.setThread(thread)
await thread.increment('postsCount')
if(uniqueMentions.length) {
let ioUsers = req.app.get('io-users')
let io = req.app.get('io')
for(const mention of uniqueMentions) {
let mentionNotification = await Notification.createPostNotification({
usernameTo: mention,
userFrom: user,
type: 'mention',
post
})
if(mentionNotification) {
await mentionNotification.emitNotificationMessage(ioUsers, io)
}
}
}
res.json(await post.reload({
include: Post.includeOptions()
}))
req.app.get('io').to('thread/' + thread.id).emit('new post', {
postNumber: thread.postsCount,
content: post.content,
username: user.username
})
} catch (e) { next(e) }
})
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('/:post_id', auth, async(req, res, next) => {
try {
if(!req.userData.admin){
res.status(401)
res.json({errors: [Errors.requestNotAuthorized]})
}
let post = await Post.findByPk(req.params.post_id)
if(!post) throw Errors.sequelizeValidation(Sequelize, {
error: 'post does not exist',
path: 'id'
})
await post.update({ content: '[This post has been removed by an administrator]', removed: true })
res.json({ success: true })
} catch (e) { next(e) }
})
module.exports = router