Skip to content

Commit

Permalink
Bug: Reset Password fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
BHS-Harish committed Jul 28, 2024
1 parent 62f960e commit 3ab43d9
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 8 deletions.
1 change: 1 addition & 0 deletions backend/.env
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ EMAIL_HOST=smtp.gmail.com
CLUSTER=no
JWT_RESET_PASSWORD_EXPIRES_IN=1h
LOCAL_DEV_ENV=http://localhost:3500/
FRONTEND_URL=https://hitk-tech-community.netlify.app
39 changes: 37 additions & 2 deletions backend/app/routes/admin/forgotPassword.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
const nodemailer = require('nodemailer');
const Admin = require('../../models/Admin');
const config = require('../../../config');
const { ErrorHandler } = require('../../../helpers/error');
const constants = require('../../../constants');
const { generateJWT } = require('../../../helpers/middlewares/auth');
const { resetPasswordMailTemplate } = require('../../../utility/emailTemplates');

module.exports = async (req, res, next) => {
const { email } = req.body;
const transporter = nodemailer.createTransport({
type: 'SMTP',
host: config.EMAIL_HOST,
secure: true,
debug: true,
port: 465,
auth: {
user: config.EMAIL_USER,
pass: config.EMAIL_PASS,
},
});
const userRecord = await Admin.findOne({ email });
console.log(userRecord)
if (!userRecord) {
const error = new ErrorHandler(constants.ERRORS.INPUT, {
statusCode: 400,
Expand All @@ -21,10 +35,31 @@ module.exports = async (req, res, next) => {
// Setting EMAIL as the token payload
const JWTPayload = { email };
const token = await generateJWT(JWTPayload, constants.JWT_RESET_PASSWORD_EXPIRES_IN);

const data = {
adminName: `${userRecord.firstName} ${userRecord.lastName}`,
url: `${config.FRONTEND_URL}/forgot-password/${token}`,
};
const mailOptions = {
from: `HITK TECH Community <${config.EMAIL_USER}>`,
to: email,
subject: 'Reset Password | HITK TECH Community',
html: resetPasswordMailTemplate(data),
};
await transporter.sendMail(mailOptions).catch((err) => {
if (err) {
const error = new ErrorHandler(constants.ERRORS.UNEXPECTED, {
statusCode: 500,
message: 'The server encountered an unexpected condition which prevented it from fulfilling the request.',
errStack: err,
user: email,
});
throw error;
}
});
// Sending the reset password URL as a response (http://localhost:3500/:token)
res.status(200).send({
resetPasswordURL: `${config.LOCAL_DEV_ENV}admin/resetpassword/${token}`,
success: 'Reset mail sent',
resetPasswordURL: `${config.FRONTEND_URL}/forgot-password/${token}`,
});
return next();
};
2 changes: 1 addition & 1 deletion backend/app/routes/admin/resetPassword.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ module.exports = async (req, res, next) => {
if (err) {
const error = new ErrorHandler(constants.ERRORS.INPUT, {
statusCode: 400,
message: 'Something went wrong',
message: 'Reset Password Failed',
user: email,
errStack: 'Reset Password',
});
Expand Down
1 change: 1 addition & 0 deletions backend/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const config = {
CLUSTER: process.env.CLUSTER,
JWT_RESET_PASSWORD_EXPIRES_IN: process.env.JWT_RESET_PASSWORD_EXPIRES_IN,
LOCAL_DEV_ENV: process.env.LOCAL_DEV_ENV,
FRONTEND_URL:process.env.FRONTEND_URL
};

module.exports = config;
12 changes: 12 additions & 0 deletions backend/utility/emailTemplates.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,15 @@ module.exports.ResourceDeletedMailTemplate = (adminName) => {
`;
return emailContent;
};

module.exports.resetPasswordMailTemplate = (data) => {
const emailContent = `
<h2>Hello, ${data.adminName}</h2>
Click below link to reset your password<br>
<a href=${data.url} target="_blank">Reset password link</a>
<br>
<br>
Please ignore this mail If you not request the service
`;
return emailContent;
};
5 changes: 5 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 41 additions & 2 deletions frontend/src/pages/ForgotPassword/ForgotPassword.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,23 @@ import { Button2 } from "../../components/util/Button/index";
import style from "./ForgotPassword.module.scss";
import Grid from "@material-ui/core/Grid";
import { Link } from "react-router-dom";
import { SimpleToast } from "../../components/util/Toast";
import axios from "axios";
import { END_POINT } from "../../config/api";

export function ForgotPassword(props) {
const [status, setStatus] = useState("");
const [submited, setSubmited] = useState(false);
let dark = props.theme;
const [toast, setToast] = useState({
open: false,
message: "",
severity: "",
});

const handleCloseToast = () => {
setToast({ open: false, message: "", severity: "" });
};
const [formdata, setFormData] = useState({
email: "",
});
Expand Down Expand Up @@ -75,8 +86,29 @@ export function ForgotPassword(props) {
setFormErrors(errors);
};

function submitForgotPassword(e) {
return setSubmited(true);
function submitForgotPassword() {
setToast({ open: true, message: "Loading...", severity: "info" });
axios
.post(
`${END_POINT}/admin/forgotpassword`,
{
email: formdata?.email,
},
{ responseType: "json" }
)
.then(function (res) {
setToast({
open: true,
message: "Reset mail sent",
severity: "success",
});
setSubmited(true);
})
.catch(function (error) {
setToast({ open: true, message: "User not found", severity: "error" });
setFormData({ email: "" });
});
return null;
}

return (
Expand Down Expand Up @@ -189,6 +221,7 @@ export function ForgotPassword(props) {
name="email"
placeholder="Email"
onChange={handleChange}
value={formdata.email}
className={
dark
? `${style["input-forgot-password-dark"]} ${style["input-forgot-password"]}`
Expand Down Expand Up @@ -227,6 +260,12 @@ export function ForgotPassword(props) {
</div>
</div>
</div>
<SimpleToast
open={toast.open}
message={toast.message}
handleCloseToast={handleCloseToast}
severity={toast.severity}
/>
</div>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,61 @@ import style from "./ForgotPasswordRecovery.module.scss";
import { Button2 } from "../../components/util/Button/index";
import { SimpleToast } from "../../components/util/Toast";
import Grid from "@material-ui/core/Grid";
import { Link } from "react-router-dom";
import { Link, useParams } from "react-router-dom";
import axios from "axios";
import { END_POINT } from "../../config/api";

export function ForgotPasswordRecovery() {
const [new_password, setNewPassword] = useState("");
const [confirm_password, setConfirmPassword] = useState("");
const [openPasswordChanged, setPasswordChanged] = useState(false);
const [openPasswordChangeFailed, setPasswordChangeFailed] = useState(false);
const [openUnmatchedPassword, setUnmatchedPassword] = useState(false);
const [checkUpdatedPassword, setCheckUpdatedPassword] = useState(false);

const { id } = useParams();

const handleCloseToast = (event, reason) => {
if (reason === "clickaway") {
return;
}
setPasswordChanged(false);
setUnmatchedPassword(false);
setPasswordChangeFailed(false);
};
function handleSubmit(e) {
e.preventDefault();
if (new_password === confirm_password) {
setNewPassword("");
setConfirmPassword("");
setPasswordChanged(true);
setCheckUpdatedPassword(true);
handleResetPassword();
} else {
setUnmatchedPassword(true);
setNewPassword("");
setConfirmPassword("");
}
}

async function handleResetPassword() {
axios
.post(
`${END_POINT}/admin/resetpassword/${id}`,
{
newPassword: new_password,
},
{ responseType: "json" }
)
.then(function (res) {
setPasswordChanged(true);
setCheckUpdatedPassword(true);
})
.catch(function (error) {
setPasswordChangeFailed(true);
setNewPassword("");
setConfirmPassword("");
});
}

return (
<>
<div className={style["forgot-password-recovery-section"]}>
Expand Down Expand Up @@ -134,6 +159,12 @@ export function ForgotPasswordRecovery() {
handleCloseToast={handleCloseToast}
severity="error"
/>
<SimpleToast
open={openPasswordChangeFailed}
message="Password change failed"
handleCloseToast={handleCloseToast}
severity="error"
/>
</>
);
}

0 comments on commit 3ab43d9

Please sign in to comment.