From 5c33a404fba1cb9ac5b69c08a2ffe8e5d38a99be Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Sat, 21 Nov 2015 15:00:31 +0100 Subject: [PATCH] handle mongoose validation errors, fix bug in import and add more tests for errors --- .../v3/unit/middlewares/errorHandler.test.js | 59 +++++++++++++++++++ website/src/controllers/api-v3/user.js | 2 +- .../src/middlewares/api-v3/errorHandler.js | 28 +++++++-- 3 files changed, 82 insertions(+), 7 deletions(-) diff --git a/test/api/v3/unit/middlewares/errorHandler.test.js b/test/api/v3/unit/middlewares/errorHandler.test.js index afc506e976..4987e1e8ac 100644 --- a/test/api/v3/unit/middlewares/errorHandler.test.js +++ b/test/api/v3/unit/middlewares/errorHandler.test.js @@ -82,6 +82,65 @@ describe('errorHandler', () => { }); }); + it('handle http-errors errors', () => { + let error = new Error('custom message'); + error.statusCode = 422; + + errorHandler(error, req, res, next); + + expect(res.status).to.be.calledOnce; + expect(res.json).to.be.calledOnce; + + expect(res.status).to.be.calledWith(error.statusCode); + expect(res.json).to.be.calledWith({ + error: error.name, + message: error.message, + }); + }); + + it('handle express-validator errors', () => { + let error = [{param: 'param', msg: 'invalid param'}]; + + errorHandler(error, req, res, next); + + expect(res.status).to.be.calledOnce; + expect(res.json).to.be.calledOnce; + + expect(res.status).to.be.calledWith(400); + expect(res.json).to.be.calledWith({ + error: 'BadRequest', + message: 'Invalid request parameters.', + errors: error, + }); + }); + + it('handle Mongoose Validation errors', () => { + let error = new Error('User validation failed.'); + error.name = 'ValidationError'; + + error.errors = { + 'auth.local.email': { + path: 'auth.local.email', + message: 'Invalid email.', + value: 'not an email', + }, + }; + + errorHandler(error, req, res, next); + + expect(res.status).to.be.calledOnce; + expect(res.json).to.be.calledOnce; + + expect(res.status).to.be.calledWith(400); + expect(res.json).to.be.calledWith({ + error: 'BadRequest', + message: 'User validation failed.', + errors: [ + {path: 'auth.local.email', message: 'Invalid email.', value: 'not an email'} + ] + }); + }); + it('logs error', () => { let error = new BadRequest(); diff --git a/website/src/controllers/api-v3/user.js b/website/src/controllers/api-v3/user.js index 8e7cbb4c62..8af250674b 100644 --- a/website/src/controllers/api-v3/user.js +++ b/website/src/controllers/api-v3/user.js @@ -4,7 +4,7 @@ import { authWithHeaders } from '../../middlewares/api-v3/auth'; import { NotAuthorized, } from '../../libs/api-v3/errors'; -import passwordUtils from '../../libs/api-v3/password'; +import * as passwordUtils from '../../libs/api-v3/password'; import { model as User } from '../../models/user'; import EmailUnsubscription from '../../models/emailUnsubscription'; import { sendTxn as sendTxnEmail } from '../../libs/api-v3/email'; diff --git a/website/src/middlewares/api-v3/errorHandler.js b/website/src/middlewares/api-v3/errorHandler.js index 5bf90f6969..616af12ffb 100644 --- a/website/src/middlewares/api-v3/errorHandler.js +++ b/website/src/middlewares/api-v3/errorHandler.js @@ -6,6 +6,7 @@ import { BadRequest, InternalServerError, } from '../../libs/api-v3/errors'; +import { map } from 'lodash'; export default function errorHandler (err, req, res, next) { if (!err) return next(); @@ -36,7 +37,19 @@ export default function errorHandler (err, req, res, next) { // Handle errors by express-validator if (Array.isArray(err) && err[0].param && err[0].msg) { responseErr = new BadRequest('Invalid request parameters.'); - responseErr.errors = err; + responseErr.errors = err; // TODO format + } + + // Handle mongoose validation errors + if (err.name === 'ValidationError') { + responseErr = new BadRequest(err.message); + responseErr.errors = map(err.errors, (mongooseErr) => { + return { + path: mongooseErr.path, + message: mongooseErr.message, + value: mongooseErr.value, + }; + }); } if (!responseErr || responseErr.httpCode >= 500) { @@ -48,11 +61,14 @@ export default function errorHandler (err, req, res, next) { responseErr = new InternalServerError(); } - // TODO unless status >= 500 return data attached to errors + let jsonRes = { + error: responseErr.name, + message: responseErr.message, + }; + + if (responseErr.errors) jsonRes.errors = responseErr.errors; + return res .status(responseErr.httpCode) - .json({ - error: responseErr.name, - message: responseErr.message, - }); + .json(jsonRes); }