diff --git a/app.js b/app.js index 56eb793..741673f 100644 --- a/app.js +++ b/app.js @@ -83,7 +83,6 @@ app.get('/forgotPassword', (req, res) => { return res.status(status.Ok); }); - // Reset with token given to user via email app.get('/reset/:token', async (req, res) => { const token = req.params.token; @@ -106,7 +105,6 @@ app.get('/reset/:token', async (req, res) => { }); }); - // 404 handler - keep the actual notFound route please // REALLY DONT DELETE THIS app.get('/notFound', (req, res) => { diff --git a/src/auth/authentication.js b/src/auth/authentication.js index d65e9c6..d32f0a8 100644 --- a/src/auth/authentication.js +++ b/src/auth/authentication.js @@ -12,10 +12,18 @@ module.exports = (users) => { const router = require("express").Router(); router.get("/logout", (req, res) => { - req.session.destroy(); - return res.redirect('/login'); + req.session.destroy((err) => { + if (err) { + console.error("Failed to destroy session: ", err); + res.status(status.InternalServerError); + return res.redirect("back"); + } + + res.status(status.Ok); + return res.redirect('/login'); + }); }); - + router.post("/login", async (req, res) => { const credentialSchema = joi.object({ @@ -46,10 +54,19 @@ module.exports = (users) => { req.session.authenticated = true; req.session.userId = user._id; - req.session.email = req.body.email; req.session.errMessage = ""; - res.redirect("/home"); - return res.status(status.Ok); + + req.session.save((err) => { + if (err) { + console.error("Failed to save session: ", err); + req.session.errMessage = "Failed to save session. Please try again."; + res.status(status.InternalServerError); + return res.redirect("/login"); + } + + res.status(status.Ok); + return res.redirect("/home"); + }); }); }); @@ -97,11 +114,20 @@ module.exports = (users) => { } req.session.authenticated = true; - req.session.email = req.body.email; req.session.userId = results.insertedId; - req.session.errMessage = ""; - return res.status(status.Ok).redirect("/home"); + + req.session.save((err) => { + if (err) { + console.error("Failed to save session: ", err); + req.session.errMessage = "Please login"; + res.status(status.Ok); + return res.redirect("/login"); + } + + res.status(status.Ok); + return res.redirect("/home"); + }); }); }); diff --git a/src/auth/forgotPass.js b/src/auth/forgotPass.js index 698a500..e0022c3 100644 --- a/src/auth/forgotPass.js +++ b/src/auth/forgotPass.js @@ -4,6 +4,7 @@ const joi = require('joi'); const nodeMail = require('nodemailer'); const bcrypt = require('bcrypt'); require('dotenv').config(); + const PORT = process.env.PORT; const transporter = nodeMail.createTransport({ @@ -13,7 +14,7 @@ const transporter = nodeMail.createTransport({ pass: process.env.EMAIL_PASS, } }); -// users info + module.exports = (users) => { const router = express.Router(); @@ -73,7 +74,7 @@ module.exports = (users) => { }); const valid = passwordSchema.validate({ password, confirmPassword }); if (valid.error) { - console.log("houston we have a problem"); + console.log("houston we have a problem"); // nice req.session.error = 'Invalid input'; res.status(status.BadRequest); return res.redirect(`/reset/${token}`); diff --git a/src/auth/middleware.js b/src/auth/middleware.js index 5c24807..b641877 100644 --- a/src/auth/middleware.js +++ b/src/auth/middleware.js @@ -1,5 +1,6 @@ const status = require("../util/statuses"); const session = require("express-session"); +const ObjectId = require("mongodb").ObjectId; // Get all names of user routes let userRouter = require("../router/user")((req, res, next) => next(), null, null, null); @@ -18,26 +19,53 @@ const createMiddleware = (users) => { return res.status(status.NotFound).redirect("/notFound"); } - if (!req.session.authenticated || !req.session.email) { + if (!req.session.authenticated || !req.session.userId) { req.session.errMessage = "Please login to view that resource"; res.redirect("/login"); return res.status(status.Unauthorized); } if (!req.session.user) { - let user = await users.findOne({ "email": req.session.email }).then((user) => user); + let user = await users.findOne({ _id: new ObjectId(req.session.userId) }).then((user) => user); if (!user) { - req.session.errMessage = "User not found"; - res.redirect("/login"); - return res.status(status.Unauthorized); + return req.session.destroy((err) => { + if (err) { + console.error("Failed to destroy session: ", err); + req.session.errMessage = "Failed to logout. Please try again"; + res.status(status.InternalServerError); + return res.redirect("/home"); + } + + req.session.errMessage = "User not found"; + res.status(status.NotFound); + res.redirect("/login"); + }); } - + req.session.user = user; + return req.session.save((err) => { + if (err) { + console.error("Failed to save session: ", err); + + return req.session.destroy((err) => { + req.session.errMessage = "An error occured, please login again."; + + if (err) { + console.error("Failed to destroy session: ", err); + } + + res.status(status.InternalServerError); + res.redirect("/login"); + }); + } + + next(); + }); } next(); }; -} +}; module.exports = createMiddleware; diff --git a/src/router/user.js b/src/router/user.js index 16c51f5..da956c2 100644 --- a/src/router/user.js +++ b/src/router/user.js @@ -86,7 +86,7 @@ module.exports = (middleware, users, plans, assets) => { }); router.get('/assets', async (req, res) => { - let userAssets = await assets.find({ userId: new ObjectId(req.session.user._id) }).toArray(); + let userAssets = await assets.find({ userId: new ObjectId(req.session.userId) }).toArray(); res.render('assets', { user: req.session.user, errMessage: req.session.errMessage, @@ -99,16 +99,16 @@ module.exports = (middleware, users, plans, assets) => { router.get('/plans', async (req, res) => { try { - const userPlansFromDB = await plans.find({ userId: new ObjectId(req.session.user._id) }).toArray(); + const userPlansFromDB = await plans.find({ userId: new ObjectId(req.session.userId) }).toArray(); // Use a for...of loop for proper async/await behavior in series for updates for (const plan of userPlansFromDB) { - const percentage = await calculatePlanProgress(plan, assets, req.session.user._id); + const percentage = await calculatePlanProgress(plan, assets, req.session.userId); await updatePlanProgressInDB(plan._id, percentage, plans); // Pass the 'plans' collection } // Re-fetch plans to get updated progress for rendering - const updatedUserPlans = await plans.find({ userId: new ObjectId(req.session.user._id) }).toArray(); + const updatedUserPlans = await plans.find({ userId: new ObjectId(req.session.userId) }).toArray(); res.render('plans', { user: req.session.user, @@ -126,18 +126,17 @@ module.exports = (middleware, users, plans, assets) => { try { const planId = req.params.id; - let userAssets = await assets.find({ userId: new ObjectId(req.session.user._id) }).toArray(); - + let userAssets = await assets.find({ userId: new ObjectId(req.session.userId) }).toArray(); if (!ObjectId.isValid(planId)) { req.session.errMessage = "Invalid plan ID format."; return res.status(status.BadRequest).redirect('/plans'); } - const plan = await plans.findOne({ userId: new ObjectId(req.session.user._id), _id: new ObjectId(planId) }); + const plan = await plans.findOne({ userId: new ObjectId(req.session.userId), _id: new ObjectId(planId) }); if (!plan) { - console.log(`Plan not found with ID: ${planId} for user: ${req.session.user.email}`); + console.log(`Plan not found with ID: ${planId} for user: ${req.session.userId}`); req.session.errMessage = "Plan not found or you do not have permission to view it."; return res.status(status.NotFound).redirect('/plans'); } @@ -197,7 +196,7 @@ module.exports = (middleware, users, plans, assets) => { return; } const newPlan = { - userId: new ObjectId(req.session.user._id), + userId: new ObjectId(req.session.userId), name: value.name, retirementAge: value.retirementAge, retirementExpenses: value.retirementExpenses, @@ -207,7 +206,7 @@ module.exports = (middleware, users, plans, assets) => { }; try { - await plans.insertOne({ userId: new ObjectId(req.session.user._id), ...newPlan }); + await plans.insertOne({ userId: new ObjectId(req.session.userId), ...newPlan }); req.session.errMessage = ""; res.redirect('/plans'); } @@ -280,7 +279,7 @@ module.exports = (middleware, users, plans, assets) => { } users.updateOne( - { _id: new ObjectId(req.session.user._id) }, + { _id: new ObjectId(req.session.userId) }, { $set: { financialData: true, @@ -295,13 +294,13 @@ module.exports = (middleware, users, plans, assets) => { } ).then((result) => { if (result.matchedCount === 0) { - console.log(`User not found during questionnaire update: ${req.session.user.email}`); + console.log(`User not found during questionnaire update: ${req.session.userId}`); req.session.errMessage = "User session invalid. Please log in again."; res.status(status.NotFound).redirect("/login"); return; } if (result.modifiedCount === 0 && result.matchedCount === 1) { - console.log(`User questionnaire data unchanged (already up-to-date): ${req.session.user.email}`); + console.log(`User questionnaire data unchanged (already up-to-date): ${req.session.userId}`); } req.session.user.financialData = true; @@ -333,7 +332,7 @@ module.exports = (middleware, users, plans, assets) => { if (valid.err) { req.session.errMessage = "Invalid input", - res.status(status.BadRequest); + res.status(status.BadRequest); return res.redirect("/profile"); } @@ -351,17 +350,17 @@ module.exports = (middleware, users, plans, assets) => { } users.updateOne( - { email: req.session.email }, + { _id: new ObjectId(req.session.userId) }, { $set: update } ).then((result) => { if (result.matchedCount === 0) { - console.log(`User not found during account update: ${req.session.email}`); + console.log(`User not found during account update: ${req.session.userId}`); req.session.errMessage = "User session invalid. Please log in again."; res.status(status.NotFound).redirect("/login"); return; } if (result.modifiedCount === 0 && result.matchedCount === 1) { - console.log(`User account data unchanged (already up-to-date): ${req.session.email}`); + console.log(`User account data unchanged (already up-to-date): ${req.session.userId}`); } req.session.errMessage = ""; @@ -393,7 +392,7 @@ module.exports = (middleware, users, plans, assets) => { } let newAsset = { - userId: new ObjectId(req.session.user._id), + userId: new ObjectId(req.session.userId), ...req.body, updatedAt: new Date(), }; @@ -437,7 +436,7 @@ module.exports = (middleware, users, plans, assets) => { return res.redirect("/assets"); } - if (req.body.userId != req.session.user._id) { + if (req.body.userId != req.session.userId) { req.session.errMessage = "Cannot change asset owner", res.status(status.BadRequest); return res.redirect("/assets"); @@ -507,20 +506,20 @@ module.exports = (middleware, users, plans, assets) => { router.post("/deleteUser", (req, res) => { // not as critical if results aren't as expected only if crashing - assets.deleteMany({ userId: new ObjectId(req.session.user._id) }).catch((err) => { + assets.deleteMany({ userId: new ObjectId(req.session.userId) }).catch((err) => { console.error("Error deleting user assets: ", err); req.session.errMessage = "An error occured while deleting your account. Please try again."; return res.status(status.InternalServerError).redirect("/profile"); }); - plans.deleteMany({ userId: new ObjectId(req.session.user._id) }).catch((err) => { + plans.deleteMany({ userId: new ObjectId(req.session.userId) }).catch((err) => { console.error("Error deleting user assets: ", err); req.session.errMessage = "An error occured while deleting your account. Please try again."; return res.status(status.InternalServerError).redirect("/profile"); }); users.deleteOne( - { _id: new ObjectId(req.session.user._id) }, + { _id: new ObjectId(req.session.userId) }, ).then((result) => { if (result.deletedCount === 0) { console.error(`User not found: ${req.body.id}`);