@springworks/input-validator
Advanced tools
Comparing version 3.1.3 to 4.0.0
104
index.js
'use strict'; | ||
var util = require('util'); | ||
var joi = require('joi'); | ||
var ErrorFactory = require('@springworks/error-factory'); | ||
var OBJECTID_REGEX = /^[0-9a-fA-F]{24}$/; | ||
var defaults = require('lodash.defaults'); | ||
const joi = require('joi'); | ||
const createError = require('@springworks/error-factory').createError; | ||
const defaults = require('lodash.defaults'); | ||
const OBJECTID_REGEX = /^[0-9a-fA-F]{24}$/; | ||
exports.joi = joi; | ||
exports.OBJECTID_REGEX = OBJECTID_REGEX; | ||
exports.objectId = function() { | ||
return joi.string().regex(OBJECTID_REGEX).options({ | ||
language: { | ||
string: { | ||
regex: 'must be a valid ObjectId' | ||
} | ||
} | ||
}); | ||
return joi.string().regex(OBJECTID_REGEX); | ||
}; | ||
exports.filterParams = filterParams; | ||
exports.validateSchema = validateSchema; | ||
@@ -30,75 +22,2 @@ | ||
/** | ||
* Ensures a `params` object only has the `allowed` parameters. | ||
* | ||
* @param {Object} params Object to filter. | ||
* @param {Array} allowed Array of allowed keys in params object. | ||
* @return {Object} Params filtered to only the ones allowed. | ||
*/ | ||
function filterParams(params, allowed) { | ||
var filtered = {}; | ||
// Ensure input params are provided | ||
if (!params) { | ||
return filtered; | ||
} | ||
// Compile object with all valid parameters | ||
allowed.forEach(function(param) { | ||
if (Object.prototype.hasOwnProperty.call(params, param)) { | ||
filtered[param] = params[param]; | ||
} | ||
}); | ||
return filtered; | ||
} | ||
/** | ||
* Checks if any of the required params are missing. | ||
* | ||
* @throws Error if provided params are invalid. | ||
* @param {Object} params Object to scan. | ||
* @param {Array} required Keys that are required to exist in `params`. | ||
* @return {Boolean} true if any key is missing in `params`. | ||
*/ | ||
function isMissingParams(params, required) { | ||
return missingParams(params, required).length > 0; | ||
} | ||
/** | ||
* Checks if any of the required params are missing. Returns any missing params | ||
* in an array. | ||
* | ||
* @throws Error if provided params are invalid. | ||
* @param {Object} params Object to scan. | ||
* @param {Array} required Keys that are required to exist in `params`. | ||
* @return {Array} any missing params. | ||
*/ | ||
function missingParams(params, required) { | ||
var i; | ||
var param; | ||
var missing = []; | ||
if (!params) { | ||
throw new Error('Missing `params` argument'); | ||
} | ||
if (!required) { | ||
// Handle missing required params as if no params are missing | ||
return []; | ||
} | ||
for (i = 0; i < required.length; i++) { | ||
param = required[i]; | ||
if (!Object.prototype.hasOwnProperty.call(params, param)) { | ||
missing.push(param); | ||
} | ||
} | ||
return missing; | ||
} | ||
/** | ||
* validates given parameters based on schema. | ||
@@ -114,3 +33,3 @@ * | ||
function validateSchema(params, schema, opt_resource_name, opt_options) { | ||
var default_options = { | ||
const default_options = { | ||
abortEarly: false, | ||
@@ -121,6 +40,7 @@ stripUnknown: false, | ||
}; | ||
var validated = joi.validate(params, schema, defaults({}, opt_options, default_options)); | ||
const options = opt_options ? defaults({}, opt_options, default_options) : default_options; | ||
const validated = joi.validate(params, schema, options); | ||
if (validated.error) { | ||
throw ErrorFactory.validationError().appendJoiValidationError(opt_resource_name || 'unspecified_resource', validated.error); | ||
throw createError({ message: 'Validation Failed', cause: validated.error }); | ||
} | ||
@@ -132,3 +52,3 @@ | ||
exports.isMissingParams = util.deprecate(isMissingParams, 'isMissingParams: Use validateSchema instead.'); | ||
exports.missingParams = util.deprecate(missingParams, 'missingParams: Use validateSchema instead.'); | ||
// Define __esModule for use with `import` | ||
Object.defineProperty(exports, '__esModule', { value: true }); |
{ | ||
"name": "@springworks/input-validator", | ||
"version": "3.1.3", | ||
"description": "Module to help validate and filter input parameters.", | ||
"version": "4.0.0", | ||
"description": "Module to help validate input parameters.", | ||
"main": "index.js", | ||
@@ -16,5 +16,3 @@ "scripts": { | ||
"keywords": [ | ||
"validation", | ||
"filtering", | ||
"input" | ||
"validation" | ||
], | ||
@@ -27,2 +25,3 @@ "author": "Springworks", | ||
"engines": { | ||
"node": ">=4", | ||
"npm": ">=2.7.0" | ||
@@ -32,14 +31,16 @@ }, | ||
"@springworks/test-harness": "1.0.3", | ||
"coveralls": "2.11.4", | ||
"eslint": "1.7.3", | ||
"eslint-config-springworks": "3.2.0", | ||
"eslint-plugin-mocha": "1.0.0", | ||
"istanbul": "0.4.0", | ||
"mocha": "2.3.3" | ||
"coveralls": "2.11.6", | ||
"eslint": "1.10.3", | ||
"eslint-config-springworks": "5.0.0", | ||
"eslint-plugin-import": "0.12.1", | ||
"eslint-plugin-mocha": "1.1.0", | ||
"eslint-plugin-springworks": "1.1.1", | ||
"istanbul": "0.4.1", | ||
"mocha": "2.3.4" | ||
}, | ||
"dependencies": { | ||
"@springworks/error-factory": "1.2.3", | ||
"joi": "6.10.0", | ||
"@springworks/error-factory": "2.0.2", | ||
"joi": "7.0.1", | ||
"lodash.defaults": "^3.1.2" | ||
} | ||
} |
'use strict'; | ||
var validator = require('..'); | ||
var joi = validator.joi; | ||
const validator = require('..'); | ||
const joi = validator.joi; | ||
describe(__filename, function() { | ||
describe('test/input-validator-test.js', () => { | ||
describe('Filtering params', function() { | ||
describe('validateSchema', () => { | ||
it('should return complete object with no disallowed params', function() { | ||
Object.keys(validator.filterParams({ | ||
foo: 'foo', | ||
bar: 'bar' | ||
}, ['foo', 'bar'])).should.have.length(2); | ||
}); | ||
it('should remove disallowed params', function() { | ||
Object.keys(validator.filterParams({ | ||
foo: 'foo', | ||
bar: 'bar', | ||
baz: 'baz' | ||
}, ['foo', 'bar'])).should.have.length(2); | ||
}); | ||
it('should return empty object with undefined params', function() { | ||
Object.keys(validator.filterParams(undefined, ['foo', 'bar'])).should.have.length(0); | ||
}); | ||
it('should remove prototype properties (length in this case).', function() { | ||
var Ref = String; | ||
var actual = new Ref(); | ||
actual.foo = 'bar'; | ||
Object.keys(validator.filterParams(actual, ['foo', 'bar'])).should.have.length(1); | ||
}); | ||
}); | ||
describe('Requiring params', function() { | ||
it('should return true if all params exist', function() { | ||
validator.isMissingParams({ | ||
foo: 'foo', | ||
bar: 'bar' | ||
}, ['foo', 'bar']).should.eql(false); | ||
}); | ||
it('should return false if required params are missing', function() { | ||
validator.isMissingParams({ | ||
foo: 'foo' | ||
}, ['foo', 'bar']).should.eql(true); | ||
}); | ||
it('should throw if required params argument is missing', function() { | ||
(function() { | ||
validator.isMissingParams(); | ||
}).should.throw(); | ||
}); | ||
it('should return false if required params is missing', function() { | ||
validator.isMissingParams({ foo: 'foo' }).should.eql(false); | ||
}); | ||
it('should return a list of missing params', function() { | ||
var missing = validator.missingParams({ foo: 'f' }, ['foo', 'bar']); | ||
var first = missing[0]; | ||
(Array.isArray(missing)).should.eql(true); | ||
missing.should.have.length(1); | ||
first.should.eql('bar'); | ||
}); | ||
}); | ||
describe('Joi integration', function() { | ||
var schema = joi.object().required().keys({ | ||
const schema = joi.object().required().keys({ | ||
string_val: joi.string().required(), | ||
number_val: joi.number().optional(), | ||
date_val: joi.date().optional(), | ||
object_id: validator.objectId().optional() | ||
object_id: validator.objectId().optional(), | ||
}); | ||
it('should validate based on Joi Schema', function() { | ||
(function() { | ||
var validated = validator.validateSchema({ | ||
string_val: 'foo', | ||
number_val: 1 | ||
}, schema, 'resource'); | ||
validated.should.have.keys(['string_val', 'number_val']); | ||
}).should.not.throw(); | ||
it('should validate with a joi schema', () => { | ||
const validated = validator.validateSchema({ | ||
string_val: 'foo', | ||
number_val: 1, | ||
}, schema); | ||
validated.should.have.keys(['string_val', 'number_val']); | ||
}); | ||
it('should cast values based on schema', function() { | ||
var d = new Date(); | ||
var validated = validator.validateSchema({ | ||
it('should cast values based on schema', () => { | ||
const d = new Date(); | ||
const validated = validator.validateSchema({ | ||
string_val: 'foo', | ||
number_val: '1', | ||
date_val: d.toISOString() | ||
}, schema, 'resource'); | ||
date_val: d.toISOString(), | ||
}, schema); | ||
validated.number_val.should.equal(1); | ||
@@ -104,136 +36,108 @@ validated.date_val.toISOString().should.equal(d.toISOString()); | ||
it('should handle object ids (mongoDB)', function() { | ||
(function() { | ||
var validated = validator.validateSchema({ | ||
string_val: 'foo', | ||
object_id: '53fbf4615c3b9f41c381b6a3' | ||
}, schema, 'resource'); | ||
validated.should.have.keys(['string_val', 'object_id']); | ||
}).should.not.throw(); | ||
it('should validate ObjectId strings', () => { | ||
const validated = validator.validateSchema({ | ||
string_val: 'foo', | ||
object_id: '53fbf4615c3b9f41c381b6a3', | ||
}, schema); | ||
validated.should.have.keys(['string_val', 'object_id']); | ||
}); | ||
it('should throw if passed unknown parameters', function() { | ||
it('should describe why an object id is invalid', () => { | ||
let error; | ||
try { | ||
validator.validateSchema({ | ||
string_val: 'foo', | ||
number_val: 1, | ||
extra_key: 'bar' | ||
}, schema, 'resource'); | ||
validator.validateSchema({ string_val: 'foo', object_id: 'x' }, schema); | ||
} | ||
catch (err) { | ||
err.should.have.property('statusCode', 422); | ||
err.output.payload.validation.should.have.keys([ | ||
'extra_key' | ||
]); | ||
err.toJSON().should.eql({ | ||
message: 'Validation Failed', | ||
errors: [ | ||
{ | ||
resource: 'resource', | ||
field: 'extra_key', | ||
code: 'invalid' | ||
} | ||
] | ||
}); | ||
return; | ||
error = err; | ||
} | ||
throw new Error('Should have thrown'); | ||
error.should.match({ | ||
output: { | ||
payload: { | ||
details: [ | ||
{ message: '"object_id" with value "x" fails to match the required pattern: /^[0-9a-fA-F]{24}$/' }, | ||
], | ||
}, | ||
}, | ||
}); | ||
}); | ||
it('should throw error when invalid parameters are given', function() { | ||
it('should throw an error with code 422', () => { | ||
let error; | ||
try { | ||
validator.validateSchema({}, schema); | ||
} | ||
catch (err) { | ||
error = err; | ||
} | ||
error.code.should.eql(422); | ||
}); | ||
it('should throw if passed unknown parameters', () => { | ||
let error; | ||
try { | ||
validator.validateSchema({ | ||
string_val: 'foo', | ||
number_val: 'fubar', | ||
date_val: 'fubar_date', | ||
object_id: 'invalid_object_id' | ||
}, schema, 'resource'); | ||
number_val: 1, | ||
extra_key: 'bar', | ||
}, schema); | ||
} | ||
catch (err) { | ||
err.should.have.property('statusCode', 422); | ||
// Check that all the fields are present in the boom error. | ||
err.output.payload.validation.should.have.keys([ | ||
'number_val', 'date_val', 'object_id' | ||
]); | ||
err.toJSON().should.eql({ | ||
message: 'Validation Failed', | ||
errors: [ | ||
{ code: 'invalid', field: 'number_val', resource: 'resource' }, | ||
{ code: 'invalid', field: 'date_val', resource: 'resource' }, | ||
{ code: 'invalid', field: 'object_id', resource: 'resource' } | ||
] | ||
}); | ||
return; | ||
error = err; | ||
} | ||
throw new Error('Should have thrown'); | ||
error.should.match({ | ||
output: { | ||
payload: { | ||
details: [ | ||
{ message: '"extra_key" is not allowed' }, | ||
], | ||
}, | ||
}, | ||
}); | ||
}); | ||
it('should throw error when required parameter is missing', function() { | ||
it('should throw error when invalid parameters are given', () => { | ||
let error; | ||
try { | ||
validator.validateSchema({ | ||
number_val: 1 | ||
}, schema, 'resource'); | ||
string_val: 'foo', | ||
number_val: 'fubar', | ||
date_val: 'fubar_date', | ||
object_id: 'invalid_object_id', | ||
}, schema); | ||
} | ||
catch (err) { | ||
err.should.have.property('statusCode', 422); | ||
// Check that the restify part is present. | ||
err.toJSON().should.eql({ | ||
message: 'Validation Failed', | ||
errors: [ | ||
{ | ||
resource: 'resource', | ||
field: 'string_val', | ||
code: 'missing_field' | ||
} | ||
] | ||
}); | ||
// Old error format (For Restify) | ||
err.should.have.property('statusCode', 422); | ||
err.should.have.property('code', 422); | ||
err.should.have.property('message', 'Validation Failed'); | ||
err.should.have.property('json'); | ||
err.should.have.property('body'); | ||
// Added boom properties | ||
err.should.have.property('data'); | ||
err.should.have.property('isBoom', true); | ||
err.should.have.property('reformat'); | ||
// Boom output | ||
err.output.should.have.property('statusCode', 422); | ||
err.output.should.have.property('payload'); | ||
err.output.payload.should.have.property('statusCode', 422); | ||
err.output.payload.should.have.property('message', 'Validation Failed'); | ||
err.output.payload.should.have.property('error', 'Unprocessable Entity'); | ||
err.output.payload.should.have.property('resource', 'resource'); | ||
return; | ||
error = err; | ||
} | ||
throw new Error('Should have thrown'); | ||
error.should.match({ | ||
output: { | ||
payload: { | ||
details: [ | ||
{ message: '"number_val" must be a number' }, | ||
{ message: '"date_val" must be a number of milliseconds or valid date string' }, | ||
{ message: '"object_id" with value "invalid_object_id" fails to match the required pattern: /^[0-9a-fA-F]{24}$/' }, | ||
], | ||
}, | ||
}, | ||
}); | ||
}); | ||
it('should default resource', function() { | ||
it('should throw error when required parameter is missing', () => { | ||
let error; | ||
try { | ||
validator.validateSchema({ | ||
number_val: 1 | ||
number_val: 1, | ||
}, schema); | ||
} | ||
catch (err) { | ||
err.toJSON().should.eql({ | ||
message: 'Validation Failed', | ||
errors: [ | ||
{ | ||
resource: 'unspecified_resource', | ||
field: 'string_val', | ||
code: 'missing_field' | ||
} | ||
] | ||
}); | ||
return; | ||
error = err; | ||
} | ||
throw new Error('Should have thrown'); | ||
error.should.match({ | ||
output: { | ||
payload: { | ||
details: [ | ||
{ message: '"string_val" is required' }, | ||
], | ||
}, | ||
}, | ||
}); | ||
}); | ||
@@ -240,0 +144,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
10884
9
11
168
1
+ Added@springworks/error-factory@2.0.2(transitive)
+ Addedboom@3.0.0(transitive)
+ Addedfel@1.1.1(transitive)
+ Addedhoek@3.0.44.3.1(transitive)
+ Addedisemail@2.2.1(transitive)
+ Addedjoi@7.0.1(transitive)
+ Addedtopo@2.1.1(transitive)
- Removed@springworks/error-factory@1.2.3(transitive)
- Removedboom@2.10.1(transitive)
- Removedhoek@2.16.3(transitive)
- Removedisemail@1.2.0(transitive)
- Removedjoi@6.10.0(transitive)
- Removedtopo@1.1.0(transitive)
Updatedjoi@7.0.1