Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added reset password functionality #108

Merged
merged 1 commit into from
May 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions model/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ const userSchema = new mongoose.Schema({
approved: { type: Boolean, default: false },
// googleId: String,
// profile: String,
resetTokenExpiration: Date,
resetToken:String
});

const User = new mongoose.model("User", userSchema);
Expand Down
174 changes: 95 additions & 79 deletions routers/userRoutes.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const express = require("express");
const router = new express.Router();
const path =require("path");

const bcrypt = require("bcrypt");
const saltRounds = 10;
Expand Down Expand Up @@ -83,83 +84,6 @@ router.post("/login", async function (req, res) {
}
});

router.route("/forgot-password").get(async (req, res) => {
res.render("forget-password");
});

router.route("/reset-password").get(async (req, res) => {
const { email, token } = req.query;

try {
const user = await User.findOne({
email,
resetToken: token,
resetTokenExpiration: { $gt: Date.now() },
});

if (!user) {
return res.status(400).send("Invalid or expired reset token");
}

// Verify the token
try {
const decodedToken = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET);
// Process the decoded token (e.g., extract information from it)
console.log(decodedToken);
// Continue with the reset-password logic
res.render("reset-password", { email, token });
} catch (error) {
// Handle JWT verification errors
console.error("JWT verification error:", error.message);
// You might want to send an error response or redirect the user
res.status(401).send("Unauthorized");
}
} catch (error) {
console.error(error);
res.status(500).send("Internal Server Error");
}
});

router.post(async (req, res) => {
const { email, token, newPassword } = req.body;

try {
// Verify the token again
const user = await User.findOne({
email,
resetToken: token,
resetTokenExpiration: { $gt: Date.now() },
});

if (!user) {
return res.status(400).send("Invalid or expired reset token");
}

try {
const decodedToken = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET);
// Process the decoded token (e.g., extract information from it)
console.log(decodedToken);

// Update the user's password and reset the resetToken fields
const hash = await bcrypt.hash(newPassword, saltRounds);
user.password = hash;
user.resetToken = null;
user.resetTokenExpiration = null;
await user.save();

res.redirect("/login"); // Redirect to login page or any other desired page
} catch (error) {
// Handle JWT verification errors
console.error("JWT verification error:", error.message);
// You might want to send an error response or redirect the user
res.status(401).send("Unauthorized");
}
} catch (error) {
console.error(error);
res.status(500).send("Internal Server Error");
}
});

// extra details added for the user
router.post("/add-details", async (req, res) => {
try {
Expand Down Expand Up @@ -354,7 +278,12 @@ router.post("/User_singUp", async function (req, res) {
}
});

router.post(async (req, res) => {
router.route("/forgot-password").get(async (req, res) => {
res.render("forget-password");
});

//send Email for the reset password
router.route("/forgot-password").post(async (req, res) => {
const { email } = req.body;
try {
const user = await User.findOne({ email });
Expand All @@ -370,6 +299,9 @@ router.post(async (req, res) => {
);

user.resetTokenExpiration = Date.now() + 300000; // 5 minutes
user.resetToken = resetToken;

console.log("use after setting ",user);
await user.save();

// Send the reset link to the user via email
Expand All @@ -393,7 +325,7 @@ router.post(async (req, res) => {
attachments: [
{
filename: "logo.png",
path: path.join(__dirname, "public", "img", "logo.png"),
path: path.join( "public", "img", "logo.png"),
cid: "logo",
},
],
Expand All @@ -414,4 +346,88 @@ router.post(async (req, res) => {
}
});

// verify Email and render reset password page
router.route("/reset-password").get(async (req, res) => {
const { email, token } = req.query;
try {
const user = await User.findOne({
email,
resetToken: token,
resetTokenExpiration: { $gt: Date.now() },
});

if (!user) {
return res.status(400).send("Invalid or expired reset token");
}

// Verify the token
try {
const decodedToken = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET);
// Process the decoded token (e.g., extract information from it)
console.log(decodedToken);
// Continue with the reset-password logic
res.render("set_password", { email, token });
} catch (error) {
// Handle JWT verification errors
console.error("JWT verification error:", error.message);
// You might want to send an error response or redirect the user
res.status(401).send("Unauthorized");
}
} catch (error) {
console.error(error);
res.status(500).send("Internal Server Error");
}
});


//verify the password
router.route("/reset-password").post(async (req, res) => {
const {email,token} =req.query;
const { newPassword } = req.body;
// console.log(" User Info",email,token,newPassword);

try {
// Verify the token again
const user = await User.findOne({
email,
resetToken: token,
resetTokenExpiration: { $gt: Date.now() },
});

if (!user) {
return res.status(400).send("Invalid or expired reset token");
}

try {
const decodedToken = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET);
// Process the decoded token (e.g., extract information from it)
console.log(decodedToken);

// Update the user's password and reset the resetToken fields
const hash = await bcrypt.hash(newPassword, saltRounds);
user.password = hash;
user.resetToken = null;
user.resetTokenExpiration = null;
await user.save();

return res.render("UserDashBoard", {
fullName: user.fullName,
email: user.email,
phoneNo: user.Mobile,
address: user.address,
});

// Redirect to login page or any other desired page
} catch (error) {
// Handle JWT verification errors
console.error("JWT verification error:", error.message);
// You might want to send an error response or redirect the user
res.status(401).send("Unauthorized");
}
} catch (error) {
console.error(error);
res.status(500).send("Internal Server Error");
}
});

module.exports = router;
3 changes: 1 addition & 2 deletions views/forget-password.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,7 @@
<div class="input-group">
<label for="" class="label-title">Enter your Email</label>
<input type="email" name="email" placeholder="Enter your Email">
<span class="icon">&#9993;</span>

<span class="icon"> &#9993;</span>
</div>
<div class="input-group">
<button class="submit-btn" type="submit">Send Reset Email</button>
Expand Down
133 changes: 133 additions & 0 deletions views/set_password.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- <link rel="stylesheet" href="/public/css/index.css"> -->
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,200&display=swap');
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'poppins', sans-serif;
}
.wrapper{
background-color: #106fde;
width: 100%;
height: 100vh;
padding: 15px;
display: flex;
flex-direction: column;
gap: 20px;
justify-content: center;
align-items: center;
}
.container{
width: 500px;
background-color: #fff;
padding: 30px;
border-radius: 16px;
background-color: rgba(0,0,0,0.08) 0px 4px 12px;
/* flex-shrink: 1; */
}
.title-section{
margin-bottom: 30px;
}
.title{
color: #38475a;
font-size: 25px;
font-weight: 500;
text-transform: capitalize;
margin-bottom: 10px;
}

.input-group{
position: relative;
}
.input-group .label-title{
color: #38475a;
text-transform: capitalize;
margin-bottom: 11px;
font-size: 14px;
display: block;
font-weight: 500;

}
.input-group input{
width: 100%;
background-color: none;
color: #38475a;
height: 50px;
font-size: 16px;
font-weight: 300;
border: 1px solid #EAECF0;
padding: 9px 18px 9px 52px;
outline: none;
border-radius: 8px;
margin-bottom: 20px;
}
.input-group .input::placeholder{
color: #38475a;
font-size: 16px;
font-weight: 400;
}
.input-group .icon{
position: absolute;
color: #38475a;
left: 13px;
font-size: 23px;
text-align: center;
top: calc(50% - 11px);
}
.submit-btn{
width: 100%;
background-color: #106fde;
border: 1px solid transparent;
border-radius: 8px;
font-size: 16px;
color: #fff;
padding: 13px 24px;
font-weight: 500;
text-align: center;
text-transform: capitalize;
cursor: pointer;
}
.submit-btn:hover{
opacity: 0.95;
}
.logo{
width: 10%;
flex: 0 0 0;

}
</style>
<title>Password Reset</title>
</head>
<body>

<div class="wrapper">
<img src="img/logo.png" alt="" class="logo">
<div class="container">
<div class="title-section">
<h2 class="title">Reset Password</h2>

<form action="/reset-password?email=<%=email%>&token=<%=token%>" class="form" method="post">
<div class="input-group">
<label for="" class="label-title">Enter new Password</label>
<input type="password" name="newPassword" placeholder="Enter your password">
<!-- <span class="icon"> &#xf3ed;</span> -->

</div>
<div class="input-group">
<button class="submit-btn" type="submit">Update my password</button>

</div>
</form>
</div>
</div>



</body>
</html>