Skip to content
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: 'technojam.reply@gmail.com' ,
pass: 'enter app password here'
}
});

const mailOptions = {
from: 'Password Reset <technojam.reply@gmail.com>', // Something like: John Snow <john@gmail.com>
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;