diff --git a/packages/component-invite/src/helpers/helpers.js b/packages/component-invite/src/helpers/helpers.js index bf0077c7692b634c51ab168063b5b2f16e4ee3fa..1376dc9945afcf01c65692b1ae80b7ea3755f151 100644 --- a/packages/component-invite/src/helpers/helpers.js +++ b/packages/component-invite/src/helpers/helpers.js @@ -44,7 +44,7 @@ const validateEmailAndToken = async (email, token, userModel) => { message: e.details[0].message, } } - logger.error(e) + logger.error('internal server error') return { success: false, status: 500, diff --git a/packages/component-invite/src/routes/reset.js b/packages/component-invite/src/routes/reset.js index cb498f1eb3a9434be192112df5043efefd43dd20..983177fa855832d97dfcc09bca309f27aef86af6 100644 --- a/packages/component-invite/src/routes/reset.js +++ b/packages/component-invite/src/routes/reset.js @@ -2,12 +2,30 @@ const logger = require('@pubsweet/logger') const helpers = require('../helpers/helpers') module.exports = models => async (req, res) => { - if (!helpers.checkForUndefinedParams(req.body)) { + const { + email, + firstName, + lastName, + title, + affiliation, + password, + token, + } = req.body + if ( + !helpers.checkForUndefinedParams( + email, + firstName, + lastName, + title, + affiliation, + password, + token, + ) + ) { res.status(400).json({ error: 'missing required params' }) return } - const { password } = req.body if (password.length < 7) { res .status(400) @@ -18,18 +36,9 @@ module.exports = models => async (req, res) => { return } - const updateFields = { - password, - firstName: req.body.firstName, - lastName: req.body.lastName, - affiliation: req.body.affiliation, - title: req.body.title, - isConfirmed: true, - } - const validateResponse = await helpers.validateEmailAndToken( - req.body.email, - req.body.token, + email, + token, models.User, ) if (validateResponse.success === false) { @@ -44,6 +53,15 @@ module.exports = models => async (req, res) => { return } + const updateFields = { + password, + firstName, + lastName, + affiliation, + title, + isConfirmed: true, + } + let newUser = Object.assign( validateResponse.user, updateFields, diff --git a/packages/component-invite/src/tests/fixtures/users.js b/packages/component-invite/src/tests/fixtures/users.js index dc4e6ed5c0483d6e894d0139ca2cde58ffe058ef..0e207530439ded9a197b616c4f0e74cd8d6ceedd 100644 --- a/packages/component-invite/src/tests/fixtures/users.js +++ b/packages/component-invite/src/tests/fixtures/users.js @@ -1,4 +1,4 @@ -module.exports = { +const users = { admin: { type: 'user', username: 'admin', @@ -11,10 +11,17 @@ module.exports = { type: 'user', username: 'editor', email: 'editor@example.com', - password: 'test', + password: 'test1234', admin: false, id: 'editor123', roles: ['editorInChief'], + passwordResetToken: 'token123', + firstName: 'vlad', + lastName: 'dracul', + affiliation: 'MIT', + title: 'prof', + save: jest.fn(() => users.editorInChief), + isConfirmed: false, }, handlingEditor: { type: 'user', @@ -26,3 +33,5 @@ module.exports = { roles: ['handlingEditor'], }, } + +module.exports = users diff --git a/packages/component-invite/src/tests/get.test.js b/packages/component-invite/src/tests/get.test.js new file mode 100644 index 0000000000000000000000000000000000000000..db3b68af7effa3400e2655e0b4762af92f7b63d1 --- /dev/null +++ b/packages/component-invite/src/tests/get.test.js @@ -0,0 +1,103 @@ +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' +process.env.SUPPRESS_NO_CONFIG_WARNING = true + +const httpMocks = require('node-mocks-http') +const fixtures = require('./fixtures/fixtures') + +const buildModels = user => { + const models = { + User: { + findByEmail: jest.fn( + () => + user instanceof Error ? Promise.reject(user) : Promise.resolve(user), + ), + }, + } + + return models +} +const user = fixtures.users.editorInChief +const query = { + email: user.email, + token: user.passwordResetToken, +} +describe('Get inivte data route handler', () => { + it('should return success email and token are correct', async () => { + const req = httpMocks.createRequest() + req.query = query + const res = httpMocks.createResponse() + const models = buildModels(user) + await require('../routes/get')(models)(req, res) + + expect(res.statusCode).toBe(200) + const data = JSON.parse(res._getData()) + expect(data.firstName).toEqual(user.firstName) + }) + it('should return an error when some parameters are missing', async () => { + delete query.email + const req = httpMocks.createRequest() + req.query = query + + const res = httpMocks.createResponse() + const models = buildModels(user) + await require('../routes/get')(models)(req, res) + expect(res.statusCode).toBe(400) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('missing required params') + query.email = user.email + }) + it('should return an error when tokens do not match', async () => { + query.token = 'wrongToken' + const req = httpMocks.createRequest() + req.query = query + + const res = httpMocks.createResponse() + const models = buildModels(user) + await require('../routes/get')(models)(req, res) + expect(res.statusCode).toBe(400) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('invalid request') + query.token = user.passwordResetToken + }) + it('should return an error when user is not found', async () => { + const req = httpMocks.createRequest() + req.query = query + const error = new Error() + error.name = 'NotFoundError' + error.status = 404 + const res = httpMocks.createResponse() + const models = buildModels(error) + await require('../routes/get')(models)(req, res) + expect(res.statusCode).toBe(404) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('user not found') + }) + it('should return an error when there is a validation problem', async () => { + const req = httpMocks.createRequest() + req.query = query + const error = new Error() + error.name = 'ValidationError' + error.status = 400 + error.details = [] + error.details.push({ message: 'validation error' }) + const res = httpMocks.createResponse() + const models = buildModels(error) + await require('../routes/get')(models)(req, res) + expect(res.statusCode).toBe(400) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('validation error') + }) + it('should return an error when there is a system problem', async () => { + const req = httpMocks.createRequest() + req.query = query + const error = new Error() + error.details = [] + error.details.push({ message: 'internal server error' }) + const res = httpMocks.createResponse() + const models = buildModels(error) + await require('../routes/get')(models)(req, res) + expect(res.statusCode).toBe(500) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('internal server error') + }) +}) diff --git a/packages/component-invite/src/tests/post.test.js b/packages/component-invite/src/tests/post.test.js index 3d90848cf1c69a3c917d68093c2f63ac66335a26..e6e2d5c2defe50f3cf3aa836bcc11137e7dea96a 100644 --- a/packages/component-invite/src/tests/post.test.js +++ b/packages/component-invite/src/tests/post.test.js @@ -170,8 +170,8 @@ describe('Post invite route handler', () => { const data = JSON.parse(res._getData()) expect(data.error).toEqual('User already exists') }) - it('should return success when the editor in chief invites a manuscript role with a collection', async () => { - body.role = manuscriptRoles[random(0, manuscriptRoles.length - 1)] + it('should return success when the editor in chief invites a handling Editor with a collection', async () => { + body.role = 'handlingEditor' body.admin = false const req = httpMocks.createRequest({ body, diff --git a/packages/component-invite/src/tests/reset.test.js b/packages/component-invite/src/tests/reset.test.js new file mode 100644 index 0000000000000000000000000000000000000000..b2ea34c15e50105b1e904834bb9c58fb695ce1c8 --- /dev/null +++ b/packages/component-invite/src/tests/reset.test.js @@ -0,0 +1,125 @@ +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' +process.env.SUPPRESS_NO_CONFIG_WARNING = true + +const httpMocks = require('node-mocks-http') +const fixtures = require('./fixtures/fixtures') +const UserMock = require('./mocks/User') + +const buildModels = user => { + const models = { + User: {}, + } + UserMock.findByEmail = jest.fn( + () => + user instanceof Error ? Promise.reject(user) : Promise.resolve(user), + ) + + models.User = UserMock + return models +} + +const editorInChiefUser = fixtures.users.editorInChief +const body = { + email: editorInChiefUser.email, + firstName: editorInChiefUser.firstName, + lastName: editorInChiefUser.lastName, + title: editorInChiefUser.email, + affiliation: editorInChiefUser.email, + password: editorInChiefUser.password, + token: editorInChiefUser.passwordResetToken, + isConfirmed: false, +} + +const notFoundError = new Error() +notFoundError.name = 'NotFoundError' +notFoundError.status = 404 + +describe('Password reset after invite route handler', () => { + it('should return success when the body is correct', async () => { + const req = httpMocks.createRequest({ body }) + const res = httpMocks.createResponse() + const models = buildModels(editorInChiefUser) + await require('../routes/reset')(models)(req, res) + + expect(res.statusCode).toBe(200) + const data = JSON.parse(res._getData()) + expect(data.firstName).toEqual(body.firstName) + expect(data.email).toEqual(body.email) + editorInChiefUser.passwordResetToken = 'token123' + }) + it('should return an error when some parameters are missing', async () => { + delete body.email + const req = httpMocks.createRequest({ body }) + + const res = httpMocks.createResponse() + const models = buildModels(editorInChiefUser) + await require('../routes/reset')(models)(req, res) + expect(res.statusCode).toBe(400) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('missing required params') + body.email = editorInChiefUser.email + }) + it('should return an error when the password is too small', async () => { + body.password = 'small' + const req = httpMocks.createRequest({ body }) + + const res = httpMocks.createResponse() + const models = buildModels(editorInChiefUser) + await require('../routes/reset')(models)(req, res) + expect(res.statusCode).toBe(400) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual( + 'password needs to be at least 7 characters long', + ) + body.password = editorInChiefUser.password + }) + it('should return an error when user is not found', async () => { + const req = httpMocks.createRequest({ body }) + const error = new Error() + error.name = 'NotFoundError' + error.status = 404 + const res = httpMocks.createResponse() + const models = buildModels(error) + await require('../routes/reset')(models)(req, res) + expect(res.statusCode).toBe(404) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('user not found') + }) + it('should return an error when there is a validation problem', async () => { + const req = httpMocks.createRequest({ body }) + const error = new Error() + error.name = 'ValidationError' + error.status = 400 + error.details = [] + error.details.push({ message: 'validation error' }) + const res = httpMocks.createResponse() + const models = buildModels(error) + await require('../routes/reset')(models)(req, res) + expect(res.statusCode).toBe(400) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('validation error') + }) + it('should return an error when there is a system problem', async () => { + const req = httpMocks.createRequest({ body }) + const error = new Error() + error.details = [] + error.details.push({ message: 'internal server error' }) + const res = httpMocks.createResponse() + const models = buildModels(error) + await require('../routes/reset')(models)(req, res) + expect(res.statusCode).toBe(500) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('internal server error') + }) + it('should return an error when the user is already confirmed', async () => { + editorInChiefUser.isConfirmed = true + const req = httpMocks.createRequest({ body }) + const res = httpMocks.createResponse() + const models = buildModels(editorInChiefUser) + await require('../routes/reset')(models)(req, res) + expect(res.statusCode).toBe(400) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('User is already confirmed') + editorInChiefUser.isConfirmed = false + }) +})