From d2b911d231854fb2a1a157e2f184bb6b826a0ef4 Mon Sep 17 00:00:00 2001 From: Hailey Martin <101282320+Hailo7ts@users.noreply.github.com> Date: Wed, 1 Jan 2025 14:05:12 -0700 Subject: [PATCH] added comment to files --- config/database.js | 12 ++----- config/passport.js | 51 ++++++++++++++++----------- controllers/auth.js | 72 +++++++++++++++++++++------------------ controllers/comments.js | 43 +++++++++++++++++++++++ controllers/home.js | 1 + controllers/posts.js | 21 +++++++++--- middleware/auth.js | 2 ++ middleware/cloudinary.js | 3 ++ middleware/multer.js | 2 ++ models/Comment.js | 26 ++++++++++++++ models/Post.js | 2 ++ models/User.js | 23 +++++++------ routes/comments.js | 14 ++++++++ routes/main.js | 6 ++++ routes/posts.js | 3 +- server.js | 18 +++++++--- views/partials/header.ejs | 2 +- views/post.ejs | 36 ++++++++++++++++++++ 18 files changed, 254 insertions(+), 83 deletions(-) create mode 100644 controllers/comments.js create mode 100644 models/Comment.js create mode 100644 routes/comments.js diff --git a/config/database.js b/config/database.js index 24102b6d5..d8bdd5fee 100644 --- a/config/database.js +++ b/config/database.js @@ -1,18 +1,12 @@ +//import mongoose const mongoose = require("mongoose"); +//mongoose connection const connectDB = async () => { try { - const conn = await mongoose.connect(process.env.DB_STRING, { - useNewUrlParser: true, - useUnifiedTopology: true, - useFindAndModify: false, - useCreateIndex: true, - }); - - console.log(`MongoDB Connected: ${conn.connection.host}`); + await mongoose.connect(process.env.DB_STRING) } catch (err) { console.error(err); - process.exit(1); } }; diff --git a/config/passport.js b/config/passport.js index 6c058d1b8..46ea603b5 100644 --- a/config/passport.js +++ b/config/passport.js @@ -1,41 +1,52 @@ +//import authentication mongoose and user model const LocalStrategy = require("passport-local").Strategy; const mongoose = require("mongoose"); const User = require("../models/User"); + +//export hash and salt module.exports = function (passport) { passport.use( - new LocalStrategy({ usernameField: "email" }, (email, password, done) => { - User.findOne({ email: email.toLowerCase() }, (err, user) => { - if (err) { - return done(err); - } + //validating email and password + new LocalStrategy({ usernameField: "email" }, async (email, password, done) => { + try { + const user = await User.findOne({ email: email.toLowerCase() }); + if (!user) { return done(null, false, { msg: `Email ${email} not found.` }); } + if (!user.password) { return done(null, false, { msg: "Your account was registered using a sign-in provider. To enable password login, sign in using a provider, and then set a password under your user profile.", }); } - user.comparePassword(password, (err, isMatch) => { - if (err) { - return done(err); - } - if (isMatch) { - return done(null, user); - } + + const isMatch = await user.comparePassword(password); + if (isMatch) { + return done(null, user); + } else { return done(null, false, { msg: "Invalid email or password." }); - }); - }); + } + } catch (err) { + return done(err); + } }) ); - passport.serializeUser((user, done) => { - done(null, user.id); - }); - passport.deserializeUser((id, done) => { - User.findById(id, (err, user) => done(err, user)); - }); + //hash and salt + passport.serializeUser((user, done) => { + done(null, user.id); + }); + + passport.deserializeUser(async (id, done) => { + try { + const user = await User.findById(id); + done(null, user); + } catch (err) { + done(err, null); + } + }); }; diff --git a/controllers/auth.js b/controllers/auth.js index 43f893aed..3c9e6f81e 100644 --- a/controllers/auth.js +++ b/controllers/auth.js @@ -1,7 +1,9 @@ +//import for validation user properties const passport = require("passport"); const validator = require("validator"); const User = require("../models/User"); +//login page exports.getLogin = (req, res) => { if (req.user) { return res.redirect("/profile"); @@ -11,7 +13,8 @@ exports.getLogin = (req, res) => { }); }; -exports.postLogin = (req, res, next) => { +//login action +exports.postLogin = async (req, res, next) => { const validationErrors = []; if (!validator.isEmail(req.body.email)) validationErrors.push({ msg: "Please enter a valid email address." }); @@ -44,18 +47,20 @@ exports.postLogin = (req, res, next) => { })(req, res, next); }; +//logout with redirect to home exports.logout = (req, res) => { req.logout(() => { - console.log('User has logged out.') - }) + console.log("User has logged out."); + }); req.session.destroy((err) => { if (err) - console.log("Error : Failed to destroy the session during logout.", err); + console.log("Error: Failed to destroy the session during logout.", err); req.user = null; res.redirect("/"); }); }; +//signup page exports.getSignup = (req, res) => { if (req.user) { return res.redirect("/profile"); @@ -65,7 +70,8 @@ exports.getSignup = (req, res) => { }); }; -exports.postSignup = (req, res, next) => { +//signup action +exports.postSignup = async (req, res, next) => { const validationErrors = []; if (!validator.isEmail(req.body.email)) validationErrors.push({ msg: "Please enter a valid email address." }); @@ -74,45 +80,45 @@ exports.postSignup = (req, res, next) => { msg: "Password must be at least 8 characters long", }); if (req.body.password !== req.body.confirmPassword) - validationErrors.push({ msg: "Passwords do not match" }); + validationErrors.push({ msg: "Passwords do not match." }); if (validationErrors.length) { req.flash("errors", validationErrors); return res.redirect("../signup"); } + req.body.email = validator.normalizeEmail(req.body.email, { gmail_remove_dots: false, }); - const user = new User({ - userName: req.body.userName, - email: req.body.email, - password: req.body.password, - }); + //checkk for exsisting user + try { + const existingUser = await User.findOne({ + $or: [{ email: req.body.email }, { userName: req.body.userName }], + }); + + if (existingUser) { + req.flash("errors", { + msg: "Account with that email address or username already exists.", + }); + return res.redirect("../signup"); + } + + const user = new User({ + userName: req.body.userName, + email: req.body.email, + password: req.body.password, + }); - User.findOne( - { $or: [{ email: req.body.email }, { userName: req.body.userName }] }, - (err, existingUser) => { + await user.save(); + + req.logIn(user, (err) => { if (err) { return next(err); } - if (existingUser) { - req.flash("errors", { - msg: "Account with that email address or username already exists.", - }); - return res.redirect("../signup"); - } - user.save((err) => { - if (err) { - return next(err); - } - req.logIn(user, (err) => { - if (err) { - return next(err); - } - res.redirect("/profile"); - }); - }); - } - ); + res.redirect("/profile"); + }); + } catch (err) { + return next(err); + } }; diff --git a/controllers/comments.js b/controllers/comments.js new file mode 100644 index 000000000..179b2dd10 --- /dev/null +++ b/controllers/comments.js @@ -0,0 +1,43 @@ +const Comment = require("../models/Comment"); + +module.exports = { + createComment: async (req, res) => { + try { + await Comment.create({ + commentText: req.body.comment, + likes: 0, + user: req.user.id, + post: req.params.id + }); + console.log("Comment has been added!"); + res.redirect("/post/"+req.params.id); + } catch (err) { + console.log(err); + } + }, + likeComment: async (req, res) => { + console.log(req.params) + try { + await Comment.findOneAndUpdate( + { _id: req.params.id }, + { + $inc: { likes: 1 }, + } + ); + console.log("Likes +1"); + res.redirect('back'); + } catch (err) { + console.log(err); + } + }, + deleteComment: async (req, res) => { + try { + console.log(req.params.id) + await Comment.findOneAndDelete({_id: req.params.id}); + console.log("Deleted Comment"); + res.redirect("/profile"); + } catch (err) { + res.redirect("/profile"); + } + }, +}; diff --git a/controllers/home.js b/controllers/home.js index 49ba26578..b0f19db74 100644 --- a/controllers/home.js +++ b/controllers/home.js @@ -1,3 +1,4 @@ +//export render for home page module.exports = { getIndex: (req, res) => { res.render("index.ejs"); diff --git a/controllers/posts.js b/controllers/posts.js index a3e2dab5d..a08ce7aac 100644 --- a/controllers/posts.js +++ b/controllers/posts.js @@ -1,7 +1,12 @@ +//import cloudinary model for post const cloudinary = require("../middleware/cloudinary"); -const Post = require("../models/Post"); +const Post = require("../models/Post"); +const Comment = require("../models/Comment"); +//export post controllers module.exports = { + +//reads posts and render getProfile: async (req, res) => { try { const posts = await Post.find({ user: req.user.id }); @@ -21,16 +26,20 @@ module.exports = { getPost: async (req, res) => { try { const post = await Post.findById(req.params.id); - res.render("post.ejs", { post: post, user: req.user }); + const comments = await Comment.find({post: req.params.id}).sort({createdAt: -1}).lean() + res.render("post.ejs", { post: post, user: req.user, comments: comments }); } catch (err) { console.log(err); } }, + +//create posts createPost: async (req, res) => { try { // Upload image to cloudinary const result = await cloudinary.uploader.upload(req.file.path); + //input to create post await Post.create({ title: req.body.title, image: result.secure_url, @@ -45,6 +54,8 @@ module.exports = { console.log(err); } }, + +//update posts likePost: async (req, res) => { try { await Post.findOneAndUpdate( @@ -59,14 +70,16 @@ module.exports = { console.log(err); } }, + +//update posts deletePost: async (req, res) => { try { // Find post by id - let post = await Post.findById({ _id: req.params.id }); + let post = await Post.findById(req.params.id); // Delete image from cloudinary await cloudinary.uploader.destroy(post.cloudinaryId); // Delete post from db - await Post.remove({ _id: req.params.id }); + await Post.findOneAndDelete(req.params.id); console.log("Deleted Post"); res.redirect("/profile"); } catch (err) { diff --git a/middleware/auth.js b/middleware/auth.js index f646630da..10634e3bb 100644 --- a/middleware/auth.js +++ b/middleware/auth.js @@ -1,5 +1,7 @@ +//export for logged in state module.exports = { ensureAuth: function (req, res, next) { + //user logged in direct home if (req.isAuthenticated()) { return next(); } else { diff --git a/middleware/cloudinary.js b/middleware/cloudinary.js index 0960c5b6f..a1eeeca99 100644 --- a/middleware/cloudinary.js +++ b/middleware/cloudinary.js @@ -1,11 +1,14 @@ const cloudinary = require("cloudinary").v2; +//giving access to loggin to cloudinary require("dotenv").config({ path: "./config/.env" }); +//access to cloudinary cloudinary.config({ cloud_name: process.env.CLOUD_NAME, api_key: process.env.API_KEY, api_secret: process.env.API_SECRET, }); +//exports cloudinary module.exports = cloudinary; diff --git a/middleware/multer.js b/middleware/multer.js index c012afe58..45ff479e9 100644 --- a/middleware/multer.js +++ b/middleware/multer.js @@ -1,6 +1,8 @@ +//import for multer const multer = require("multer"); const path = require("path"); +/*stores image string not image*/ module.exports = multer({ storage: multer.diskStorage({}), fileFilter: (req, file, cb) => { diff --git a/models/Comment.js b/models/Comment.js new file mode 100644 index 000000000..7a30cc2b5 --- /dev/null +++ b/models/Comment.js @@ -0,0 +1,26 @@ +const mongoose = require("mongoose"); + +const CommentSchema = new mongoose.Schema({ + commentText: { + type: String, + required: true, + }, + likes: { + type: Number, + required: true, + }, + user: { + type: mongoose.Schema.Types.ObjectId, + ref: "User", + }, + post: { + type: mongoose.Schema.Types.ObjectId, + ref: "Post", + }, + createdAt: { + type: Date, + default: Date.now, + }, +}); + +module.exports = mongoose.model("Comment", CommentSchema); diff --git a/models/Post.js b/models/Post.js index f7d14c981..12b776967 100644 --- a/models/Post.js +++ b/models/Post.js @@ -1,5 +1,7 @@ +//import for schema const mongoose = require("mongoose"); +//schema for properties in posts const PostSchema = new mongoose.Schema({ title: { type: String, diff --git a/models/User.js b/models/User.js index afe8afc36..eda09d8a8 100644 --- a/models/User.js +++ b/models/User.js @@ -1,14 +1,16 @@ +//import encryption and mongoose for schema const bcrypt = require("bcrypt"); const mongoose = require("mongoose"); +//Schema for User const UserSchema = new mongoose.Schema({ - userName: { type: String, unique: true }, - email: { type: String, unique: true }, + userName: { type: String, unique: true }, //check db for unique + email: { type: String, unique: true }, //check db for unique password: String, }); // Password hash middleware. - +//password hashing and encryption UserSchema.pre("save", function save(next) { const user = this; if (!user.isModified("password")) { @@ -29,14 +31,15 @@ UserSchema.pre("save", function save(next) { }); // Helper method for validating user's password. - -UserSchema.methods.comparePassword = function comparePassword( - candidatePassword, - cb -) { - bcrypt.compare(candidatePassword, this.password, (err, isMatch) => { - cb(err, isMatch); +//decrypt and validate +UserSchema.methods.comparePassword = function (candidatePassword) { + return new Promise((resolve, reject) => { + bcrypt.compare(candidatePassword, this.password, (err, isMatch) => { + if (err) return reject(err); + resolve(isMatch); + }); }); }; +//export user schema module.exports = mongoose.model("User", UserSchema); diff --git a/routes/comments.js b/routes/comments.js new file mode 100644 index 000000000..57d267e54 --- /dev/null +++ b/routes/comments.js @@ -0,0 +1,14 @@ +//imports +const express = require("express"); +const router = express.Router(); +const commentsController = require("../controllers/comments"); +const { ensureAuth, ensureGuest } = require("../middleware/auth"); + +//crud operations for comments +router.post("/createComment/:id", commentsController.createComment); + +router.put("/likeComment/:id/:post", commentsController.likeComment); + +router.delete("/deleteComment/:id", commentsController.deleteComment); + +module.exports = router; diff --git a/routes/main.js b/routes/main.js index d6883000e..2e44be46b 100644 --- a/routes/main.js +++ b/routes/main.js @@ -6,12 +6,18 @@ const postsController = require("../controllers/posts"); const { ensureAuth, ensureGuest } = require("../middleware/auth"); //Main Routes - simplified for now + +//get home page router.get("/", homeController.getIndex); +//get user posts router.get("/profile", ensureAuth, postsController.getProfile); +//get all user posts router.get("/feed", ensureAuth, postsController.getFeed); +//login and logout router.get("/login", authController.getLogin); router.post("/login", authController.postLogin); router.get("/logout", authController.logout); +//signup router.get("/signup", authController.getSignup); router.post("/signup", authController.postSignup); diff --git a/routes/posts.js b/routes/posts.js index aa463ac90..7340895d9 100644 --- a/routes/posts.js +++ b/routes/posts.js @@ -1,10 +1,11 @@ +//imports const express = require("express"); const router = express.Router(); const upload = require("../middleware/multer"); const postsController = require("../controllers/posts"); const { ensureAuth, ensureGuest } = require("../middleware/auth"); -//Post Routes - simplified for now +//Post Routes - simplified for now CRUD router.get("/:id", ensureAuth, postsController.getPost); router.post("/createPost", upload.single("file"), postsController.createPost); diff --git a/server.js b/server.js index 1718db010..16025ee33 100644 --- a/server.js +++ b/server.js @@ -1,3 +1,4 @@ +/*fileimports*/ const express = require("express"); const app = express(); const mongoose = require("mongoose"); @@ -10,6 +11,13 @@ const logger = require("morgan"); const connectDB = require("./config/database"); const mainRoutes = require("./routes/main"); const postRoutes = require("./routes/posts"); +const commentRoutes = require("./routes/comments"); +const cloudinary = require('cloudinary').v2 + +const PORT = process.env.PORT || 3000 + +//Connect To Database +connectDB(); //Use .env file in config folder require("dotenv").config({ path: "./config/.env" }); @@ -17,8 +25,6 @@ require("dotenv").config({ path: "./config/.env" }); // Passport config require("./config/passport")(passport); -//Connect To Database -connectDB(); //Using EJS for views app.set("view engine", "ejs"); @@ -56,8 +62,10 @@ app.use(flash()); //Setup Routes For Which The Server Is Listening app.use("/", mainRoutes); app.use("/post", postRoutes); +app.use("/comment", commentRoutes); //Server Running -app.listen(process.env.PORT, () => { - console.log("Server is running, you better catch it!"); -}); +mongoose.connection.once('open', () => { + console.log('Connected to MongoDB') + app.listen(PORT, () => console.log(`Server running on port ${PORT}`)) +}) diff --git a/views/partials/header.ejs b/views/partials/header.ejs index 011ff2239..39f44e27a 100644 --- a/views/partials/header.ejs +++ b/views/partials/header.ejs @@ -29,7 +29,7 @@

Binary Upload Boom

- The #100Devs Social Network + The RC Social Network
diff --git a/views/post.ejs b/views/post.ejs index c36a1c946..da82fc2aa 100644 --- a/views/post.ejs +++ b/views/post.ejs @@ -27,6 +27,42 @@

<%= post.caption %>

+ +
+

Add a comment

+
+
+ + +
+ +
+
Return to Profile Return to Feed