Skip to content

Commit

Permalink
Merge ceec4c7 into 7504d49
Browse files Browse the repository at this point in the history
  • Loading branch information
sabin18 committed Nov 4, 2019
2 parents 7504d49 + ceec4c7 commit 2531b2a
Show file tree
Hide file tree
Showing 12 changed files with 102 additions and 124 deletions.
37 changes: 12 additions & 25 deletions src/controllers/userController.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import strings from '../utils/stringsUtil';
import hashPassword from '../utils/hashPassword';
import generateToken from '../utils/generateToken';
import EmailToken from '../utils/EmailToken';
import emailHelper from '../helpers/emailHelper';
import updateUser from '../helpers/updateUser';

dotenv.config();
Expand Down Expand Up @@ -83,48 +84,34 @@ export default class UserController {
return responseUtil(res, 404, strings.users.error.USER_NOT_FOUND);
}
const verifyToken = EmailToken.ResetToken(user);
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const msg = {
to: email,
from: 'BarefootNomad@gmail.com',
subject: 'Barefoot Nomad Resetpassword Link',
html: `<div style="font-family:Avenir,Helvetica,sans-serif;box-sizing:border-box;padding:35px;">
<h1 style="color: #848484;">Barefoot Nomad</h1>
<p style="font-family:Avenir,Helvetica,sans-serif;box-sizing:border-box;color:#74787e;font-size:16px;line-height:1.5em;margin-top:0;text-align:left">Welcome Back,<br> We are happy to be with you. Please you can reset your password now.<br> Click the button below to reset your password.</p>
<p><a style="background-color: #3097d1; border: 2px solid #3097d1; padding: 8px; color: #fff; font-size: 16px; text-decoration: none;cursor: pointer;" href="${req.protocol}://${req.headers.host}/api/v1/users/resetpassword/${verifyToken}">Reset passowrd</a>
</a></p>
<p style="color:#74787e;font-size:16px;line-height:1.5em;margin-top:0;text-align:left">Thank you for using our application!</p>
<p style="color:#74787e;font-size:16px;line-height:1.5em;margin-top:0;">Regards,<br>Barefoot Nomad Caret Team</p>
</div>`
};
sgMail.send(msg);

emailHelper.resetEmail(req, email, verifyToken);
return responseUtil(res, 200, strings.users.success.SEND_EMAIL);
});
}

static Changepassword(req, res) {
const { email, newpassword, confirmpassword } = req.body;
models.users.findOne({
where: {
email,
},
}).then(user => {
const { newPassword, confirmPassword } = req.body;
const { token } = req.params;
const decodedToken = jwt.decode(token, process.env.JWT_SECRET);

models.users.findOne({ where: { email: decodedToken.payload.email, }, }).then(user => {
if (user == null) {
return responseUtil(res, 404, strings.users.error.USER_NOT_FOUND);
}
if (newpassword !== confirmpassword) {
if (newPassword !== confirmPassword) {
return responseUtil(res, 400, strings.users.error.PASSWORD_NOT_MATCH);
}
const compare = bcrypt.compareSync(req.body.newpassword, user.password);
const compare = bcrypt.compareSync(req.body.newPassword, user.password);
if (compare) {
return responseUtil(res, 409, strings.users.error.PASSWORD_ALREADY_EXISTS);
}
models.users.update({

password: hashPassword(req.body.newpassword),
password: hashPassword(req.body.newPassword),
}, {
where: {
email,
email: decodedToken.payload.email,
},
});
return responseUtil(res, 200, strings.users.success.PASSWORD_CHANGED);
Expand Down
25 changes: 24 additions & 1 deletion src/helpers/emailHelper.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import nodemailer from 'nodemailer';
import dotenv from 'dotenv';

dotenv.config();

const transporter = nodemailer.createTransport({
service: 'gmail',
Expand Down Expand Up @@ -30,7 +33,27 @@ const sendEmail = (email, action, name, reasons) => {
} catch (error) {
return error;
}
};

const resetEmail = (req, email, verifyToken) => {
try {
const message = {
to: email,
from: 'BarefootNomad@gmail.com',
subject: 'Barefoot Nomad Reset password Link',
html: `<div style="font-family:Avenir,Helvetica,sans-serif;box-sizing:border-box;padding:35px;">
<h1 style="color: #848484;">Barefoot Nomad</h1>
<p style="font-family:Avenir,Helvetica,sans-serif;box-sizing:border-box;color:#74787e;font-size:16px;line-height:1.5em;margin-top:0;text-align:left">Welcome Back,<br> We are happy to be with you. Please you can reset your password now.<br> Click the button below to reset your password.</p>
<p><a style="background-color: #3097d1; border: 2px solid #3097d1; padding: 8px; color: #fff; font-size: 16px; text-decoration: none;cursor: pointer;" href="${req.protocol}://${req.headers.host}/api/v1/users/resetpassword/${verifyToken}">Reset password</a>
</a></p>
<p style="color:#74787e;font-size:16px;line-height:1.5em;margin-top:0;text-align:left">Thank you for using our application!</p>
<p style="color:#74787e;font-size:16px;line-height:1.5em;margin-top:0;">Regards,<br>Barefoot Nomad Caret Team</p>
</div>`
};
transporter.sendMail(message);
} catch (error) {
return error;
}
};

export default sendEmail;
export default { sendEmail, resetEmail };
39 changes: 0 additions & 39 deletions src/middlewares/checkResetpassword.js

This file was deleted.

16 changes: 16 additions & 0 deletions src/middlewares/inputValidation.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,20 @@ export default class InputValidation {
});
validation(req, res, schema, next);
}

static validateResetpassword(req, res, next) {
const schema = Joi.object({
newPassword: Joi.string().regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})/).message('password field should contain at least 8 characters, at least 1 lowercase, 1 uppercase and 1 number and a special character.').required(),
confirmPassword: Joi.string().regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})/).message('confirmpassword field should contain at least 8 characters, at least 1 lowercase, 1 uppercase and 1 number and a special character.').required(),
});
validation(req, res, schema, next);
}

static validateEmail(req, res, next) {
const schema = Joi.object({
email: Joi.string().email({ minDomainSegments: 2 }).message('email field should be a valid email address. e.g: johndoe@gmail.com.').required(),
});
validation(req, res, schema, next);
}

}
1 change: 0 additions & 1 deletion src/middlewares/managerUserIdField.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const managerUserIdField = async (req, res, next) => {
if ((Object.keys(req.body).length === 0) || (Object.keys(req.body).length > 0 && !Object.keys(req.body).includes('username'))) {
const managerId = req.user.payload.id;
const myUsers = [];

await models.users.findAll({
where: {
lineManager: managerId,
Expand Down
9 changes: 5 additions & 4 deletions src/routes/api/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import express from 'express';
import UserController from '../../controllers/userController';
import profile from '../../controllers/profileController';
import EmailToken from '../../utils/EmailToken';
import validateResetpassword from '../../middlewares/checkResetpassword';
import verifyExist from '../../middlewares/verifyExist';
import validateToken from '../../middlewares/auth/validateToken';
import InputValidation from '../../middlewares/inputValidation';
Expand All @@ -12,7 +11,9 @@ import wrongSwitch from '../../middlewares/wrongSwitch';

const { signup, signIn, switchNotif } = UserController;
const { updateProfile, getProfile } = profile;
const { validateProfile, validateLogin, validateSignup } = InputValidation;
const {
validateProfile, validateLogin, validateSignup, validateEmail, validateResetpassword
} = InputValidation;


const router = express.Router();
Expand Down Expand Up @@ -274,8 +275,8 @@ const router = express.Router();

router.post('/register', validateSignup, verifyExist, confirmPassword, signup);
router.get('/verify/:token', UserController.userVerify);
router.post('/forgotpassword', validateResetpassword.checkEmail, UserController.Providelink);
router.patch('/resetpassword/:token', EmailToken.UseraccessRequired, validateResetpassword.checkReset, UserController.Changepassword);
router.post('/forgotpassword', validateEmail, UserController.Providelink);
router.patch('/resetpassword/:token', EmailToken.UseraccessRequired, validateResetpassword, UserController.Changepassword);
router.patch('/profile/:email', validateToken, user.compareData, validateProfile, updateProfile);
router.post('/login', validateLogin, signIn);
router.get('/profile/:email', validateToken, user.compareData, getProfile);
Expand Down
25 changes: 10 additions & 15 deletions src/tests/mockData/signupMockdata.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,29 +114,24 @@ const testdata = {
email: 'teamcaret41@gmail.com',
},
passwordData2: {
email: 'teamcaret@gmail.com',
newpassword: 'Pa$6W0rd',
confirmpassword: 'Pa$6W0rd',
newPassword: 'Pa$6W0rd',
confirmPassword: 'Pa$6W0rd',
},
Missingpassword: {
email: 'teamcaret@gmail.com',
newpassword: '',
confirmpassword: 'Pa$6W0rd',
newPassword: '',
confirmPassword: 'Pa$6W0rd',
},
Invalidpassword: {
email: 'teamcaret@gmail.com',
newpassword: 'Pa$6W0re',
confirmpassword: 'Pa$6W0rd',
newPassword: 'Pa$6W0re',
confirmPassword: 'Pa$6W0rd',
},
invaliduser2: {
email: 'teamcaret41@gmail.com',
newpassword: 'Pa$5W0re',
confirmpassword: 'Pa$6W0rd',
newPassword: 'Pa$5W0re',
confirmPassword: 'Pa$6W0rd',
},
wrongEmail: {
email: 'teamcaret41@gmail.com',
newpassword: 'Pa$5W0re',
confirmpassword: 'Pa$6W0rd',
newPassword: 'Pa$5W0re',
confirmPassword: 'Pa$6W0rd',
},

};
Expand Down
25 changes: 18 additions & 7 deletions src/tests/signupTest.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import EmailToken from '../utils/EmailToken';
const token = generateToken(testdata.verifyUser);
const validTroken = EmailToken.ResetToken(testdata.validuser);
const invalidToken = EmailToken.ResetToken(testdata.invaliduser);
const invalidToken2 = 'hdhdhdhj';

chai.should();
chai.use(chaiHttp);
Expand Down Expand Up @@ -158,25 +159,35 @@ describe('Signup Test Suite', () => {
done();
});
});

it('user Should not reset password with wrong email', done => {
it('user Should not reset password with wrong Token', done => {
chai.request(app)
.patch(`/api/v1/users/resetpassword/${validTroken}`)
.send(testdata.wrongEmail)
.patch(`/api/v1/users/resetpassword/${invalidToken}`)
.send(testdata.passwordData2)
.end((err, res) => {
res.should.have.property('status').eql(403);
res.body.should.have.property('message').eql('you are not authorized to access this page');
res.should.have.property('status').eql(404);
res.body.should.have.property('message').eql('can not find that user');
done();
});
});
it('user Should not reset password with wrong Token', done => {
chai.request(app)
.patch(`/api/v1/users/resetpassword/${invalidToken}`)
.patch(`/api/v1/users/resetpassword/${token}`)
.send(testdata.passwordData2)
.end((err, res) => {
res.should.have.property('status').eql(403);
res.body.should.have.property('message').eql('you are not authorized to access this page');
done();
});
});
it('user Should not reset password with invalid Token', done => {
chai.request(app)
.patch(`/api/v1/users/resetpassword/${invalidToken2}`)
.send(testdata.passwordData2)
.end((err, res) => {
res.should.have.property('status').eql(400);
res.body.should.have.property('message').eql('Invalid token!');
done();
});
});
});
28 changes: 16 additions & 12 deletions src/utils/EmailToken.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,24 @@ const ResetToken = user => {
// Access token required for a user
const UseraccessRequired = (req, res, next) => {
const { token } = req.params;
const { email } = req.body;
const decodedToken = jwt.decode(token, process.env.JWT_SECRET);

models.users.findOne({ where: { id: decodedToken.payload.id } })
.then(user => {
const now = moment().unix();
if (now > decodedToken.payload.expiration) {
return responseUtil(res, 400, strings.users.error.EXPERED);
}
if (!user || decodedToken.payload.send !== true || decodedToken.payload.email !== email) {
return responseUtil(res, 403, strings.users.error.ANAUTHORIZED);
}
});
next();
try {
models.users.findOne({ where: { id: decodedToken.payload.id } })
.then(user => {
const now = moment().unix();
if (now > decodedToken.payload.expiration) {
return responseUtil(res, 400, strings.users.error.EXPERED);
}
if (!user || decodedToken.payload.send !== true) {
return responseUtil(res, 403, strings.users.error.ANAUTHORIZED);
}
});
next();
} catch (error) {
return responseUtil(res, 400, strings.token.INVALID_TOKEN);
}

};

export default { ResetToken, UseraccessRequired };
1 change: 0 additions & 1 deletion src/utils/requestsSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ const requestsSearch = async options => {
requests.forEach(request => {
const { departureDate } = request.dataValues;
let { returnDate } = request.dataValues;

if (!returnDate) {
// eslint-disable-next-line max-len
const lastDestination = request.dataValues.destinations[request.dataValues.destinations.length - 1].dataValues;
Expand Down
2 changes: 1 addition & 1 deletion src/utils/stringsUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const strings = {
PASSWORD_CHANGED: 'password changed successfully',
SUCCESS_UPDATE: 'User Updated',
SUCCESSFUL_LOGIN: 'User logged in successfully!',
SUCCESSFUL_ASSIGN: 'you assign the role to user',
SUCCESSFUL_ASSIGN: 'you have assigned the role to this user',
ROLE_ADDED: 'role added successfully'
},
error: {
Expand Down
18 changes: 0 additions & 18 deletions src/validation/validateResetpassword.js

This file was deleted.

0 comments on commit 2531b2a

Please sign in to comment.