From f7e4775ed3146bfcee07fea281dd19be4b2aaafc Mon Sep 17 00:00:00 2001 From: viviannTam Date: Tue, 30 Jan 2024 12:52:52 +0800 Subject: [PATCH 1/6] reset password --- consumerWebsite/app.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/consumerWebsite/app.js b/consumerWebsite/app.js index ab82e57..75fce1e 100644 --- a/consumerWebsite/app.js +++ b/consumerWebsite/app.js @@ -1,12 +1,14 @@ const express = require("express"); const { rateLimit } = require("express-rate-limit"); const path = require("path"); +const router = require('./routes/user'); +const errorHandler = require('./utils/errorHandler'); const app = express(); const ejs = require("ejs"); module.exports = app; -process.nextTick(() => require("./mqttApp")); +//process.nextTick(() => require("./mqttApp")); app.use(express.json()); app.set("json spaces", 2); @@ -68,6 +70,7 @@ app.use(function (err, req, res, next) { keyErrors[item.path] = item.message; } } + res.status = 422; } if (![404, 401, 422].includes(err.status || res.status)) { @@ -76,6 +79,7 @@ app.use(function (err, req, res, next) { console.error("========================================="); } res.status(err.status || 500); + // res.status(err.status || 500); if (req.get('Content-Type') && req.get('Content-Type').includes("json")) { res.json({ @@ -91,4 +95,15 @@ app.use(function (err, req, res, next) { keyErrors, }); } +}); + +//reset password logic +app.use("/api/user", router) + +app.use(errorHandler); + +const PORT = 3000; + +app.listen(PORT, () => { + console.log('server running on port ' + PORT); }); \ No newline at end of file From ac98abc23ed9a566820c9e40e08e9c93d5a48415 Mon Sep 17 00:00:00 2001 From: viviannTam Date: Tue, 30 Jan 2024 13:03:58 +0800 Subject: [PATCH 2/6] a --- consumerWebsite/controller/user_controller.js | 110 ++++++++++++++++++ consumerWebsite/routes/user.js | 4 + consumerWebsite/utils/error.js | 13 +++ consumerWebsite/utils/errorHandler.js | 0 consumerWebsite/utils/object_isEmpty.js | 8 ++ 5 files changed, 135 insertions(+) create mode 100644 consumerWebsite/controller/user_controller.js create mode 100644 consumerWebsite/utils/error.js create mode 100644 consumerWebsite/utils/errorHandler.js create mode 100644 consumerWebsite/utils/object_isEmpty.js diff --git a/consumerWebsite/controller/user_controller.js b/consumerWebsite/controller/user_controller.js new file mode 100644 index 0000000..5cc49e1 --- /dev/null +++ b/consumerWebsite/controller/user_controller.js @@ -0,0 +1,110 @@ +const connection = require('../database/mySQL'); +const { isEmpty } = require('../utils/object_isEmpty'); +const AppError = require('../utils/error'); +const bcrypt = require('bcryptjs'); +const { USER_MODEL, USER_LOGIN_MODEL, FORGOT_PASSWORD_MODEL, RESET_PASSWORD_MODEL } = require('../database/model/userModel'); +const nodemailer = require('nodemailer'); + +exports.user_forgotPassword = (req, res, next) => { + + //Check the form data is found or not + if (isEmpty(req.body)) return next(new AppError('form data not found', 400)); + + try { + + //Check the form data is valid or not + const { error } = FORGOT_PASSWORD_MODEL.validate(req.body); + + if (error) return next(new AppError(error.details[0].message, 400)); + + connection.query("SELECT * FROM user WHERE email = ?", [[req.body.email]], async (err, data1, fields) => { + if (err) return next(new AppError(err, 500)); + + if (data1.length == 0) { + return next(new AppError("user not exist", 400)) + } + + const otp = Math.floor(1000 + Math.random() * 9000); + + const otpExpier = new Date(); + otpExpier.setMinutes(otpExpier.getMinutes() + 1); + + connection.query("UPDATE user SET otp = ?, otpExpire = ? WHERE email = ?", [otp, otpExpier, req.body.email], (err, data2, fields) => { + if (err) return next(new AppError(err, 500)); + + const transporter = nodemailer.createTransport({ + service: 'Gmail', + auth: { + user: 'ecosavertp@gmail.com', + pass: 'Ecosaver1234!', + }, + }); + + const mailOptions = { + from: 'ecosavertp@gmail.com', + to: req.body.email, + subject: 'Password reset OTP', + text: `Your OTP (It is expired after 1 min) : ${otp}`, + }; + + transporter.sendMail(mailOptions, (error, info) => { + if (error) { + return next(new AppError(error, 500)); + } else { + res.json({ + data: "Your OTP send to the email" + }) + } + }); + + }) + + }) + + } + catch (err) { + return next(new AppError(err, 500)); + } +} + +exports.user_resetPassword = (req, res, next) => { + + const body = req.body; + const password = body.password; + const confirmPassword = body.confirmPassword; + + if (isEmpty(body)) return next(new AppError('form data not found', 400)); + + try { + + const { error } = RESET_PASSWORD_MODEL.validate(body); + + if (error) return next(new AppError(error.details[0].message, 400)); + + if (password.localeCompare(confirmPassword) != 0) return next(new AppError('passwords are not equal', 400)); + + connection.query("SELECT * FROM user WHERE otp = ? AND otpExpire > NOW()", [[body.otp]], async (err, data, fields) => { + if (err) return next(new AppError(err, 500)); + + if (data.length == 0) return next(new AppError('Invalid or expired OTP', 400)); + + const solt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(password, solt); + + connection.query("UPDATE user SET password = ?, otp = null, otpExpire = null WHERE otp = ?", [hashedPassword, body.otp], async (err, data, fields) => { + if (err) return next(new AppError(err, 500)); + + res.json({ + data: 'Password reset successful' + }) + + }) + + }) + + } + catch (err) { + return next(new AppError(err, 500)); + } + +} \ No newline at end of file diff --git a/consumerWebsite/routes/user.js b/consumerWebsite/routes/user.js index e81ac90..001d27b 100644 --- a/consumerWebsite/routes/user.js +++ b/consumerWebsite/routes/user.js @@ -76,4 +76,8 @@ router.delete("/delete", async function (req, res, next) { }); }); +const { user_register, user_login, user_forgotPassword, user_resetPassword } = require('../controller/user_controller'); +router.route("/forgotPassword").post(user_forgotPassword); +router.route("/resetPassword").post(user_resetPassword); + module.exports = router; diff --git a/consumerWebsite/utils/error.js b/consumerWebsite/utils/error.js new file mode 100644 index 0000000..a4ad20c --- /dev/null +++ b/consumerWebsite/utils/error.js @@ -0,0 +1,13 @@ +class AppError extends Error { + constructor(msg, statusCode) { + super(msg); + + this.statusCode = statusCode; + this.error = `${statusCode}`.startsWith('4') ? 'fail' : 'error'; + this.isOperational = true; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = AppError; \ No newline at end of file diff --git a/consumerWebsite/utils/errorHandler.js b/consumerWebsite/utils/errorHandler.js new file mode 100644 index 0000000..e69de29 diff --git a/consumerWebsite/utils/object_isEmpty.js b/consumerWebsite/utils/object_isEmpty.js new file mode 100644 index 0000000..c4099a8 --- /dev/null +++ b/consumerWebsite/utils/object_isEmpty.js @@ -0,0 +1,8 @@ +//Checking that the request body is empty +exports.isEmpty = function (obj) { + for(var prop in obj) { + if(obj.hasOwnProperty(prop)) + return false; + } + return JSON.stringify(obj) === JSON.stringify({}); +} \ No newline at end of file From da46db3134112d6b07580e84d22878c5a66a14b3 Mon Sep 17 00:00:00 2001 From: viviannTam Date: Tue, 30 Jan 2024 13:05:01 +0800 Subject: [PATCH 3/6] a --- consumerWebsite/routes/user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consumerWebsite/routes/user.js b/consumerWebsite/routes/user.js index 001d27b..543077b 100644 --- a/consumerWebsite/routes/user.js +++ b/consumerWebsite/routes/user.js @@ -76,7 +76,7 @@ router.delete("/delete", async function (req, res, next) { }); }); -const { user_register, user_login, user_forgotPassword, user_resetPassword } = require('../controller/user_controller'); +const {user_forgotPassword, user_resetPassword } = require('../controller/user_controller'); router.route("/forgotPassword").post(user_forgotPassword); router.route("/resetPassword").post(user_resetPassword); From 4ee164ebfded5c36a218a6f5b19a42bdd457999d Mon Sep 17 00:00:00 2001 From: viviannTam Date: Tue, 30 Jan 2024 13:06:44 +0800 Subject: [PATCH 4/6] a --- consumerWebsite/controller/user_controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consumerWebsite/controller/user_controller.js b/consumerWebsite/controller/user_controller.js index 5cc49e1..c901c23 100644 --- a/consumerWebsite/controller/user_controller.js +++ b/consumerWebsite/controller/user_controller.js @@ -2,7 +2,7 @@ const connection = require('../database/mySQL'); const { isEmpty } = require('../utils/object_isEmpty'); const AppError = require('../utils/error'); const bcrypt = require('bcryptjs'); -const { USER_MODEL, USER_LOGIN_MODEL, FORGOT_PASSWORD_MODEL, RESET_PASSWORD_MODEL } = require('../database/model/userModel'); +const {FORGOT_PASSWORD_MODEL, RESET_PASSWORD_MODEL } = require('../database/model/userModel'); const nodemailer = require('nodemailer'); exports.user_forgotPassword = (req, res, next) => { From 9a5e128f3f8491b9ce69748b8711dae51bdb7430 Mon Sep 17 00:00:00 2001 From: viviannTam Date: Tue, 30 Jan 2024 13:07:41 +0800 Subject: [PATCH 5/6] a --- consumerWebsite/utils/errorHandler.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/consumerWebsite/utils/errorHandler.js b/consumerWebsite/utils/errorHandler.js index e69de29..ba09996 100644 --- a/consumerWebsite/utils/errorHandler.js +++ b/consumerWebsite/utils/errorHandler.js @@ -0,0 +1,8 @@ +module.exports = (err, req, res, next) => { + err.statusCode = err.statusCode || 500; + err.status = err.status || "error"; + res.status(err.statusCode).json({ + status: err.status, + message: err.message, + }); +}; \ No newline at end of file From 31fe6b3c7c3a805f4e43c5ce6af2d6be516798a2 Mon Sep 17 00:00:00 2001 From: viviannTam Date: Tue, 30 Jan 2024 14:48:17 +0800 Subject: [PATCH 6/6] b --- consumerWebsite/app.js | 14 --- consumerWebsite/controller/user_controller.js | 110 ------------------ consumerWebsite/database/mySQL.js | 2 +- consumerWebsite/functions/nodeMail.js | 63 +++++++++- consumerWebsite/routes/auth.js | 24 ++++ consumerWebsite/routes/user.js | 4 - consumerWebsite/utils/error.js | 13 --- consumerWebsite/utils/errorHandler.js | 8 -- consumerWebsite/utils/object_isEmpty.js | 8 -- consumerWebsite/views/forgotPassword.ejs | 7 +- consumerWebsite/views/resetpassword.ejs | 2 +- 11 files changed, 91 insertions(+), 164 deletions(-) delete mode 100644 consumerWebsite/controller/user_controller.js delete mode 100644 consumerWebsite/utils/error.js delete mode 100644 consumerWebsite/utils/errorHandler.js delete mode 100644 consumerWebsite/utils/object_isEmpty.js diff --git a/consumerWebsite/app.js b/consumerWebsite/app.js index 75fce1e..382772d 100644 --- a/consumerWebsite/app.js +++ b/consumerWebsite/app.js @@ -1,10 +1,7 @@ const express = require("express"); const { rateLimit } = require("express-rate-limit"); const path = require("path"); -const router = require('./routes/user'); -const errorHandler = require('./utils/errorHandler'); const app = express(); -const ejs = require("ejs"); module.exports = app; @@ -96,14 +93,3 @@ app.use(function (err, req, res, next) { }); } }); - -//reset password logic -app.use("/api/user", router) - -app.use(errorHandler); - -const PORT = 3000; - -app.listen(PORT, () => { - console.log('server running on port ' + PORT); -}); \ No newline at end of file diff --git a/consumerWebsite/controller/user_controller.js b/consumerWebsite/controller/user_controller.js deleted file mode 100644 index c901c23..0000000 --- a/consumerWebsite/controller/user_controller.js +++ /dev/null @@ -1,110 +0,0 @@ -const connection = require('../database/mySQL'); -const { isEmpty } = require('../utils/object_isEmpty'); -const AppError = require('../utils/error'); -const bcrypt = require('bcryptjs'); -const {FORGOT_PASSWORD_MODEL, RESET_PASSWORD_MODEL } = require('../database/model/userModel'); -const nodemailer = require('nodemailer'); - -exports.user_forgotPassword = (req, res, next) => { - - //Check the form data is found or not - if (isEmpty(req.body)) return next(new AppError('form data not found', 400)); - - try { - - //Check the form data is valid or not - const { error } = FORGOT_PASSWORD_MODEL.validate(req.body); - - if (error) return next(new AppError(error.details[0].message, 400)); - - connection.query("SELECT * FROM user WHERE email = ?", [[req.body.email]], async (err, data1, fields) => { - if (err) return next(new AppError(err, 500)); - - if (data1.length == 0) { - return next(new AppError("user not exist", 400)) - } - - const otp = Math.floor(1000 + Math.random() * 9000); - - const otpExpier = new Date(); - otpExpier.setMinutes(otpExpier.getMinutes() + 1); - - connection.query("UPDATE user SET otp = ?, otpExpire = ? WHERE email = ?", [otp, otpExpier, req.body.email], (err, data2, fields) => { - if (err) return next(new AppError(err, 500)); - - const transporter = nodemailer.createTransport({ - service: 'Gmail', - auth: { - user: 'ecosavertp@gmail.com', - pass: 'Ecosaver1234!', - }, - }); - - const mailOptions = { - from: 'ecosavertp@gmail.com', - to: req.body.email, - subject: 'Password reset OTP', - text: `Your OTP (It is expired after 1 min) : ${otp}`, - }; - - transporter.sendMail(mailOptions, (error, info) => { - if (error) { - return next(new AppError(error, 500)); - } else { - res.json({ - data: "Your OTP send to the email" - }) - } - }); - - }) - - }) - - } - catch (err) { - return next(new AppError(err, 500)); - } -} - -exports.user_resetPassword = (req, res, next) => { - - const body = req.body; - const password = body.password; - const confirmPassword = body.confirmPassword; - - if (isEmpty(body)) return next(new AppError('form data not found', 400)); - - try { - - const { error } = RESET_PASSWORD_MODEL.validate(body); - - if (error) return next(new AppError(error.details[0].message, 400)); - - if (password.localeCompare(confirmPassword) != 0) return next(new AppError('passwords are not equal', 400)); - - connection.query("SELECT * FROM user WHERE otp = ? AND otpExpire > NOW()", [[body.otp]], async (err, data, fields) => { - if (err) return next(new AppError(err, 500)); - - if (data.length == 0) return next(new AppError('Invalid or expired OTP', 400)); - - const solt = await bcrypt.genSalt(10); - const hashedPassword = await bcrypt.hash(password, solt); - - connection.query("UPDATE user SET password = ?, otp = null, otpExpire = null WHERE otp = ?", [hashedPassword, body.otp], async (err, data, fields) => { - if (err) return next(new AppError(err, 500)); - - res.json({ - data: 'Password reset successful' - }) - - }) - - }) - - } - catch (err) { - return next(new AppError(err, 500)); - } - -} \ No newline at end of file diff --git a/consumerWebsite/database/mySQL.js b/consumerWebsite/database/mySQL.js index 6bba43b..275674f 100644 --- a/consumerWebsite/database/mySQL.js +++ b/consumerWebsite/database/mySQL.js @@ -15,7 +15,7 @@ const sequelize = new Sequelize( attributeBehavior: 'escape', dialectOptions: { ssl: { - ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt_3.pem')), + ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt.pem')), }, }, diff --git a/consumerWebsite/functions/nodeMail.js b/consumerWebsite/functions/nodeMail.js index f81a8c4..c54f8b7 100644 --- a/consumerWebsite/functions/nodeMail.js +++ b/consumerWebsite/functions/nodeMail.js @@ -77,6 +77,67 @@ async function sendTokenEmail(email, token) { } } +async function sendResetPasswordEmail(email, message) { + console.log(email, message); + + try { + let resetMessage = await transporter.sendMail({ + to: process.env.euser, + subject: "Reset Password", + html: ` +

Reset Password

+

From: Eco Saver

+

User Email: ${email}

+

Message: ${message}

+

Kindly click on the link given to reset your password!

+

Regards,

+

EcoSaver Team

+

EcoSaver Website

+

Please do not reply to this email.

+ `, + }); + transporter.sendMail({ resetMessage }, function (error, info) { + if (error) { + console.log(error); + } else { + console.log("Email sent: " + info.response); + } + }); + } catch (error) { + console.error(error); + } +} + +async function sendResetTokenEmail(email, token) { + + try { + let tokenMessage = await transporter.sendMail({ + to: email, + from: process.env.euser, + subject: "API Token", + html: ` +

API Token

+

Token: ${token}

+

Please do not lose this token and do not share your token with anyone!

+

Thank you for using EcoSaver.

+

Regards,

+

EcoSaver Team

+

EcoSaver Website

+

Please do not reply to this email.

+ + `, + }); + transporter.sendMail({ resetMessage }, function (error, info) { + if (error) { + console.log(error); + } else { + console.log("Email sent: " + info.response); + } + }); + } catch (error) { + console.error(error); + } +} -module.exports = { sendContactEmail , sendTokenEmail }; +module.exports = { sendContactEmail , sendTokenEmail, sendResetPasswordEmail, sendResetTokenEmail }; diff --git a/consumerWebsite/routes/auth.js b/consumerWebsite/routes/auth.js index 276a5a2..675e72d 100644 --- a/consumerWebsite/routes/auth.js +++ b/consumerWebsite/routes/auth.js @@ -72,4 +72,28 @@ router.post("/contact", async (req, res, next) => { } }); +//reset +router.post("/checkemail", async (req, res, next) => { + try{ + //console.log(req.body); + let Res = await checkEmail(req.body.email); + if (!Res) { + let error = new Error("Email not found"); + error.status = 400; + return next(error); + } + else{ + //console.log(Res); + send(req.body.email, req.body.name, req.body.message); + return res.json({ + message: "Reset Password Link has successfully sent to your email!", + }); + + } + }catch (error){ + console.error(error); + next(error); + } +}); + module.exports = router; diff --git a/consumerWebsite/routes/user.js b/consumerWebsite/routes/user.js index 543077b..e81ac90 100644 --- a/consumerWebsite/routes/user.js +++ b/consumerWebsite/routes/user.js @@ -76,8 +76,4 @@ router.delete("/delete", async function (req, res, next) { }); }); -const {user_forgotPassword, user_resetPassword } = require('../controller/user_controller'); -router.route("/forgotPassword").post(user_forgotPassword); -router.route("/resetPassword").post(user_resetPassword); - module.exports = router; diff --git a/consumerWebsite/utils/error.js b/consumerWebsite/utils/error.js deleted file mode 100644 index a4ad20c..0000000 --- a/consumerWebsite/utils/error.js +++ /dev/null @@ -1,13 +0,0 @@ -class AppError extends Error { - constructor(msg, statusCode) { - super(msg); - - this.statusCode = statusCode; - this.error = `${statusCode}`.startsWith('4') ? 'fail' : 'error'; - this.isOperational = true; - - Error.captureStackTrace(this, this.constructor); - } -} - -module.exports = AppError; \ No newline at end of file diff --git a/consumerWebsite/utils/errorHandler.js b/consumerWebsite/utils/errorHandler.js deleted file mode 100644 index ba09996..0000000 --- a/consumerWebsite/utils/errorHandler.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = (err, req, res, next) => { - err.statusCode = err.statusCode || 500; - err.status = err.status || "error"; - res.status(err.statusCode).json({ - status: err.status, - message: err.message, - }); -}; \ No newline at end of file diff --git a/consumerWebsite/utils/object_isEmpty.js b/consumerWebsite/utils/object_isEmpty.js deleted file mode 100644 index c4099a8..0000000 --- a/consumerWebsite/utils/object_isEmpty.js +++ /dev/null @@ -1,8 +0,0 @@ -//Checking that the request body is empty -exports.isEmpty = function (obj) { - for(var prop in obj) { - if(obj.hasOwnProperty(prop)) - return false; - } - return JSON.stringify(obj) === JSON.stringify({}); -} \ No newline at end of file diff --git a/consumerWebsite/views/forgotPassword.ejs b/consumerWebsite/views/forgotPassword.ejs index ca37f61..735c74e 100644 --- a/consumerWebsite/views/forgotPassword.ejs +++ b/consumerWebsite/views/forgotPassword.ejs @@ -4,10 +4,9 @@
Reset Password
-
- - - + +

diff --git a/consumerWebsite/views/resetpassword.ejs b/consumerWebsite/views/resetpassword.ejs index 18f140e..960e236 100644 --- a/consumerWebsite/views/resetpassword.ejs +++ b/consumerWebsite/views/resetpassword.ejs @@ -29,7 +29,7 @@