From 70e486dced6067bfcf05b59fa64fcdd969f0cf31 Mon Sep 17 00:00:00 2001 From: Hariket Sukeshkumar Sheth Date: Sat, 26 Aug 2023 10:27:08 +0530 Subject: [PATCH 1/6] Added Passport Configuration --- .gitignore | 1 + app.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/.gitignore b/.gitignore index a3ce655..f52cb10 100644 --- a/.gitignore +++ b/.gitignore @@ -128,6 +128,7 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* +yarn.lock # Personal Folder personal/ diff --git a/app.js b/app.js index 50b84d1..2e2f282 100644 --- a/app.js +++ b/app.js @@ -5,12 +5,18 @@ const expressLayouts = require('express-ejs-layouts'); const cookieParser = require('cookie-parser'); const session = require('express-session'); const MongoStore = require('connect-mongo'); +const passport = require('passport'); +const LocalStrategy = require('passport-local').Strategy; +const bcrypt = require('bcrypt'); const connectDB = require('./server/config/db.js'); const app = express(); const port = 5000 || process.env.PORT; +// User Model (replace with actual user Model created) +const User = require('./server/models/User'); + app.use(express.urlencoded({ extended: true })); app.use(express.json()); //allows to use form values app.use(cookieParser()); @@ -35,6 +41,42 @@ app.use(expressLayouts); app.set('layout', './layouts/main'); app.set('view engine', 'ejs'); +// Passport Configuration +passport.use(new LocalStrategy( + {usernameField: 'email' }, + async(email, password, done) => { + try{ + const user = await User.findOne({ email }); + + if(!user){ + return done(null, false, { message: 'Incorrect email or password' }); + } + + const isMatch = await bcrypt.compare(password, user.password); + if(isMatch){ + return done(null, user); + } else{ + return done(null, false, { message: 'Incorrect email or password' }); + } + } catch(err){ + return done(err); + } + } +)); + +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); + } +}); + app.use('/', require('./server/routes/main')) app.use('/', require('./server/routes/admin')) From 2e2f59010da113d7094a1de4f28435416e2d849a Mon Sep 17 00:00:00 2001 From: Hariket Sukeshkumar Sheth Date: Sat, 26 Aug 2023 10:30:59 +0530 Subject: [PATCH 2/6] Added Registration Route --- app.js | 118 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 69 insertions(+), 49 deletions(-) diff --git a/app.js b/app.js index 2e2f282..f0a9b88 100644 --- a/app.js +++ b/app.js @@ -1,21 +1,21 @@ -require('dotenv').config(); +require("dotenv").config(); -const express = require('express'); -const expressLayouts = require('express-ejs-layouts'); -const cookieParser = require('cookie-parser'); -const session = require('express-session'); -const MongoStore = require('connect-mongo'); -const passport = require('passport'); -const LocalStrategy = require('passport-local').Strategy; -const bcrypt = require('bcrypt'); +const express = require("express"); +const expressLayouts = require("express-ejs-layouts"); +const cookieParser = require("cookie-parser"); +const session = require("express-session"); +const MongoStore = require("connect-mongo"); +const passport = require("passport"); +const LocalStrategy = require("passport-local").Strategy; +const bcrypt = require("bcrypt"); -const connectDB = require('./server/config/db.js'); +const connectDB = require("./server/config/db.js"); const app = express(); const port = 5000 || process.env.PORT; // User Model (replace with actual user Model created) -const User = require('./server/models/User'); +const User = require("./server/models/User"); app.use(express.urlencoded({ extended: true })); app.use(express.json()); //allows to use form values @@ -24,62 +24,82 @@ app.use(cookieParser()); // Connect to MongoDB connectDB(); -app.use(express.static('public')); +app.use(express.static("public")); -app.use(session({ - secret: 'keyboard cat', +app.use( + session({ + secret: "keyboard cat", resave: false, saveUninitialized: true, store: MongoStore.create({ - mongoUrl: process.env.MONGODB_URI + mongoUrl: process.env.MONGODB_URI, }), - //cookie: { maxAge: new Date ( Date.now() + (3600000) ) } -})); + //cookie: { maxAge: new Date ( Date.now() + (3600000) ) } + }) +); // Templating engine app.use(expressLayouts); -app.set('layout', './layouts/main'); -app.set('view engine', 'ejs'); +app.set("layout", "./layouts/main"); +app.set("view engine", "ejs"); // Passport Configuration -passport.use(new LocalStrategy( - {usernameField: 'email' }, - async(email, password, done) => { - try{ - const user = await User.findOne({ email }); - - if(!user){ - return done(null, false, { message: 'Incorrect email or password' }); - } - - const isMatch = await bcrypt.compare(password, user.password); - if(isMatch){ - return done(null, user); - } else{ - return done(null, false, { message: 'Incorrect email or password' }); - } - } catch(err){ - return done(err); +passport.use( + new LocalStrategy( + { usernameField: "email" }, + async (email, password, done) => { + try { + const user = await User.findOne({ email }); + + if (!user) { + return done(null, false, { message: "Incorrect email or password" }); } + + const isMatch = await bcrypt.compare(password, user.password); + if (isMatch) { + return done(null, user); + } else { + return done(null, false, { message: "Incorrect email or password" }); + } + } catch (err) { + return done(err); + } } -)); + ) +); passport.serializeUser((user, done) => { - done(null, user.id); + done(null, user.id); }); -passport.deserializeUser(async(id, done)=>{ - try{ - const user = await User.findById(id); - done (null, user); - } catch(err){ - done(err); - } +passport.deserializeUser(async (id, done) => { + try { + const user = await User.findById(id); + done(null, user); + } catch (err) { + done(err); + } }); -app.use('/', require('./server/routes/main')) -app.use('/', require('./server/routes/admin')) +// Registration Route +app.post("/register", async (req, res) => { + const { name, email, password } = req.body; + const hashedPassword = await bcrypt.hash(password, 10); + + try { + const newUser = new User({ name, email, passowrd: hashedPassword }); + await newUser.save(); + res.redirect("/login"); + } catch (err) { + res.render("register", { error: 'An error occured during registration' }); + } +}); + +// Login Route + +app.use("/", require("./server/routes/main")); +app.use("/", require("./server/routes/admin")); app.listen(port, (req, res) => { - console.log(`Server is running on port ${port}`); + console.log(`Server is running on port ${port}`); }); From 652737d1127495dad9b9617edef778d4fe188461 Mon Sep 17 00:00:00 2001 From: Hariket Sukeshkumar Sheth Date: Sat, 26 Aug 2023 10:33:02 +0530 Subject: [PATCH 3/6] Added Login Route --- app.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index f0a9b88..4ce0d0f 100644 --- a/app.js +++ b/app.js @@ -91,11 +91,19 @@ app.post("/register", async (req, res) => { await newUser.save(); res.redirect("/login"); } catch (err) { - res.render("register", { error: 'An error occured during registration' }); + res.render("register", { error: "An error occured during registration" }); } }); // Login Route +app.post( + "/login", + passport.authenticate("local", { + successRedirect: "/dashboard", + failureRedirect: "/login", + failureFlash: true, + }) +); app.use("/", require("./server/routes/main")); app.use("/", require("./server/routes/admin")); From daeef8d531a46f87560a481220bcd6acba1c57e2 Mon Sep 17 00:00:00 2001 From: Hariket Sukeshkumar Sheth Date: Sat, 26 Aug 2023 10:34:22 +0530 Subject: [PATCH 4/6] Logout Route Added --- app.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app.js b/app.js index 4ce0d0f..59e76b0 100644 --- a/app.js +++ b/app.js @@ -105,6 +105,12 @@ app.post( }) ); +// Logout Route +app.get("/logout", (req, res) => { + req.logout(); + res.redirect("/"); +}); + app.use("/", require("./server/routes/main")); app.use("/", require("./server/routes/admin")); From d4b02c68397fee7f37d7ae6077fdbca1ef3ce0bf Mon Sep 17 00:00:00 2001 From: Hariket Sukeshkumar Sheth Date: Sat, 26 Aug 2023 11:20:39 +0530 Subject: [PATCH 5/6] Updated Routes and Registration --- app.js | 29 ----------------------------- server/routes/admin.js | 25 +++++++++++++++++++++---- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/app.js b/app.js index 59e76b0..a9ab5d8 100644 --- a/app.js +++ b/app.js @@ -81,35 +81,6 @@ passport.deserializeUser(async (id, done) => { } }); -// Registration Route -app.post("/register", async (req, res) => { - const { name, email, password } = req.body; - const hashedPassword = await bcrypt.hash(password, 10); - - try { - const newUser = new User({ name, email, passowrd: hashedPassword }); - await newUser.save(); - res.redirect("/login"); - } catch (err) { - res.render("register", { error: "An error occured during registration" }); - } -}); - -// Login Route -app.post( - "/login", - passport.authenticate("local", { - successRedirect: "/dashboard", - failureRedirect: "/login", - failureFlash: true, - }) -); - -// Logout Route -app.get("/logout", (req, res) => { - req.logout(); - res.redirect("/"); -}); app.use("/", require("./server/routes/main")); app.use("/", require("./server/routes/admin")); diff --git a/server/routes/admin.js b/server/routes/admin.js index f8c4a1a..822bbdf 100644 --- a/server/routes/admin.js +++ b/server/routes/admin.js @@ -4,6 +4,7 @@ const Post = require('../models/Post'); const User = require('../models/User'); const bcrypt = require('bcrypt'); const jwt = require('jsonwebtoken'); +const { body, validationResult } = require('express-validator'); const adminLayout = '../views/layouts/admin'; const jwtSecret = process.env.JWT_SECRET; @@ -13,22 +14,38 @@ const jwtSecret = process.env.JWT_SECRET; * POST / * Admin - Register */ -router.post('/register', async (req, res) => { +router.post('/register', [ + // Validate username + body('username') + .notEmpty().withMessage('Username is required') + .isLength({ min: 4 }).withMessage('Username must be at least 4 characters'), + + // Validate password + body('password') + .notEmpty().withMessage('Password is required') + .isLength({ min: 6 }).withMessage('Password must be at least 6 characters') +], async (req, res) => { try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ errors: errors.array() }); + } + const { username, password } = req.body; const hashedPassword = await bcrypt.hash(password, 10); + try { const user = await User.create({ username, password: hashedPassword }); res.status(201).json({ message: 'User Created', user }); } catch (error) { if (error.code === 11000) { - res.status(409).json({ message: 'User already in use' }); + return res.status(409).json({ message: 'User already in use' }); } - res.status(500).json({ message: 'Internal server error' }) + res.status(500).json({ message: 'Internal server error' }); } - } catch (error) { console.log(error); + res.status(500).json({ message: 'Internal server error' }); } }); From 33d91893174b924c3cb315de3708ce73796eeb8c Mon Sep 17 00:00:00 2001 From: Hariket Sukeshkumar Sheth Date: Sat, 26 Aug 2023 11:21:12 +0530 Subject: [PATCH 6/6] Added User Profile Update Feature --- server/routes/admin.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/server/routes/admin.js b/server/routes/admin.js index 822bbdf..7f8828f 100644 --- a/server/routes/admin.js +++ b/server/routes/admin.js @@ -117,6 +117,47 @@ router.post('/admin', async (req, res) => { } }); +/** + * PUT / + * User - Update Profile + */ +router.put('/update-profile', [ + authMiddleware, // Authenticate the user + body('password') + .optional() + .isLength({ min: 6 }).withMessage('New password must be at least 6 characters') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ errors: errors.array() }); + } + + const userId = req.userId; + const { password } = req.body; + + try { + const user = await User.findById(userId); + if (!user) { + return res.status(404).json({ message: 'User not found' }); + } + + if (password) { + const hashedPassword = await bcrypt.hash(password, 10); + user.password = hashedPassword; + } + + await user.save(); + res.status(200).json({ message: 'Profile updated successfully' }); + } catch (error) { + console.log(error); + res.status(500).json({ message: 'Internal server error' }); + } + } catch (error) { + console.log(error); + res.status(500).json({ message: 'Internal server error' }); + } +}); // Post request` router.post('/admin', async (req, res) => {