Skip to content

Commit 164a7d0

Browse files
committed
nodemailer for forgot password add
1 parent 85efcfc commit 164a7d0

File tree

6 files changed

+154
-102
lines changed

6 files changed

+154
-102
lines changed

controller/AuthController.js

Lines changed: 111 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,107 +1,119 @@
1-
const User = require('../model/user')
2-
const jwt = require('jsonwebtoken')
3-
const bcrypt = require('bcryptjs');
4-
const { findOne } = require('../model/user');
1+
const User = require("../model/user");
2+
const jwt = require("jsonwebtoken");
3+
const bcrypt = require("bcryptjs");
4+
const emailer = require("../utils/mailConfig");
55

66
module.exports = {
7-
register: async (req, res) => {
8-
try {
9-
const { name, email, password, pin } = req.body;
10-
let user = await User.findOne({ email });
11-
if (user)
12-
return res.status(400).json({msg: "User already exists"});
13-
if(!email.match(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/))
14-
return res.status(400).json({msg: "Invalid Mail Provided"});
15-
if (password.length < 8)
16-
return res.status(400).json({msg: "Password should be of 8 characters atleast"})
17-
if (pin.match(/[^0-9]/g))
18-
return res.status(400).json({msg: "Pin should consist only numbers"})
19-
if (pin.length !== 4)
20-
return res.status(400).json({msg: "Pin should be exactly 4 length"})
21-
user = new User({ name, email, password, pin });
22-
user.password = await bcrypt.hash(user.password, 8);
23-
user.pin = await bcrypt.hash(user.pin, 4);
24-
await user.save();
25-
res.json({ msg: "User Created. Login!" })
26-
} catch (error) {
27-
console.log(error)
28-
res.status(500).json({msg: "Internal Server Error"})
29-
}
30-
},
7+
register: async (req, res) => {
8+
try {
9+
const { name, email, password, pin } = req.body;
10+
let user = await User.findOne({ email });
11+
if (user) return res.status(400).json({ msg: "User already exists" });
12+
if (
13+
!email.match(
14+
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
15+
)
16+
)
17+
return res.status(400).json({ msg: "Invalid Mail Provided" });
18+
if (password.length < 8)
19+
return res
20+
.status(400)
21+
.json({ msg: "Password should be of 8 characters atleast" });
22+
if (pin.match(/[^0-9]/g))
23+
return res.status(400).json({ msg: "Pin should consist only numbers" });
24+
if (pin.length !== 4)
25+
return res.status(400).json({ msg: "Pin should be exactly 4 length" });
26+
user = new User({ name, email, password, pin });
27+
user.password = await bcrypt.hash(user.password, 8);
28+
user.pin = await bcrypt.hash(user.pin, 4);
29+
await user.save();
30+
res.json({ msg: "User Created. Login!" });
31+
} catch (error) {
32+
console.log(error);
33+
res.status(500).json({ msg: "Internal Server Error" });
34+
}
35+
},
3136

32-
loginWithPin: async (req, res) => {
33-
try {
34-
const { email, pin } = req.body;
35-
let user = await User.findOne({ email });
36-
if (user.length === 0)
37-
return res.status(400).json({msg: "No User Founded"});
38-
if (!await bcrypt.compare(pin, user.pin))
39-
return res.status(400).json({msg: "Pin Mismatched"})
40-
const token = await user.generateToken()
41-
res.cookie('token', token, { httpOnly: true }).json(token)
42-
} catch (error) {
43-
console.log(error)
44-
res.status(500).json({msg: "Internal Server Error"})
45-
}
46-
},
37+
loginWithPin: async (req, res) => {
38+
try {
39+
const { email, pin } = req.body;
40+
let user = await User.findOne({ email });
41+
if (user.length === 0)
42+
return res.status(400).json({ msg: "No User Founded" });
43+
if (!(await bcrypt.compare(pin, user.pin)))
44+
return res.status(400).json({ msg: "Pin Mismatched" });
45+
const token = await user.generateToken();
46+
res.cookie("token", token, { httpOnly: true }).json(token);
47+
} catch (error) {
48+
console.log(error);
49+
res.status(500).json({ msg: "Internal Server Error" });
50+
}
51+
},
4752

48-
loginWithPassword: async (req, res) => {
49-
try {
50-
const { email, password } = req.body;
51-
let user = await User.findOne({ email });
52-
if (!user)
53-
return res.status(400).json({msg: "No User Founded"});
54-
if (!await bcrypt.compare(password, user.password))
55-
return res.status(400).json({msg: "Password Mismatched"})
56-
const token = await user.generateToken()
57-
res.cookie('token', token, { httpOnly: true }).json(token)
58-
} catch (error) {
59-
console.log(error)
60-
res.status(500).json({msg: "Internal Server Error"})
61-
}
62-
},
53+
loginWithPassword: async (req, res) => {
54+
try {
55+
const { email, password } = req.body;
56+
let user = await User.findOne({ email });
57+
if (!user) return res.status(400).json({ msg: "No User Founded" });
58+
if (!(await bcrypt.compare(password, user.password)))
59+
return res.status(400).json({ msg: "Password Mismatched" });
60+
const token = await user.generateToken();
61+
res.cookie("token", token, { httpOnly: true }).json(token);
62+
} catch (error) {
63+
console.log(error);
64+
res.status(500).json({ msg: "Internal Server Error" });
65+
}
66+
},
6367

64-
forgotPasswordRequest: async (req, res) => {
65-
try {
66-
const { email } = req.body
67-
let user = await User.findOne({ email });
68-
if (!user)
69-
return res.status(400).json({ msg: "No User Founded" });
70-
const payload = {
71-
password: user.password
72-
}
73-
const token = jwt.sign(payload, user.password, {
74-
expiresIn: 3600
75-
})
76-
res.json(token)
77-
} catch (error) {
78-
console.log(error)
79-
res.status(500).json({msg: "Internal Server Error"})
80-
}
81-
},
68+
forgotPasswordRequest: async (req, res) => {
69+
try {
70+
const { email } = req.body;
71+
let user = await User.findOne({ email });
72+
if (!user) return res.status(400).json({ msg: "No User Founded" });
73+
const payload = {
74+
password: user.password,
75+
};
76+
const token = jwt.sign(payload, user.password, {
77+
expiresIn: 3600,
78+
});
79+
emailer({
80+
to: email,
81+
body: `
82+
<h2 style="font-style: arial; font-size: 2em">Greetings from Admin</h2>
83+
<h3 style="font-style: arial; font-size: 1.2em">
84+
Seems like you forgot your password, use <a href="http://localhost:3000/reset/password/${token}" target="_blank">this link</a> to reset it.
85+
</h3>
86+
<code style="color: red; font-size: 1em">Do not share this code with anyone else</code>
87+
`,
88+
});
89+
res.json("Mail sent!");
90+
} catch (error) {
91+
console.log(error);
92+
res.status(500).json({ msg: "Internal Server Error" });
93+
}
94+
},
8295

83-
resetPassword: async (req, res) => {
84-
let tokenValid = true;
85-
try {
86-
const { email, password } = req.body
87-
const user = await User.findOne({ email })
88-
const token = req.params.requestId
89-
jwt.verify(token, user.password, (err) => {
90-
if(err){
91-
tokenValid = false
92-
return res.status(400).json({msg: "Token Expired"})
93-
}
94-
})
95-
if(tokenValid){
96-
const passwordHashed = await bcrypt.hash(password, 8)
97-
user.password = passwordHashed;
98-
await user.save();
99-
res.json({ msg: "Password Changed Succesfully" })
100-
}
101-
} catch (error) {
102-
console.log(error)
103-
if(tokenValid)
104-
res.status(500).json({ msg: "Internal Server Error" })
96+
resetPassword: async (req, res) => {
97+
let tokenValid = true;
98+
try {
99+
const { email, password } = req.body;
100+
const user = await User.findOne({ email });
101+
const token = req.params.requestId;
102+
jwt.verify(token, user.password, (err) => {
103+
if (err) {
104+
tokenValid = false;
105+
return res.status(400).json({ msg: "Token Expired" });
105106
}
107+
});
108+
if (tokenValid) {
109+
const passwordHashed = await bcrypt.hash(password, 8);
110+
user.password = passwordHashed;
111+
await user.save();
112+
res.json({ msg: "Password Changed Succesfully" });
113+
}
114+
} catch (error) {
115+
console.log(error);
116+
if (tokenValid) res.status(500).json({ msg: "Internal Server Error" });
106117
}
107-
}
118+
},
119+
};

example.env

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
MONGO_URI =
2+
JWT_TOKEN =
3+
MAIl =
4+
PASS =

package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
"dotenv": "^8.2.0",
1717
"express": "^4.17.1",
1818
"jsonwebtoken": "^8.5.1",
19-
"mongoose": "^5.11.15"
19+
"mongoose": "^5.11.15",
20+
"nodemailer": "6.6.3"
2021
},
2122
"devDependencies": {
2223
"jest": "^26.6.3",

readme.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
# Node Authentication API
2-
### A full fledged, API for handling users and there authentication
32

3+
### A full fledged, API for handling users and there authentication
4+
5+
To run API locally, make sure to create a `.env` file and copy variables from `example.env` and give them valid values as well
46

57
API Offers endpoints for
8+
69
- [x] Register User
710
- [x] Login User with PIN
811
- [x] Login User with password
@@ -13,4 +16,4 @@ API Offers endpoints for
1316
- [x] Reset User's Pin
1417
- [x] Reset User's Password
1518

16-
Check complete documentation [here](https://bit.ly/3aJeLCS)
19+
Check complete documentation [here](https://bit.ly/3aJeLCS)

utils/mailConfig.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const nodemailer = require("nodemailer");
2+
3+
module.exports = (data) => {
4+
const { to, body } = data;
5+
let transporter = nodemailer.createTransport({
6+
host: "smtp.gmail.com",
7+
port: 465,
8+
secure: true,
9+
auth: {
10+
user: process.env.MAIL,
11+
pass: process.env.PASS,
12+
},
13+
});
14+
let mailOptions = {
15+
from: `"Admin" <${process.env.MAIL}>`,
16+
to,
17+
subject: "Reset password request",
18+
html: body,
19+
};
20+
transporter.sendMail(mailOptions, (error) => {
21+
if (error) {
22+
console.log(error);
23+
return false;
24+
}
25+
return true;
26+
});
27+
};

0 commit comments

Comments
 (0)