Skip to content

Commit

Permalink
[Feature #165412916] Send confirmation email when email is updated
Browse files Browse the repository at this point in the history
  • Loading branch information
rwajon committed Jul 11, 2019
1 parent 257fff5 commit 2694474
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 12 deletions.
15 changes: 8 additions & 7 deletions src/controllers/UserController.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,21 @@ export default class UserController {
*/
static async update(req, res) {
const userId = req.userId || req.user.id;

if (req.body.password) {
req.body.password = helper.password.hash(req.body.password);
}
const updatedUser = await User.update(req.body, { id: userId });

if (updatedUser.errors) {
const errors = helper.checkCreateUpdateUserErrors(updatedUser.errors);
return res.status(errors.code).json({ errors: errors.errors });
}

delete updatedUser.password;

if (req.changeEmail.newEmail) {
await helper.sendMail(req.changeEmail.newEmail, 'updateEmail', { email: req.body.email });
}

return res.status(status.OK).json({
message: Object.keys(updatedUser).length
? 'profile successfully updated'
: "this account doesn't exist",
message: `Profile successfully updated. ${req.changeEmail.message}`,
user: updatedUser
});
}
Expand Down
3 changes: 2 additions & 1 deletion src/helpers/mailer/templates/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import notification from './notification';
import signup from './signup';
import resetPassword from './resetPassword';
import updateEmail from './updateEmail';

export { notification };
export { notification, updateEmail };
export { signup, resetPassword };
18 changes: 18 additions & 0 deletions src/helpers/mailer/templates/updateEmail.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import dotenv from 'dotenv';
import { generate as generateToken } from '../../tokens';

dotenv.config();

export default (data) => {
const message = {};
const token = generateToken({ email: data.email }, { expiresIn: '1h' });
const appUrl = process.env.APP_URL_FRONTEND;
const link = `${appUrl}/reset-password/${token}`;
message.subject = 'Reset your password - Authors Haven';
message.html = `Hello</br>,
<p>You are receiving this because you (or someone else) have requested the reset of your current email,<br>
Click on the link bellow to confirm the process<br>
<br><br><br>
<a href='${link}' style="margin:35px 0;padding:15px 35px;background:#266cef;color:#ffffff;clear:both;border-radius:30px;text-decoration:none" target='_blank'>Confirm email</a></p>`;
return message;
};
29 changes: 29 additions & 0 deletions src/middlewares/checkUpdateUser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import status from '../config/status';
import * as helper from '../helpers';
import { User } from '../queries';

export default async (req, res, next) => {
let [isEmailUsed, isSameOldEmail] = [false, false];
req.changeEmail = { newEmail: '', message: '' };

if (req.body.password) {
req.body.password = helper.password.hash(req.body.password);
}
if (req.body.email && req.user.role !== 'admin') {
const findUser = await User.findOne({ email: req.body.email });
if (!findUser.errors && Object.keys(findUser).length > 0) {
isEmailUsed = req.user.id !== findUser.id;
isSameOldEmail = req.body.email === findUser.email;
}
if (!isSameOldEmail) {
req.changeEmail.newEmail = req.body.email;
req.changeEmail.message = 'Check your email to confirm your new email';
}
delete req.body.email;
}

return (
(isEmailUsed && res.status(status.EXIST).json({ errors: { email: 'email already used' } }))
|| next()
);
};
11 changes: 10 additions & 1 deletion src/routes/api/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,26 @@ import asyncHandler from '../../middlewares/asyncHandler';
import AuthLocalController from '../../controllers/AuthLocalController';
import isActiveUser from '../../middlewares/isActiveUser';
import verifyAdmin from '../../middlewares/verifyAdmin';
import checkUpdateUser from '../../middlewares/checkUpdateUser';

const router = Router();

router.put('/', verifyToken, checkUpdateUserPermission, validateUser, UserController.update); // update user profile
router.put(
'/',
verifyToken,
checkUpdateUserPermission,
validateUser,
checkUpdateUser,
UserController.update
); // update user profile
router.get('/authors', verifyToken, asyncHandler(UserController.getAllAuthors));
router.put(
'/:id',
verifyToken,
validateUser,
isActiveUser,
checkUpdateUserPermission,
checkUpdateUser,
UserController.update
); // update user profile by id

Expand Down
19 changes: 16 additions & 3 deletions src/tests/routes/users.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,28 @@ describe('Users routes', () => {
chai
.request(app)
.put('/api/v1/users')
.send({ username: 'anotherusername', password: 'Abcd1234!', email: 'aaa@bbb.com' })
.set('access-token', accessTokenAdmin)
.send({ username: 'anotherusername', password: 'Abcd1234!', email: 'email@email.com' })
.set('access-token', accessTokenNormalUser)
.end((err, res) => {
expect(res.status).to.be.equal(status.OK);
expect(res.body).to.include.keys('user');
expect(res.body).to.not.include.keys('errors');
done();
});
});
it('should not update the user profile if the email is already used', (done) => {
chai
.request(app)
.put('/api/v1/users')
.send({ email: createdUserTwo.email })
.set('access-token', accessTokenNormalUser)
.end((err, res) => {
expect(res.status).to.be.equal(status.EXIST);
expect(res.body).to.not.include.keys('user');
expect(res.body).to.include.keys('errors');
done();
});
});
it('should update the user profile', (done) => {
chai
.request(app)
Expand Down Expand Up @@ -174,7 +187,7 @@ describe('Users routes', () => {
chai
.request(app)
.put(`/api/v1/users/${createdUserTwo.id}`)
.send({ email: 'aaa@bbb.com' })
.send({ email: createdUserOne.email })
.set('access-token', accessTokenAdmin)
.end((err, res) => {
expect(res.status).to.be.equal(status.EXIST);
Expand Down

0 comments on commit 2694474

Please sign in to comment.