From cbc63d79ee56e788b0dd9baa8947366b16ded495 Mon Sep 17 00:00:00 2001 From: Sourabh782 Date: Fri, 8 Nov 2024 17:54:32 +0530 Subject: [PATCH 1/2] Added otp based forgot password implementation --- README.md | 3 +- login-system/dbServer.js | 5 ++- login-system/login.js | 43 ++++++++++++++++++- login-system/otp.js | 77 ++++++++++++++++++++++++++++++++++ package-lock.json | 9 ++-- package.json | 2 +- public/password_reset.html | 85 ++++++++++++++++---------------------- 7 files changed, 165 insertions(+), 59 deletions(-) create mode 100644 login-system/otp.js diff --git a/README.md b/README.md index deacdd4..0fef281 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,8 @@ Follow these steps to run the Research Nexas userid INT auto_increment unique primary key, username varchar(60) not null, email varchar(80) not null unique, - password varchar(140) not null unique + password varchar(140) not null unique, + otp varchar(15) ); ``` ``` diff --git a/login-system/dbServer.js b/login-system/dbServer.js index 65676b3..ea91feb 100644 --- a/login-system/dbServer.js +++ b/login-system/dbServer.js @@ -5,7 +5,7 @@ const db = require('../config/mysql_connection') const { stk_signup, stk_signin } = require("../stakeholder/login"); const { info, check } = require("../file_upload/form_db"); -const { signup, signin } = require("./login"); +const { signup, signin, reset } = require("./login"); const rateLimiter = require("express-rate-limit"); const { approve, uploadedpapers, displaydetail } = require("../stakeholder/stk_approval"); const { saveNewsLetterData } = require("../backend/newsLetter"); @@ -15,6 +15,7 @@ const { logout } = require("./logout"); const { setcriteria, evaluate } = require("../stakeholder/evaluation"); const { allot, DisplayPapers } = require("../stakeholder/allotment"); const { Dis_fac_papers, fac_signup, fac_login, dis_mail, giverating } = require("../stakeholder/faculty"); +const { sendOtp } = require("./otp"); const app = express(); const globalLimit = rateLimiter({ @@ -128,6 +129,8 @@ app.post("/fac_signup", fac_signup); // registration of faculty app.post("/login", signin); app.post("/stk_holder_signin", stk_signin); app.post("/fac_login", fac_login); //login for faculty +app.post("/sendotp", sendOtp) +app.post("/resetpassword", reset); // approval by stakeholder app.get("/approval", approve); diff --git a/login-system/login.js b/login-system/login.js index 6b9a4da..81c06bf 100644 --- a/login-system/login.js +++ b/login-system/login.js @@ -48,7 +48,7 @@ const signup=async (req, res) => { const sqlSearch = "SELECT * FROM user_table WHERE email=? OR username=?"; const search_query = mysql.format(sqlSearch, [email,username]) - const sqlinsert = "INSERT INTO user_table VALUES (0,?,?,?)" + const sqlinsert = "INSERT INTO user_table VALUES (0,?,?,?,'')" const insert_query = mysql.format(sqlinsert, [username, email, hashpassword]) await connection.query(search_query, async (err, result) => { if (err) throw (err) @@ -117,8 +117,47 @@ const signin=(req, res) => { }) } +const reset=(req, res)=>{ + const email = req.body.email.trim() + const password = req.body.password.trim(); + const otp = req.body.otp.trim(); + db.getConnection(async (err, connection) => { + if (err) throw (err) + const sqlSearch = "Select * from user_table where email=?" + const search_query = mysql.format(sqlSearch, [email]) + await connection.query(search_query, async (err, result) => { + if (err) throw (err) + if (result.length == 0) { + console.log("User does not exist") + res.sendStatus(404) + } + else { + // console.log(result); + const userOtp = result[0].otp + + if(otp !== userOtp || userOtp.length === 0){ + return res.status(400).json({success: false, message: "Invalid otp"}) + } + + const hashpassword = await bcrypt.hash(password, 10); + + const reset_query = `Update user_table set otp=?, password=? where email=?` + const query = mysql.format(reset_query, ["", hashpassword, email]) + + await connection.query(query, async (err, result) => { + if(err) throw (err) + }) + + res.json({ success: true, message: "password reset successfully" }) + } + connection.release() + }) + }) +} + // exporting signup,signin funtion module.exports={ signup : [signupRateLimiter,signup], - signin : [signinRateLimiter,signin] + signin : [signinRateLimiter,signin], + reset } diff --git a/login-system/otp.js b/login-system/otp.js new file mode 100644 index 0000000..5b8b1ed --- /dev/null +++ b/login-system/otp.js @@ -0,0 +1,77 @@ +const mysql = require('mysql') +const bcrypt = require('bcrypt') +const {generateAccessToken}=require('./token'); +const notify = require('./notification'); +const rateLimit = require('express-rate-limit') +require("dotenv").config() +const db = require('../config/mysql_connection') +const nodemailer = require("nodemailer"); + +// connecting database to the server +db.getConnection((err, connection) => { + if (err) throw err; + console.log("Database Connected Successfully") +}) + +const sendOtp = (req, res)=>{ + const email = req.body.email; + console.log(email); + + + db.getConnection(async (err, connection) => { + if (err) throw (err) + const sqlSearch = "Select * from user_table where email=?" + + const search_query = mysql.format(sqlSearch, [email]) + await connection.query(search_query, async (err, result) => { + if (err) throw (err) + if (result.length == 0) { + console.log("User does not exist") + res.sendStatus(404) + } + else { + const verifyCode = Math.floor(100000 + Math.random() * 900000).toString(); + + const otp_query = `Update user_table set otp=? where email=?` + const query = mysql.format(otp_query, [verifyCode, email]) + + await connection.query(query, async (err, result) => { + if(err) throw (err) + }) + + const transporter = nodemailer.createTransport({ + service: "gmail", + auth: { + user: process.env.EMAIL, + pass: process.env.MYPASS, + }, + }); + + const mailOptions = { + from: process.env.EMAIL_USER, + to: email, + subject: "Email Verification", + text: `This is otp to verify your email: ${verifyCode}`, + }; + + transporter.sendMail(mailOptions, (error, info) => { + if (error) { + console.error("Error sending email:", error); + return res.status(500).json({ + success: false, + message: `Error sending verification email: ${error.message}`, + }); + } + + return res.sendStatus(200).send({message: "otp sent successfully"}) + }); + } + connection.release() + }) + }) +} + +// exporting signup,signin funtion +module.exports={ + sendOtp +} diff --git a/package-lock.json b/package-lock.json index 4b4718c..9163c64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "mailgun-js": "^0.22.0", "multer": "^1.4.5-lts.1", "mysql": "^2.18.1", - "nodemailer": "^6.9.8", + "nodemailer": "^6.9.16", "sih_project_2": "file:" }, "devDependencies": { @@ -1767,9 +1767,10 @@ } }, "node_modules/nodemailer": { - "version": "6.9.8", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.8.tgz", - "integrity": "sha512-cfrYUk16e67Ks051i4CntM9kshRYei1/o/Gi8K1d+R34OIs21xdFnW7Pt7EucmVKA0LKtqUGNcjMZ7ehjl49mQ==", + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.16.tgz", + "integrity": "sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ==", + "license": "MIT-0", "engines": { "node": ">=6.0.0" } diff --git a/package.json b/package.json index 0902f0b..6f1741a 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "mailgun-js": "^0.22.0", "multer": "^1.4.5-lts.1", "mysql": "^2.18.1", - "nodemailer": "^6.9.8", + "nodemailer": "^6.9.16", "sih_project_2": "file:" }, "devDependencies": { diff --git a/public/password_reset.html b/public/password_reset.html index 00a5c6a..4abd73a 100644 --- a/public/password_reset.html +++ b/public/password_reset.html @@ -35,11 +35,7 @@ } /* Disable the password and reset button initially */ - #password, - #reset-password-btn { - opacity: 0.5; - pointer-events: none; - } + @@ -64,7 +60,7 @@

Enter Invalid email domain. Please use Gmail, Outlook, Yahoo, Protonmail, Icloud, or Tutanota. - + @@ -120,17 +116,30 @@

Enter // Validate email and send code validateEmailBtn.addEventListener('click', async function () { const emailValue = emailInput.value; + console.log(emailValue); + const emailDomain = emailValue.split('@')[1]; if (emailDomain && allowedDomains.includes(emailDomain.toLowerCase())) { emailInput.classList.add('valid'); errorMessage.style.display = 'none'; + // sending otp + const response = await fetch('/sendotp', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ email: emailValue }), + }); + // Simulate sending validation code (you should replace this with actual backend logic) + validationCodeInput.disabled = false; + passwordInput.disabled = false + resetPasswordBtn.disabled = false; alert("A validation code has been sent to your email!"); // Enable validation code input - validationCodeInput.disabled = false; } else { emailInput.classList.add('invalid'); @@ -139,24 +148,30 @@

Enter }); // Validate the entered code - validationCodeInput.addEventListener('input', function () { + resetPasswordBtn.addEventListener('click', async function (e) { // Simulate code validation (replace with backend logic) - if (validationCodeInput.value === "123456") { // Sample validation code for demonstration - emailValidated = true; + // /resetpassword + e.preventDefault() + const emailValue = emailInput.value; + const password = passwordInput.value; + const otp = validationCodeInput.value; - // Enable password input and reset button - passwordInput.disabled = false; - resetPasswordBtn.style.opacity = '1'; - resetPasswordBtn.style.pointerEvents = 'auto'; + const response = await fetch('/resetpassword', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ email: emailValue, password, otp }), + }); - } else { - emailValidated = false; + console.log(response); + + if(!response.ok){ - // Disable password input and reset button if the code is incorrect - passwordInput.disabled = true; - resetPasswordBtn.style.opacity = '0.5'; - resetPasswordBtn.style.pointerEvents = 'none'; } + + alert('Password reset successfully!'); + window.location.href = 'login.html'; }); // Password criteria validation @@ -194,36 +209,6 @@

Enter } }); - document.getElementById('resetForm').addEventListener('submit', async function (event) { - event.preventDefault(); - - let email = document.getElementById('email').value; - let password = document.getElementById('password').value; - - if (!emailValidated) { - alert('Please validate your email first!'); - return; - } - - try { - const response = await fetch('http://localhost:5000/reset_password', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ email, password }), - }); - - if (response.ok) { - alert('Password reset successfully!'); - window.location.href = 'login.html'; - } else { - alert('Error resetting password. Please try again.'); - } - } catch (error) { - console.error('Error:', error); - } - }); }); From b1924c787f6e22a192fea15810720e74f8605596 Mon Sep 17 00:00:00 2001 From: Sourabh782 Date: Fri, 8 Nov 2024 21:17:48 +0530 Subject: [PATCH 2/2] resolved changes --- login-system/notification.js | 2 +- login-system/otp.js | 29 +++-------------------------- 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/login-system/notification.js b/login-system/notification.js index cee4410..66cdc4c 100644 --- a/login-system/notification.js +++ b/login-system/notification.js @@ -27,4 +27,4 @@ const notify=(req,res,email,sub,content)=>{ }); } -module.exports=notify; \ No newline at end of file +module.exports = notify; \ No newline at end of file diff --git a/login-system/otp.js b/login-system/otp.js index 5b8b1ed..849bf9b 100644 --- a/login-system/otp.js +++ b/login-system/otp.js @@ -39,32 +39,9 @@ const sendOtp = (req, res)=>{ if(err) throw (err) }) - const transporter = nodemailer.createTransport({ - service: "gmail", - auth: { - user: process.env.EMAIL, - pass: process.env.MYPASS, - }, - }); - - const mailOptions = { - from: process.env.EMAIL_USER, - to: email, - subject: "Email Verification", - text: `This is otp to verify your email: ${verifyCode}`, - }; - - transporter.sendMail(mailOptions, (error, info) => { - if (error) { - console.error("Error sending email:", error); - return res.status(500).json({ - success: false, - message: `Error sending verification email: ${error.message}`, - }); - } - - return res.sendStatus(200).send({message: "otp sent successfully"}) - }); + notify(req, res, email, "Email Verification", `This is otp to verify your email: ${verifyCode}`); + + return res.send({message: "otp sent successfully"}) } connection.release() })