Skip to content

Commit

Permalink
Merge pull request #469 from virginiam1203/Issue-#468-Handle-error-ob…
Browse files Browse the repository at this point in the history
…ject-passed-into-raiseError

Issue #468 handle error object passed into raise error
  • Loading branch information
nelsonic authored Jun 4, 2024
2 parents 93e105d + b55b2c3 commit 00e5759
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 52 deletions.
19 changes: 13 additions & 6 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,12 +301,19 @@ internals.raiseError = function raiseError(
// the errorFunc must return an object with keys:
// errorType and message, we need not worry about
// errorContext being undefined

const error = Boom[errorContext.errorType](
errorContext.message,
errorContext.scheme,
errorContext.attributes
);
let error;
if (
errorContext.error instanceof Error &&
errorContext.errorType === 'boomify'
) {
error = Boom.boomify(errorContext.error);
} else {
error = Boom[errorContext.errorType](
errorContext.message,
errorContext.scheme,
errorContext.attributes
);
}

return isMissingToken
? Object.assign(error, {
Expand Down
124 changes: 78 additions & 46 deletions test/validate_func.test.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,93 @@
const test = require('tape');
const Hapi = require('@hapi/hapi');
const JWT = require('jsonwebtoken');
const test = require('tape');
const JWT = require('jsonwebtoken');
const secret = 'NeverShareYourSecret';

test('Should respond with 500 series error when validate errs', async function (t) {

const server = new Hapi.server({ debug: false });
try {
await server.register(require('../'));
} catch (err) {
t.ifError(err, 'No error registering hapi-auth-jwt2 plugin');
}
server.auth.strategy('jwt', 'jwt', {
key: secret,
validate: function (decoded, request, h) {
if (decoded.id === 138) {
throw new Error('ASPLODE');
}
if (decoded.id === 139) {
return { isValid: false }
}
if (decoded.id === 140) {
return { isValid: false, errorMessage: 'Bad ID' }
}
return { response: h.redirect('https://dwyl.com') }
},
verifyOptions: {algorithms: ['HS256']}
});

server.route({
method: 'POST',
path: '/privado',
handler: function (req, h) { return 'PRIVADO'; },
config: { auth: 'jwt' }
});
const server = require('./validate_func_server'); // test server which in turn loads our module

test('Should respond with 500 when validate function throws an error', async function (t) {
let options = {
method: 'POST',
url: '/privado',
headers: {Authorization: JWT.sign({id: 138, name: 'Test'}, secret)}
headers: { Authorization: JWT.sign({ id: 138, name: 'Test' }, secret) },
};

let response = await server.inject(options);
t.equal(response.statusCode, 500, 'Server returned 500 for validate error');
t.end();
});

test('Should redirect when validate function returns a response object with redirect', async function (t) {
let options = {
method: 'POST',
url: '/privado',
headers: { Authorization: JWT.sign({ id: 200, name: 'Test' }, secret) },
};

let response = await server.inject(options);
t.equal(response.statusCode, 302, 'Server redirected successfully');
t.equal(
response.headers.location,
'https://dwyl.com',
'Server redirected to correct URL'
);
t.end();
});

test('Should respond with 401 when validate function returns isValid false', async function (t) {
let options = {
method: 'POST',
url: '/privado',
headers: { Authorization: JWT.sign({ id: 139, name: 'Test' }, secret) },
};

options.headers.Authorization = JWT.sign({ id: 200, name: 'Test' }, secret);
response = await server.inject(options);
t.equal(response.statusCode, 302, 'Server redirect status code');
t.equal(response.headers.location, 'https://dwyl.com', 'Server redirect header');
let response = await server.inject(options);
t.equal(
response.statusCode,
401,
'Server returned 401 for invalid credentials'
);
t.equal(
response.result.message,
'Invalid credentials',
'Default error message for invalid credentials'
);
t.end();
});

options.headers.Authorization = JWT.sign({id: 139, name: 'Test'}, secret);
response = await server.inject(options);
t.equal(response.statusCode, 401, 'Server errors when isValid false');
t.equal(response.result.message, 'Invalid credentials', 'Default error message when custom not provided');
test('Should respond with custom error message when validate function returns custom errorMessage', async function (t) {
let options = {
method: 'POST',
url: '/privado',
headers: { Authorization: JWT.sign({ id: 140, name: 'Test' }, secret) },
};

options.headers.Authorization = JWT.sign({id: 140, name: 'Test'}, secret);
response = await server.inject(options);
t.equal(response.result.message, 'Bad ID', 'Custom error message when provided');
let response = await server.inject(options);
t.equal(response.statusCode, 401, 'Server returned 401 for custom error');
t.equal(
response.result.message,
'Bad ID',
'Custom error message for invalid credentials'
);
t.end();
});

test('Should respond with non-generic error message when validate function throws a non-server error', async function (t) {
let options = {
method: 'POST',
url: '/privado',
headers: { Authorization: JWT.sign({ id: 141, name: 'Test' }, secret) },
};

let response = await server.inject(options);
t.equal(
response.statusCode,
404,
'Server returned 404 for resource not found'
);
t.equal(
response.result.message,
'Resource not found',
'Error message for resource not found'
);
t.end();
});
46 changes: 46 additions & 0 deletions test/validate_func_server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const Boom = require('@hapi/boom');
const Hapi = require('@hapi/hapi');
const secret = 'NeverShareYourSecret';

// for debug options see: https://hapi.dev/tutorials/logging/
let debug;
// debug = { debug: { 'request': ['error', 'uncaught'] } };
debug = { debug: false };
const server = new Hapi.server(debug);

const init = async () => {
await server.register(require('../'));

server.auth.strategy('jwt', 'jwt', {
key: secret,
validate: function (decoded, request, h) {
if (decoded.id === 138) {
throw new Error('ASPLODE');
}
if (decoded.id === 139) {
return { isValid: false };
}
if (decoded.id === 140) {
return { isValid: false, errorMessage: 'Bad ID' };
}
if (decoded.id === 141) {
throw Boom.notFound('Resource not found');
}
return { response: h.redirect('https://dwyl.com') };
},
verifyOptions: { algorithms: ['HS256'] },
});

server.route({
method: 'POST',
path: '/privado',
handler: function (req, h) {
return 'PRIVADO';
},
config: { auth: 'jwt' },
});
};

init();

module.exports = server;

0 comments on commit 00e5759

Please sign in to comment.