diff --git a/server/controllers/profile.js b/server/controllers/profile.js index b6b029c..492642f 100644 --- a/server/controllers/profile.js +++ b/server/controllers/profile.js @@ -5,45 +5,59 @@ const asyncHandler = require("express-async-handler"); // @desc Create new profile // @access Public exports.createProfile = asyncHandler(async (req, res, next) => { + const { + firstName, + lastName, + gender, + birthday, + email, + phoneNumber, + location, + profilePic, + description, + availability, + } = req.body; - const { - firstName, - lastName, - gender, - birthday, - email, - phoneNumber, - location, - profilePic, - description, - availability, - } = req.body; - - const profile = await Profile.create({ - firstName, - lastName, - gender, - birthday, - email, - phoneNumber, - location, - profilePic, - description, - availability, - }); + const profile = await Profile.create({ + firstName, + lastName, + gender, + birthday, + email, + phoneNumber, + location, + profilePic, + description, + availability, + }); - res.status(201).json({ - profile, - }); + res.status(201).json({ + profile, + }); }); // @route PUT /profile // @desc updates a profile with given ID // @access Private exports.updateProfile = asyncHandler(async (req, res, next) => { - const id = req.user._id; + const id = req.user._id; + + const { + firstName, + lastName, + gender, + birthday, + email, + phoneNumber, + location, + profilePic, + description, + availability, + } = req.body; - const { + const profile = await Profile.findOneAndUpdate( + { user: id }, + { firstName, lastName, gender, @@ -54,59 +68,38 @@ exports.updateProfile = asyncHandler(async (req, res, next) => { profilePic, description, availability, - } = req.body; + }, + { new: true } + ); - const profile = await Profile.findOneAndUpdate( - { user: id }, - { - firstName, - lastName, - gender, - birthday, - email, - phoneNumber, - location, - profilePic, - description, - availability, - }, - { new: true } - ); - - res.status(200).json({ - profile, - }); + res.status(200).json({ + profile, + }); }); // @route GET /profile // @desc gets a profile with the given ID // @access Private exports.getProfile = asyncHandler(async (req, res, next) => { - const id = req.user._id; - const profile = await Profile.findOne({ user: id }); + const id = req.user._id; + const profile = await Profile.findOne({ user: id }); - if (!profile) { - res.status(404); - throw new Error("The profile does not exist"); - } + if (!profile.length) return res.json({ profile }); - res.status(200).json({ - profile, - }); + res.status(200).json({ + profile, + }); }); // @route GET /profiles // @desc gets all profiles // @access Private exports.getAllProfiles = asyncHandler(async (req, res, next) => { - const profiles = await Profile.find(); + const profiles = await Profile.find(); - if (!profiles) { - res.status(500); - throw new Error("0 results"); - } + if (!profiles.length) return res.json({ profile }); - res.status(200).json({ - profiles, - }); -}); \ No newline at end of file + res.status(200).json({ + profiles, + }); +}); diff --git a/server/models/Profile.js b/server/models/Profile.js index b738ab3..0eb8a15 100644 --- a/server/models/Profile.js +++ b/server/models/Profile.js @@ -71,4 +71,4 @@ profileSchema.methods.setProflePic = function (imgUrl) { this.save(); }; -module.exports = Profile = mongoose.model("profile", profileSchema); +module.exports = Profile = mongoose.model("profile", profileSchema); \ No newline at end of file diff --git a/server/package.json b/server/package.json index 4e628ee..9aade1b 100644 --- a/server/package.json +++ b/server/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "bcryptjs": "^2.4.3", + "cloudinary": "^1.27.0", "colors": "^1.4.0", "cookie-parser": "^1.4.5", "dotenv": "^8.2.0", @@ -21,6 +22,7 @@ "jsonwebtoken": "^8.5.1", "mongoose": "^5.12.8", "morgan": "^1.10.0", + "multer": "^1.4.3", "nodemon": "^2.0.6", "socket.io": "^4.1.0" }, diff --git a/server/routes/profile.js b/server/routes/profile.js index c93f919..d2d3516 100644 --- a/server/routes/profile.js +++ b/server/routes/profile.js @@ -1,7 +1,26 @@ const express = require("express"); +const protect = require("../middleware/auth"); +const upload = require("../middleware/multer"); +const { validateMongoId, validateProfileDetails } = require("../validate"); const router = express.Router(); -const { createProfile } = require("../controllers/profile"); +const { + updateProfile, + getProfile, + getAllProfiles, + uploadProfilePic, + createProfile +} = require("../controllers/profile"); -router.route("/create").post(createProfile); +router.route("/create").post(protect, validateProfileDetails, createProfile); + +router + .route("/update") + .put(validateMongoId, validateProfileDetails, updateProfile); + +router.route("/").get(protect, getProfile); + +router.route("/upload").post(upload.single("profilePic"), uploadProfilePic); + +router.route("/profiles").get(protect, getAllProfiles); module.exports = router; diff --git a/server/validate.js b/server/validate.js index 40a49c9..5ef4abd 100755 --- a/server/validate.js +++ b/server/validate.js @@ -1,13 +1,17 @@ const { check, validationResult } = require("express-validator"); +const msgPrefix = "Please enter a valid"; +const genderOptions = ["MALE", "FEMALE", "OTHER"]; +const checkFalsyVal = { checkFalsy: true }; + exports.validateRegister = [ - check("username", "Please enter a username").not().isEmpty(), - check("email", "Please enter a valid email address").isEmail(), + check("username", `${msgPrefix} username`).notEmpty(), + check("email", `${msgPrefix} email address`).isEmail(), check( "password", "Please enter a password with 6 or more characters" ).isLength({ - min: 6 + min: 6, }), (req, res, next) => { const errors = validationResult(req); @@ -16,17 +20,79 @@ exports.validateRegister = [ if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() }); next(); - } + }, ]; exports.validateLogin = [ - check("email", "Please enter a valid email address").isEmail(), - check("password", "Password is required").not().isEmpty(), + check("email", `${msgPrefix} email address`).isEmail(), + check("password", "Password is required").notEmpty(), + (req, res, next) => { + const errors = validationResult(req); + + if (!errors.isEmpty()) + return res.status(400).json({ errors: errors.array() }); + next(); + }, +]; + +exports.validateProfileDetails = [ + check("firstName", ` ${msgPrefix} first name`) + .exists(checkFalsyVal) + .trim() + .escape() + .isLength({ max: 20 }), + check("lastName", ` ${msgPrefix} last name`) + .exists(checkFalsyVal) + .trim() + .escape() + .isLength({ max: 20 }), + check("gender", ` ${msgPrefix} gender`) + .exists(checkFalsyVal) + .isIn(genderOptions), + check("birthday", ` ${msgPrefix} birthday format`) + .exists(checkFalsyVal) + .toDate(), + check("email", ` ${msgPrefix} email address`) + .exists(checkFalsyVal) + .trim() + .escape() + .isEmail(), + check("phoneNumber", ` ${msgPrefix} phone number`) + .exists(checkFalsyVal) + .trim() + .isMobilePhone(), + check("location", ` ${msgPrefix} location`) + .exists(checkFalsyVal) + .trim() + .escape() + .isLength({ max: 10 }), + check("profilePic", ` ${msgPrefix} image url`) + .exists(checkFalsyVal) + .escape() + .isURL(), + check("description", ` ${msgPrefix} description format`) + .exists(checkFalsyVal) + .escape() + .isLength({ max: 100 }), + check("availability", ` ${msgPrefix} availability format`) + .exists(checkFalsyVal) + .isArray(), + (req, res, next) => { + const errors = validationResult(req); + + if (!errors.isEmpty()) + return res.status(400).json({ errors: errors.array() }); + next(); + }, +]; + +exports.validateMongoId = [ + check("_id", "Invalid profile ID").exists(checkFalsyVal).isMongoId(), (req, res, next) => { const errors = validationResult(req); if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() }); next(); - } + }, ];