@@ -1,27 +1,30 @@ | |||
const sanitizer = require('sanitizer'); | |||
// Verifies a single property is well formed | |||
const verifyProp = (prop, expected) => new Promise((resolve, reject) => { | |||
const verifyProp = async (prop, expected) => { | |||
if (!expected.optional && !prop) | |||
return reject({code: 400, message: expected.name + ' not specified.'}); | |||
if (prop && expected.type && typeof prop !== expected.type) | |||
return reject({code: 400, message: expected.name + ' malformed.'}); | |||
if (prop && expected.instance && !(prop instanceof expected.instance)) | |||
return reject({code: 400, message: expected.name + ' malformed.'}); | |||
if (prop && expected.maxLength && prop.length > expected.maxLength) | |||
return reject({code: 400, message: expected.name + ' too long.'}); | |||
if (prop && expected.sanitize && sanitizer.sanitize(prop) !== prop) | |||
return reject({code: 400, message: expected.name + ' contains invalid characters.'}); | |||
if (prop && expected.restrict && prop.replace(expected.restrict, '') !== prop) | |||
return reject({code: 400, message: expected.name + ' contains invalid characters.'}); | |||
resolve(); | |||
}); | |||
throw {code: 400, message: expected.name + ' not specified.'}; | |||
else if (!prop) | |||
return; | |||
if (expected.type) { | |||
if (expected.type === 'date' && isNaN(new Date(prop))) | |||
throw {code: 400, message: `${expected.name} malformed.`}; | |||
else if (expected.type === 'array' && !(prop instanceof Array)) | |||
throw {code: 400, message: `${expected.name} malformed.`}; | |||
else if (typeof prop !== expected.type) | |||
throw {code: 400, message: `${expected.name} malformed.`}; | |||
} | |||
if (expected.maxLength && prop.length > expected.maxLength) | |||
throw {code: 400, message: `${expected.name} too long.`}; | |||
if (expected.sanitize && sanitizer.sanitize(prop) !== prop) | |||
throw {code: 400, message: `${expected.name} contains invalid characters.`}; | |||
if (expected.restrict && prop.replace(expected.restrict, '') !== prop) | |||
throw {code: 400, message: `${expected.name} contains invalid characters.`}; | |||
}; | |||
// Verifies the entire request body is well formed | |||
// expectedProps follows the format: | |||
@@ -18,8 +18,21 @@ describe('Body Verification', () => { | |||
}; | |||
it('must continue properly with valid prop', () => { | |||
const expected = [{name: 'test'}]; | |||
return testVerifyBody({test: 'test'}, expected); | |||
const tests = [{ | |||
expected: [{name: 'test'}], | |||
body: {test: 'test'} | |||
}, { | |||
expected: [{name: 'test', type: 'array'}], | |||
body: {test: [1, 2, 3]} | |||
}, { | |||
expected: [{name: 'test', type: 'date'}], | |||
body: {test: '11/12/2018'} | |||
}, { | |||
expected: [{name: 'test', type: 'date'}], | |||
body: {test: 1546368715} | |||
}]; | |||
return Promise.all(tests.map(test => testVerifyBody(test.body, test.expected))); | |||
}); | |||
it('must continue with a missing but optional prop', () => { | |||
@@ -32,13 +45,18 @@ describe('Body Verification', () => { | |||
return testVerifyBody({}, expected, 400, 'test not specified.'); | |||
}); | |||
it('must error with an invalid type', () => { | |||
it('must error with an invalid primitive type', () => { | |||
const expected = [{name: 'test', type: 'string'}]; | |||
return testVerifyBody({test: [1, 2, 3]}, expected, 400, 'test malformed.'); | |||
}); | |||
it('must error with an invalid instance', () => { | |||
const expected = [{name: 'test', instance: Array}]; | |||
it('must error with an invalid date type', () => { | |||
const expected = [{name: 'test', type: 'date'}]; | |||
return testVerifyBody({test: '123abc'}, expected, 400, 'test malformed.'); | |||
}); | |||
it('must error with an invalid array type', () => { | |||
const expected = [{name: 'test', type: 'array'}]; | |||
return testVerifyBody({test: 'test'}, expected, 400, 'test malformed.'); | |||
}); | |||