const asyncHandler = require("express-async-handler"); const bcrypt = require("bcryptjs"); const User = require("../models/user.js"); const Post = require("../models/post.js"); const jwt = require("jsonwebtoken"); const { body, validationResult } = require("express-validator"); const { default: mongoose } = require("mongoose"); // C exports.post = [ // Validate and sanitize username body("username", "Please enter username!") .isLength({ min: 1 }) .trim() .escape(), // Validate and sanitize password body("password", "Please enter password!") .isLength({ min: 1 }) .trim() .escape(), asyncHandler(async (req, res, next) => { const errors = validationResult(req); // if there are validation errors, return them if (!errors.isEmpty()) { return res.status(400).json({ message: "There were validation errors!", errors: errors.array(), }); } const { username, password } = req.body; // get fields from body const dbUser = await User.findOne({ username: req.params.username }) .lean() .exec(); const exists = await User.findOne({ username: username }).lean().exec(); if (exists) { return res.status(409).json({ message: "Username is taken!", }); } // else const user = new User({ username: username, password: await bcrypt.hash(password, 10), }); // save to DB await user.save(); return res.status(200).json({ message: "User created!", }); }), ]; // R exports.get = asyncHandler(async (req, res, next) => { const user = await User.findOne({ username: req.params.username }) .lean() .exec(); // gets user based on username return res.status(200).json({ user, }); }); // U exports.put = [ // Validate and sanitize username body("username", "Please enter username!") .isLength({ min: 1 }) .trim() .escape(), // Validate and sanitize password body("password", "Please enter password!") .isLength({ min: 1 }) .trim() .escape(), asyncHandler(async (req, res, next) => { // return any validation errors const errors = validationResult(req); // if there are validation errors, return them if (!errors.isEmpty()) { return res.status(400).json({ message: "Comment produced validation errors!", errors: errors.array(), }); } // check for duplicates const { username, password } = req.body; // get fields from body const exists = await User.findOne({ username: username }).lean().exec(); if (exists) { return res.status(409).json({ message: "Username is taken!", }); } // otherwise update user const dbUser = await User.findOne({ username: req.params.username }) .lean() .exec(); const user = new User({ username: username, password: await bcrypt.hash(password, 10), _id: dbUser._id, }); // find all posts that were under the old user's username and rename them to current user's username const dbPosts = await Post.find({ author: req.params.username }) .lean() .exec(); if (dbPosts) { for (let i = 0; i < dbPosts.length; i++) { const currentPost = dbPosts[i]; const post = new Post({ title: currentPost.title, date: currentPost.date, text: currentPost.text, author: currentPost.author, published: username, _id: currentPost._id, }); // updates posts await Post.findByIdAndUpdate(currentPost._id, post, {}); } } // save to DB await User.findByIdAndUpdate(dbUser._id, user, {}); return res.status(200).json({ message: "User updated!", }); }), ]; // D exports.delete = asyncHandler(async (req, res, next) => { // if everything is correct, delete user await User.findOneAndDelete({ username: originalUsername }).exec(); return res.status(200).json({ message: "Post deleted!" }); }); exports.login = asyncHandler(async (req, res, next) => { const { username, password } = req.body; // get fields from body const user = await User.findOne({ username: username }).lean().exec(); // gets user based on username if (user) { const match = await bcrypt.compare(password, user.password); // compare bcrypt hashed passwords let opts = {}; if (match) { opts.expiresIn = "1d"; const token = jwt.sign({ username }, process.env.SECRET_KEY, opts); // create token and return below return res .cookie("JWT_TOKEN", token, { httpOnly: true, sameSite: "none", secure: true, }) .status(200) .json({ message: "Authentication complete", // a winrar is you }); } } return res.status(401).json({ message: "Authentication failed" }); // epic fail }); exports.logout = (req, res, next) => { return res .clearCookie("JWT_TOKEN", { httpOnly: true, sameSite: "none", secure: true, }) .status(200) .json({ message: "Successfully logged out!" }); };