const { default: mongoose } = require("mongoose"); const asyncHandler = require("express-async-handler"); const { body, validationResult } = require("express-validator"); const jwt = require("jsonwebtoken"); const Post = require("../models/post.js"); const Comment = require("../models/comment.js"); const hasToken = require("../middleware/hasToken.js"); const sameAuthor = require("../middleware/sameAuthor.js"); exports.index = asyncHandler(async (req, res, next) => { // get all posts let dbPosts = await Post.find().lean().exec(); // check for authorization const token = req.cookies.JWT_TOKEN; if (token) { const username = jwt.verify(token, process.env.SECRET_KEY).username; // filter dbPosts.forEach((post, index) => { if (post.published == false) { if (post.author != username) { dbPosts.splice(index, 1); } } }); } else { // filter dbPosts.forEach((post, index) => { if (post.published == false) { dbPosts.splice(index, 1); } }); } const posts = []; for (let i = 0; i < dbPosts.length; i++) { const comments = await Comment.find({ post: dbPosts[i]._id }); const post = { title: dbPosts[i].title, date: dbPosts[i].date, text: dbPosts[i].text, author: dbPosts[i].author, published: dbPosts[i].published, _id: dbPosts[i]._id, comments: comments, }; posts.push(post); } return res.status(200).json({ posts }); }); // makes new post - C exports.post = [ // Validate and sanitize title body("title", "Please enter blog post title!").isLength({ min: 1 }).trim(), // Validate and sanitize text body("text", "Please enter blog post text!").isLength({ min: 1 }).trim(), asyncHandler(async (req, res, next) => { // then return any validation errors const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ message: "Comment produced validation errors!", errors: errors.array(), }); } // get current user from jwt token // get token const token = req.cookies.JWT_TOKEN; // extract username from token const username = jwt.verify(token, process.env.SECRET_KEY).username; // else data is valid, make post object const post = new Post({ title: req.body.title, date: new Date(), text: req.body.text, author: username, published: req.body.published, _id: new mongoose.Types.ObjectId(), }); // save to DB await post.save(); return res.status(200).json({ message: "Post created!", }); }), ]; // returns post in json format - R exports.get = asyncHandler(async (req, res, next) => { const dbPost = await Post.findById(req.params.postID).lean().exec(); const comments = await Comment.find({ post: dbPost._id }) .sort({ date: -1, }) .lean() .exec(); const post = { title: dbPost.title, date: dbPost.date, text: dbPost.text, author: dbPost.author, published: dbPost.published, _id: dbPost._id, comments: comments, }; // if post is not published, not publicly visible if (!dbPost.published) { const token = req.cookies.JWT_TOKEN; if (token) { const username = jwt.verify(token, process.env.SECRET_KEY).username; if (username == dbPost.author) { return res.status(200).json({ post }); } return res.status(403).json({ message: "Not authorized!", }); } return res.status(403).json({ message: "Token not found!", }); } // otherwise return post if published return res.status(200).json({ post }); }); // updates post - U exports.put = [ // Validate and sanitize title body("title", "Please enter blog post title!").isLength({ min: 1 }).trim(), // Validate and sanitize text body("text", "Please enter blog post text!").isLength({ min: 1 }).trim(), // Process request after sanitization and validation asyncHandler(async (req, res, next) => { // return any validation errors const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ message: "Comment produced validation errors!", errors: errors.array(), }); } // else data is valid, update post object const dbPost = await Post.findById(req.params.postID).lean().exec(); const post = new Post({ title: req.body.title, date: new Date(), text: req.body.text, author: dbPost.author, published: req.body.published, _id: dbPost._id, }); // save to DB await Post.findByIdAndUpdate(dbPost._id, post, {}); return res.status(200).json({ message: "Post updated!", }); }), ]; // deletes a post - D exports.delete = asyncHandler(async (req, res, next) => { await Post.findByIdAndDelete(req.params.postID).exec(); return res.status(200).json({ message: "Post deleted!" }); });