Skip to content

Commit d0b53d9

Browse files
committed
Implemented Forget Password usng sendinblue or brevo mail service
1 parent 51baacb commit d0b53d9

File tree

13 files changed

+480
-8
lines changed

13 files changed

+480
-8
lines changed

app.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const sequelize = require('./util/database');
1919
const User = require('./models/user'); // ? What is use of this
2020
const Expense = require('./models/expense'); // ? What is use of this
2121
const Premium = require('./models/premium');
22+
const ResetPassword = require("./models/resetPassword");
2223

2324
// set the static folder in my express (by the we can use css and js file)
2425
app.use(express.static('./public'));
@@ -35,6 +36,9 @@ Expense.belongsTo(User);
3536
User.hasMany(Premium);
3637
Premium.belongsTo(User);
3738

39+
User.hasMany(ResetPassword);
40+
ResetPassword.belongsTo(User);
41+
3842
//{ force: true } - it is writen in sync(), when we want to crate the fresh tabel or update the table or table schema
3943
sequelize.sync().then((result) => { // ? How this .sync find the all module for creating table
4044
app.listen(port, function (err) {

controllers/user_controller.js

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ const sequelize = require('sequelize');
22
const User = require('../models/user');
33
const Expense = require("../models/expense");
44
const Premium = require('../models/premium');
5+
const ResetPassword = require("../models/resetPassword");
56
const path = require('path');
67
const jwt = require("jsonwebtoken");
7-
const Razorpay = require("razorpay");
8+
const Razorpay = require("razorpay"); //payment gateway service
9+
const Sib = require("sib-api-v3-sdk"); //sendinblue or brevo - emain sending service
10+
const { v4: uuidv4 } = require("uuid"); // unique id generator
811

912
module.exports.signUp = async (req, res) => {
1013
try {
@@ -70,6 +73,7 @@ module.exports.userDashboard = function (req, res) {
7073
res.sendFile(path.join(__dirname, '../public/views/user_dashboard.html'));
7174
};
7275

76+
// here we use razorpay service for payment
7377
module.exports.buyPremium = async (req, res) => {
7478
try {
7579
var rzp = new Razorpay({
@@ -225,4 +229,104 @@ module.exports.monthlyReports = async (req, res) => {
225229
} catch (error) {
226230
console.log(error);
227231
}
228-
};
232+
};
233+
234+
// Forget Password implemented here
235+
236+
module.exports.forgotPasswordPage = async (req, res) => {
237+
try {
238+
res.status(200).sendFile(path.join(__dirname, "../public/views/forgotPassword.html"));
239+
} catch (error) {
240+
console.log(error);
241+
}
242+
};
243+
244+
module.exports.sendMail = async (req, res) => {
245+
try {
246+
const email = req.body.email;
247+
const requestId = uuidv4(); //generate the unique id from uuid
248+
249+
const recepientEmail = await User.findOne({ where: { email: email } });
250+
251+
if (!recepientEmail) {
252+
return res.status(404).json({ message: "Please provide the registered email!" });
253+
}
254+
255+
await ResetPassword.create({
256+
id: requestId,
257+
isActive: true, // mail link is active
258+
userId: recepientEmail.dataValues.id // Foriegn Key
259+
});
260+
261+
//Here we use Brevo or sendinblue service for email
262+
const client = Sib.ApiClient.instance; // it gets instance object from brevo or alias as SendInBlue(sib)
263+
const apiKey = client.authentications["api-key"]; // it get the api-key object
264+
apiKey.apiKey = process.env.BREVO_API_KEY; // we set a property name as apikey under the api-key object
265+
const transEmailApi = new Sib.TransactionalEmailsApi();
266+
const sender = {
267+
email: "chiragraj106@gmail.com",
268+
name: "Chirag Raj",
269+
};
270+
const receivers = [{ email: email }];
271+
await transEmailApi.sendTransacEmail({
272+
sender,
273+
To: receivers,
274+
subject: "Expense Tracker Reset Password",
275+
// textContent: "Link Below", (no need of text content because html content overide on textcontent)
276+
htmlContent: `<h3> Hii! We got the request from you for reset the password. Here is the link below >>> </h3>
277+
<a href="http://localhost:9000/resetPasswordPage/{{params.requestId}}"> Reset your Password from here </a>`,
278+
params: {
279+
requestId: requestId,
280+
},
281+
});
282+
return res.status(200).json({
283+
message:
284+
"Link for reset the password is successfully send on your Mail Id!",
285+
});
286+
} catch (error) {
287+
console.log("error");
288+
return res.status(409).json({ message: "failed changing password" });
289+
}
290+
};
291+
292+
module.exports.resetPasswordPage = async (req, res, next) => {
293+
try {
294+
res.status(200).sendFile(path.join(__dirname, "../public/views/resetPassword.html"));
295+
} catch (error) {
296+
console.log(error);
297+
}
298+
// here we can acess req.params and req.url
299+
};
300+
301+
module.exports.resetPassword = async (req, res, next) => {
302+
try {
303+
const password = req.body.password;
304+
const requestId = req.headers.referer.split("/"); //req.headers.referer - it provide the address or url of the just previous web page.
305+
//req.url - this gives same as req.headers.referer but of the current reuest, and we cannot use this because of the request is chnage, see carefullly this is diifrent route
306+
//req.params - see carefullly this is diifrent route, we cannot find params from this reset password controller beacuse request is change after clicking reset paasword button means rout and controller change and req object is also change
307+
// see just abouve controller name as module.exports.resetPasswordPage there we can acess req.url and req.parms
308+
309+
const checkResetRequest = await ResetPassword.findAll({
310+
where: { id: requestId[requestId.length - 1], isActive: true },
311+
});
312+
313+
if (checkResetRequest[0]) {
314+
await ResetPassword.update(
315+
{ isActive: false },
316+
{ where: { id: requestId[requestId.length - 1] } }
317+
);
318+
const userId = checkResetRequest[0].dataValues.userId;
319+
await User.update(
320+
{ password: password },
321+
{ where: { id: userId } }
322+
);
323+
return res.status(200).json({ message: "Successfully changed password!" });
324+
}
325+
else {
326+
return res.status(409).json({ message: "Link is already Used Once, Request for new Link!" });
327+
}
328+
} catch (err) {
329+
console.log(err);
330+
return res.status(409).json({ message: "Failed to change password!" });
331+
}
332+
};

models/resetPassword.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const Sequelize = require("sequelize");
2+
const sequelize = require("../util/database");
3+
4+
const ResetPassword = sequelize.define("ResetPassword", {
5+
id: {
6+
type: Sequelize.STRING,
7+
primaryKey: true,
8+
allowNull: false,
9+
},
10+
isActive: Sequelize.BOOLEAN,
11+
});
12+
13+
module.exports = ResetPassword;

0 commit comments

Comments
 (0)