diff --git a/server/controllers/user.js b/server/controllers/user.js index b5e4f22..6956e13 100644 --- a/server/controllers/user.js +++ b/server/controllers/user.js @@ -3,6 +3,7 @@ import bcrypt from 'bcrypt'; import db from '../models'; import validateSignup from '../validators/validateSignup'; import validateSignin from '../validators/validateSignin'; +import serverError from '../errorHandler/serverError'; const { User } = db; @@ -69,8 +70,7 @@ class Users { }) .catch((error) => { return response.status(500).json({ - message: - 'Something went wrong! We are currently working on resolving this issue.' + message: serverError }); }); } @@ -120,10 +120,50 @@ class Users { }); }).catch(() => { return response.status(500).json({ - message: 'Something went wrong! We are currently working on resolving this issue.' + message: serverError }); }); } + + /** + * Update a user password + * + * @param {object} request - The request object + * @param {object} response - The response object + * + * @returns {object} The user object + */ + static editPassword(request, response) { + User.findById(request.userDetails.id) + .then((userDetail) => { + if (!userDetail) { + return response.status(400).json({ + message: 'User not found' + }); + } + const unhashedPassword = bcrypt + .compareSync(request.body.currentPassword, userDetail.password); + + if (!unhashedPassword) { + return response.status(400).json({ + message: 'Incorrect password.' + }); + } + const hashedUpdatedPassword = bcrypt + .hashSync(request.body.newPassword, 10); + return userDetail.update({ + password: hashedUpdatedPassword + }).then((updatedUser) => { + return response.status(201).json({ + message: 'Password updated successfully.', + }); + }); + }).catch(() => { + return response.status(500).json({ + error: serverError + }); + }); + } } export default Users; diff --git a/server/middleware/SessionControl.js b/server/middleware/SessionControl.js index ffa51dc..30b6e1c 100644 --- a/server/middleware/SessionControl.js +++ b/server/middleware/SessionControl.js @@ -4,7 +4,17 @@ import serverError from '../errorHandler/serverError'; const { User } = db; +/** + * Controls the user session + */ class SessionControl { + /** + * Checks if a user is logged in + * + * @param {object} request - The request object + * @param {object} response - The response object + * @param {function} next - Callback function + */ static isLoggedIn(request, response, next) { request.token = request.headers['x-access-token'] || request.query.token || request.headers.token; @@ -16,6 +26,14 @@ class SessionControl { next(); } + /** + * Verifies the identity of a user + * + * @param {object} request - The request object + * @param {object} response - The response object + * @param {function} next - Callback function + * + */ static isUser(request, response, next) { let verifyToken; request.userDetails = {}; diff --git a/server/routes/index.js b/server/routes/index.js index aeda030..274832b 100644 --- a/server/routes/index.js +++ b/server/routes/index.js @@ -41,4 +41,8 @@ module.exports = (app) => { app.get('/api/v1/centers/search', centerController.searchCenters); app.get('/api/v1/center/:centerId', centerController.getOneCenter); app.get('/api/v1/center/events/:venueId', eventController.getCenterEvents); + app.put( + '/api/v1/user/profile', sessionControl.isLoggedIn, + sessionControl.isUser, userController.editPassword + ); }; diff --git a/server/tests/seed/userseed.js b/server/tests/seed/userseed.js index 60769f3..8ccb922 100644 --- a/server/tests/seed/userseed.js +++ b/server/tests/seed/userseed.js @@ -1,8 +1,9 @@ import jwt from 'jsonwebtoken'; const adminUserID = '1'; -const dummyUserID = '3'; +const dummyUserID = '5'; const secondDummyUserId = '6'; +const nonExistentUserID = '100'; const dummyUser = { id: dummyUserID, @@ -28,6 +29,17 @@ export const secondDummyUser = { }, process.env.SECRET).toString() }; +export const nonExistentUser = { + id: nonExistentUserID, + username: 'secondDummyUser', + email: 'secondDummyUserEmail@gmail.com', + password: 'qwertyuiop', + phoneNumber: '08012345678', + token: jwt.sign({ + id: nonExistentUserID, + username: 'secondDummyUser' + }, process.env.SECRET).toString() +}; export const adminUser = { id: adminUserID, diff --git a/server/tests/user.test.js b/server/tests/user.test.js index 132ed2d..00eaf16 100644 --- a/server/tests/user.test.js +++ b/server/tests/user.test.js @@ -1,7 +1,7 @@ import supertest from 'supertest'; import { expect } from 'chai'; import app from '../app'; -import dummyUser from './seed/userseed'; +import dummyUser, { nonExistentUser } from './seed/userseed'; const request = supertest(app); const signupAPI = '/api/v1/users/signup'; @@ -244,4 +244,47 @@ describe('Integration tests for Authentication', () => { }); }); }); + describe('User profile test', () => { + it('should return an error if the user is not found', (done) => { + request.put(`/api/v1/user/profile?token=${nonExistentUser.token}`) + .set('Connection', 'keep alive') + .set('Content-Type', 'application/json') + .type('form') + .send(nonExistentUser) + .end((error, response) => { + expect(response.status).to.equal(400); + done(); + }); + }); + it('should fail to update a user\'s password if they provide an incorrect current password', (done) => { + const testUser = { currentPassword: 'somethingelse', newPassword: 'newPasswordMan' }; + request.put(`/api/v1/user/profile?token=${dummyUser.token}`) + .set('Connection', 'keep alive') + .set('Content-Type', 'application/json') + .type('form') + .send(testUser) + .end((error, response) => { + expect(response.status).to.equal(400); + expect(response.body.message).to.equal('Incorrect password.'); + done(); + }); + }); + it('should update the password of a signed in user', (done) => { + const testUser = { + currentPassword: dummyUser.password, + newPassword: 'newPasswordhere' + }; + request.put(`/api/v1/user/profile?token=${dummyUser.token}`) + .set('Connection', 'keep alive') + .set('Content-Type', 'application/json') + .type('form') + .send(testUser) + .end((error, response) => { + expect(response.status).to.equal(201); + expect(response.body.message).to + .equal('Password updated successfully.'); + done(); + }); + }); + }); });