Skip to content

api/password end point added for reseting password which uses api/pas… #22

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
51 changes: 40 additions & 11 deletions package-lock.json

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

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@
"body-parser": "^1.19.0",
"config": "^3.2.3",
"cors": "^2.8.5",
"crypto": "^1.0.1",
"emailjs": "^3.3.0",
"emailjs-com": "^2.6.3",
"express": "^4.17.1",
"helmet": "^3.21.1",
"jsonwebtoken": "^8.5.1",
"mongo-sanitize": "^1.0.1",
"mongoose": "^5.7.4",
"nodemailer": "^6.4.11",
"nodemon": "^1.19.3",
"uuid": "^3.3.3"
}
Expand Down
1 change: 1 addition & 0 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ app.use('/api/groups', require('./routes/groups'));
app.use('/api/contact', require('./routes/contact'));
app.use('/api/events', require('./routes/events'));
app.use('/api/projects', require('./routes/projects'));
app.use('/api/password', require('./routes/reset'));

app.listen(PORT, () => console.log(`server started at port ${PORT}`));
13 changes: 13 additions & 0 deletions src/docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,19 @@ <h2>Available Routes</h2>
<th>OUTPUT</th>
<th>DESCRIPTION</th>
</tr>
<tr>
<td rowspan="2">LOGIN</td>
<td>[POST]/api/password/forget</td>
<td>{email:''}</td>
<td>{info:'',msg:'',token:''}</td>
<th>Accepts email and send user an email with link and returns reset token</th>
</tr>
<tr>
<td>[POST]/api/password/reset</td>
<td>{email:'',token:'',password:''}</td>
<td>{user:'',msg:''}</td>
<th>Accepts email, token and password and return user and msg after resetting the password</th>
</tr>
<tr>
<td>REGISTER</td>
<td>[POST]/api/register</td>
Expand Down
14 changes: 13 additions & 1 deletion src/models/user.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
const mongoose = require('mongoose');

const paassWordReset = new mongoose.Schema({
token: {
type: String,
default: ''
},
expiry: {
type: Date,
default: Date.now()+2*86400000
}
})

const usersSchema = new mongoose.Schema({
uid: {
type: String,
Expand Down Expand Up @@ -49,7 +60,8 @@ const usersSchema = new mongoose.Schema({
registeredEvents: {
type: [String],
default: []
}
},
resetInfo: paassWordReset
});

module.exports = mongoose.model('Users', usersSchema);
149 changes: 149 additions & 0 deletions src/routes/reset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const config = require('config');
const crypto = require('crypto');
const nodemailer = require('nodemailer');
const sanitize = require('mongo-sanitize');

const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: '[email protected]' ,
pass: 'enter app password here'
}
});

const mailOptions = {
from: 'Password Reset <[email protected]>', // Something like: John Snow <[email protected]>
to: null,
subject: 'noReply-password reset info', // email subject
};

const reset_expiry_days = 2; // number of days after which reset link expires
const exp_ms = reset_expiry_days*24*60*60*1000; // days to millisecond

const User = require('../models/user');

/*
expects body
{
email: "users email"
}
*/
router.post('/forget', (req, res) => {
User.findOne(req.body)
.then(user => {
if(!user){
return res.status(400).json({ msg: `No user with ${req.body.email} email`});
}

crypto.randomBytes(48, (err, buffer)=>{
if(err){
return res.status(500).json({ msg: `Reset token not generated`});
}
const token = buffer.toString('hex');
user.resetInfo = {
token: token,
expiry: Date.now()+exp_ms
}

user.save()
.then(user => {

const html = `
<p style="font-size: 18px;">Hello ${user.name},</p>
<p style="font-size: 18px;">You have requested to reset the password of your account kindly visit below link for further instructions.</p>
<br/>
<a href="${req.hostname}">${req.hostname}</a>
<br/><br/>
`;
mailOptions.html = html;
mailOptions.to = user.email;
transporter.sendMail(mailOptions, (err, info)=>{
if(err){
res.status(500).json(err);
}else{
res.status(200).json({info: info,
msg: 'Mail has been send to your registered id',
token: user.resetInfo
})
}
});

}, err => res.status(500).send('Server error'))
.catch(err => {
console.error(err.message);
res.status(500).send('Server error');
})

});

}, err => res.status(500).send('Server error'))
.catch(err => {
console.error(err.message);
res.status(500).send('Server error');
})
});


/*
expects body
{
token: "token send to users email",
email: "users email",
password: "new password"
}
*/
router.post('/reset', (req, res)=>{
User.findOne({
email: req.body.email
})
.then(user => {
if(!user){
return res.status(400).json({ msg: `No user with ${req.body.email} email`});
}
if(user.resetInfo.expiry == undefined){
return res.status(200).json({ msg: `Invalid url`});
}
const currDate = Date.now();
if(currDate > user.resetInfo.expiry) {
return res.status(200).json({ msg: `Sorry this link is expired`});
}
if(req.body.token != this.user.resetInfo.token){
return res.status(200).json({ msg: `Invalid token`});
}

bcrypt.genSalt(10, (err, salt) => {
if(err){
return res.status(500).json(err);
}
bcrypt.hash(req.body.password, salt, (err, hash)=>{
if(err){
return res.status(500).json(err);
}
user.password = hash;
user.resetInfo = undefined;
user.save()
.then(user => {
if(!user){
return res.status(500).send('Server error');
}
res.status(200).json({user: user, msg:'Password successfully reset'})
}, err => res.status(500).send('Server error'))
.catch(err => {
console.error(err.message);
res.status(500).send('Server error');
})
});
});

}, err => res.status(500).send('Server error'))
.catch(err => {
console.error(err.message);
res.status(500).send('Server error');
})
})

module.exports = router;