Skip to content

Commit

Permalink
fix(validation): respect allowUnknown route property (krakenjs#169)
Browse files Browse the repository at this point in the history
This ensures it is possible to allow unknown properties in request bodies (Postel’s Law), by respecting the `x-hapi-options` option.

Co-authored-by: Kristofer Sommestad <[email protected]>
  • Loading branch information
sommestad and Kristofer Sommestad authored Apr 3, 2020
1 parent 48b1a84 commit 429bfbf
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 5 deletions.
3 changes: 2 additions & 1 deletion lib/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ const create = async function (server, { api, basedir, cors, vhost, handlers, ex
const skipValidation = options.payload && options.payload.parse === false;

if (operation.parameters && !skipValidation) {
const v = validator.makeAll(operation.parameters, operation.consumes || api.consumes);
const allowUnknownProperties = xoptions.validate && xoptions.validate.options && xoptions.validate.options.allowUnknown === true;
const v = validator.makeAll(operation.parameters, operation.consumes || api.consumes, allowUnknownProperties);
options.validate = v.validate;
options.ext = {
onPreAuth: { method: v.routeExt }
Expand Down
9 changes: 5 additions & 4 deletions lib/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ const enjoi = Enjoi.defaults({ types, refineType });

const create = function (options = {}) {

const makeValidator = function (parameter, consumes) {
const makeValidator = function (parameter, consumes, allowUnknownProperties = false) {
const coerce = coercion(parameter, consumes);

let schema;

if ((parameter.in === 'body' || parameter.in === 'formData') && parameter.schema) {
schema = enjoi.schema(parameter.schema);
schema = enjoi.schema(parameter.schema).unknown(allowUnknownProperties);
}
else {
const template = {
Expand Down Expand Up @@ -96,6 +96,7 @@ const create = function (options = {}) {
},
validate: async function (value) {
const data = coerce && value && coerce(value);
console.log('validation data: %j', data);
const result = await schema.validate(data);

if (result.error) {
Expand Down Expand Up @@ -132,7 +133,7 @@ const create = function (options = {}) {
return schemas;
};

const makeAll = function (parameters = [], consumes) {
const makeAll = function (parameters = [], consumes, allowUnknownProperties = false) {
const routeExt = [];
const validate = {};
const formValidators = {};
Expand All @@ -149,7 +150,7 @@ const create = function (options = {}) {
};

for (const parameter of parameters) {
const validator = makeValidator(parameter, consumes);
const validator = makeValidator(parameter, consumes, allowUnknownProperties);

switch (validator.parameter.in) {
case 'header':
Expand Down
78 changes: 78 additions & 0 deletions test/test-hapi-openapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,84 @@ Test('test plugin', function (t) {

});

t.test('hapi allowUnknown request payload properties', async function (t) {
t.plan(1);

const server = new Hapi.Server();

const api = {
swagger: '2.0',
info: {
title: 'Minimal',
version: '1.0.0'
},
paths: {
'/test': {
post: {
'x-hapi-options': {
validate: {
options: {
allowUnknown: true
}
}
},
parameters: [
{
name: 'thing',
in: 'body',
schema: {
type: 'object',
properties: {
id: {
type: 'string'
}
}
}
}
],
responses: {
200: {
description: 'default response'
}
}
}
}
}
};

try {
await server.register({
plugin: OpenAPI,
options: {
api,
handlers: {
test: {
post() {
return 'test';
}
}
}
}
});

let response = await server.inject({
method: 'POST',
url: '/test',
payload: {
id: 'string-id',
excessive: 42
}
});

t.strictEqual(response.statusCode, 200, `${response.request.path} OK.`);

}
catch (error) {
t.fail(error.message);
}

});

t.test('hapi operation tags', async function (t) {
t.plan(1);

Expand Down

0 comments on commit 429bfbf

Please sign in to comment.