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 const dbPosts = await Post.find({ published: true }).lean().exec(); // check for authorization const token = req.cookies.JWT_TOKEN; blocc: if (token) { try { const username = jwt.verify(token, process.env.SECRET_KEY); } catch { break blocc; } // run through unpublished posts const unpublished = await Post.find({ published: false }).lean().exec(); for (let z = 0; z < unpublished.length; z++) { const post = unpublished[i]; // if any are by the current user, append to dbPosts if (username == post.author) { dbPosts.push(post); } } } 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, _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() .escape(), // Validate and sanitize text body("text", "Please enter blog post text!") .isLength({ min: 1 }) .trim() .escape(), 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, _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, _id: dbPost._id, comments: comments, }; // if post is not published, not publicly visible if (!dbPost.published) { hasToken(); sameAuthor(); return res.status(200).json({ post }); } // 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() .escape(), // Validate and sanitize text body("text", "Please enter blog post text!") .isLength({ min: 1 }) .trim() .escape(), // 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!" }); });