From 198f593b200b979a91c2b81b39958a8daaf7ae67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20de=20Assis=20Gon=C3=A7alves?= Date: Fri, 25 Jan 2019 13:50:05 -0200 Subject: [PATCH 1/6] Added uuid validation to string type --- docs/validation.md | 5 +++++ src/validation/string.js | 1 + test/unit/validation/string.spec.js | 33 +++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/docs/validation.md b/docs/validation.md index 4536ddb..ad4b65d 100644 --- a/docs/validation.md +++ b/docs/validation.md @@ -62,9 +62,14 @@ Validations marked with __**__ accept a value or an [attribute reference](#attri - `lowerCase`: all characters must be lower cased - `upperCase`: all characters must be upper cased - `email`: is a valid email (default: `false`) +- `uuid`: is a valid uuid (default: `false`) ```javascript const User = attributes({ + id: { + type: String, + uuid: true + }, initials: { type: String, upperCase: true, diff --git a/src/validation/string.js b/src/validation/string.js index 1ba009f..e968a1d 100644 --- a/src/validation/string.js +++ b/src/validation/string.js @@ -12,6 +12,7 @@ module.exports = { ['lowerCase', 'lowercase'], ['upperCase', 'uppercase'], ['email', 'email'], + ['uuid', 'uuid'], ['required', 'required'] ], createJoiSchema(typeDescriptor) { diff --git a/test/unit/validation/string.spec.js b/test/unit/validation/string.spec.js index 5f29365..cae85e6 100644 --- a/test/unit/validation/string.spec.js +++ b/test/unit/validation/string.spec.js @@ -443,5 +443,38 @@ describe('validation', () => { }); }); }); + + describe('uuid', () => { + var User; + + beforeEach(() => { + User = attributes({ + id: { + type: String, + uuid: true + } + })(class User {}); + }); + + context('when value is a valid uuid', () => { + it('is valid', () => { + const user = new User({ + name: '759535af-3314-4ace-81b9-a519c29d0e17' + }); + + assertValid(user); + }); + }); + + context('when value is not a valid uuid', () => { + it('is not valid and has errors set', () => { + const user = new User({ + id: 'Not a valid uuid' + }); + + assertInvalid(user, 'id'); + }); + }); + }); }); }); From 8398237dd9a9fb28410c6867d1ce97c25e82d43b Mon Sep 17 00:00:00 2001 From: Talysson Date: Fri, 22 Feb 2019 15:37:14 -0300 Subject: [PATCH 2/6] Fix test --- test/unit/validation/string.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/validation/string.spec.js b/test/unit/validation/string.spec.js index cae85e6..d30abf1 100644 --- a/test/unit/validation/string.spec.js +++ b/test/unit/validation/string.spec.js @@ -459,7 +459,7 @@ describe('validation', () => { context('when value is a valid uuid', () => { it('is valid', () => { const user = new User({ - name: '759535af-3314-4ace-81b9-a519c29d0e17' + id: '759535af-3314-4ace-81b9-a519c29d0e17' }); assertValid(user); From 79269fecee29b1ca6545580298015674aaae0467 Mon Sep 17 00:00:00 2001 From: Talysson Date: Fri, 22 Feb 2019 15:38:58 -0300 Subject: [PATCH 3/6] Update new docs --- new-docs/validation/string-validations.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/new-docs/validation/string-validations.md b/new-docs/validation/string-validations.md index 1a6df12..db268e5 100644 --- a/new-docs/validation/string-validations.md +++ b/new-docs/validation/string-validations.md @@ -11,9 +11,14 @@ - `lowerCase`: all characters must be lower cased - `upperCase`: all characters must be upper cased - `email`: is a valid email (default: `false`) +- `uuid`: is a valid uuid (default: `false`) ```javascript const User = attributes({ + id: { + type: String, + uuid: true + }, initials: { type: String, upperCase: true, From 70d37cde683fc1f289aef75c3de6ce18390a175b Mon Sep 17 00:00:00 2001 From: Talysson Date: Fri, 22 Feb 2019 16:17:27 -0300 Subject: [PATCH 4/6] Rename option to guid --- docs/validation.md | 4 ++-- new-docs/validation/string-validations.md | 4 ++-- src/validation/string.js | 2 +- test/unit/validation/string.spec.js | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/validation.md b/docs/validation.md index ad4b65d..96fb0f5 100644 --- a/docs/validation.md +++ b/docs/validation.md @@ -62,13 +62,13 @@ Validations marked with __**__ accept a value or an [attribute reference](#attri - `lowerCase`: all characters must be lower cased - `upperCase`: all characters must be upper cased - `email`: is a valid email (default: `false`) -- `uuid`: is a valid uuid (default: `false`) +- `guid`: is a valid guid (default: `false`) ```javascript const User = attributes({ id: { type: String, - uuid: true + guid: true }, initials: { type: String, diff --git a/new-docs/validation/string-validations.md b/new-docs/validation/string-validations.md index db268e5..a8e41b6 100644 --- a/new-docs/validation/string-validations.md +++ b/new-docs/validation/string-validations.md @@ -11,13 +11,13 @@ - `lowerCase`: all characters must be lower cased - `upperCase`: all characters must be upper cased - `email`: is a valid email (default: `false`) -- `uuid`: is a valid uuid (default: `false`) +- `guid`: is a valid guid (default: `false`) ```javascript const User = attributes({ id: { type: String, - uuid: true + guid: true }, initials: { type: String, diff --git a/src/validation/string.js b/src/validation/string.js index e968a1d..ebd8f58 100644 --- a/src/validation/string.js +++ b/src/validation/string.js @@ -12,7 +12,7 @@ module.exports = { ['lowerCase', 'lowercase'], ['upperCase', 'uppercase'], ['email', 'email'], - ['uuid', 'uuid'], + ['guid', 'guid'], ['required', 'required'] ], createJoiSchema(typeDescriptor) { diff --git a/test/unit/validation/string.spec.js b/test/unit/validation/string.spec.js index d30abf1..6ed5da0 100644 --- a/test/unit/validation/string.spec.js +++ b/test/unit/validation/string.spec.js @@ -444,19 +444,19 @@ describe('validation', () => { }); }); - describe('uuid', () => { + describe('guid', () => { var User; beforeEach(() => { User = attributes({ id: { type: String, - uuid: true + guid: true } })(class User {}); }); - context('when value is a valid uuid', () => { + context('when value is a valid guid', () => { it('is valid', () => { const user = new User({ id: '759535af-3314-4ace-81b9-a519c29d0e17' @@ -466,10 +466,10 @@ describe('validation', () => { }); }); - context('when value is not a valid uuid', () => { + context('when value is not a valid guid', () => { it('is not valid and has errors set', () => { const user = new User({ - id: 'Not a valid uuid' + id: 'Not a valid guid' }); assertInvalid(user, 'id'); From e473f6e137702e128dd190f55c6674df9794083d Mon Sep 17 00:00:00 2001 From: Talysson Date: Fri, 22 Feb 2019 16:44:50 -0300 Subject: [PATCH 5/6] Accept options to validate specific guid versions --- docs/validation.md | 2 +- new-docs/validation/string-validations.md | 2 +- src/validation/string.js | 3 +- src/validation/utils.js | 18 +++--- test/unit/validation/string.spec.js | 79 +++++++++++++++++------ 5 files changed, 74 insertions(+), 30 deletions(-) diff --git a/docs/validation.md b/docs/validation.md index 96fb0f5..0598585 100644 --- a/docs/validation.md +++ b/docs/validation.md @@ -62,7 +62,7 @@ Validations marked with __**__ accept a value or an [attribute reference](#attri - `lowerCase`: all characters must be lower cased - `upperCase`: all characters must be upper cased - `email`: is a valid email (default: `false`) -- `guid`: is a valid guid (default: `false`) +- `guid`: is a valid guid. You can pass a boolean or the [options object accepted by Joi](https://github.com/hapijs/joi/blob/v10.2.0/API.md#stringguid---aliases-uuid) (default: `false`) ```javascript const User = attributes({ diff --git a/new-docs/validation/string-validations.md b/new-docs/validation/string-validations.md index a8e41b6..6a24877 100644 --- a/new-docs/validation/string-validations.md +++ b/new-docs/validation/string-validations.md @@ -11,7 +11,7 @@ - `lowerCase`: all characters must be lower cased - `upperCase`: all characters must be upper cased - `email`: is a valid email (default: `false`) -- `guid`: is a valid guid (default: `false`) +- `guid`: is a valid guid. You can pass a boolean or the [options object accepted by Joi](https://github.com/hapijs/joi/blob/v10.2.0/API.md#stringguid---aliases-uuid) (default: `false`) ```javascript const User = attributes({ diff --git a/src/validation/string.js b/src/validation/string.js index ebd8f58..df8c41b 100644 --- a/src/validation/string.js +++ b/src/validation/string.js @@ -1,4 +1,5 @@ const joi = require('joi'); +const { isPlainObject } = require('lodash'); const { mapToJoi, equalOption } = require('./utils'); module.exports = { @@ -12,7 +13,7 @@ module.exports = { ['lowerCase', 'lowercase'], ['upperCase', 'uppercase'], ['email', 'email'], - ['guid', 'guid'], + ['guid', 'guid', isPlainObject], ['required', 'required'] ], createJoiSchema(typeDescriptor) { diff --git a/src/validation/utils.js b/src/validation/utils.js index 5aff74a..e981a91 100644 --- a/src/validation/utils.js +++ b/src/validation/utils.js @@ -1,14 +1,16 @@ const joi = require('joi'); -const { isPlainObject } = require('lodash'); +const { isPlainObject, isFunction } = require('lodash'); exports.mapToJoi = function mapToJoi(typeDescriptor, { initial, mappings }) { return mappings.reduce((joiSchema, [optionName, joiMethod, passValueToJoi]) => { - if(typeDescriptor[optionName] === undefined) { + const attributeDescriptor = typeDescriptor[optionName]; + + if(attributeDescriptor === undefined) { return joiSchema; } - if(passValueToJoi) { - return joiSchema[joiMethod](typeDescriptor[optionName]); + if(passValueToJoi && (!isFunction(passValueToJoi) || passValueToJoi(attributeDescriptor))) { + return joiSchema[joiMethod](attributeDescriptor); } return joiSchema[joiMethod](); @@ -25,15 +27,15 @@ function mapValueOrReference(valueOrReference) { exports.mapToJoiWithReference = function mapToJoiWithReference(typeDescriptor, { initial, mappings }) { return mappings.reduce((joiSchema, [optionName, joiMethod]) => { - var optionValue = typeDescriptor[optionName]; + var attributeDescriptor = typeDescriptor[optionName]; - if(optionValue === undefined) { + if(attributeDescriptor === undefined) { return joiSchema; } - optionValue = mapValueOrReference(optionValue); + attributeDescriptor = mapValueOrReference(attributeDescriptor); - return joiSchema[joiMethod](optionValue); + return joiSchema[joiMethod](attributeDescriptor); }, initial); }; diff --git a/test/unit/validation/string.spec.js b/test/unit/validation/string.spec.js index 6ed5da0..d7a83f9 100644 --- a/test/unit/validation/string.spec.js +++ b/test/unit/validation/string.spec.js @@ -445,34 +445,75 @@ describe('validation', () => { }); describe('guid', () => { - var User; + context('when validating as a generic guid', () => { + var User; - beforeEach(() => { - User = attributes({ - id: { - type: String, - guid: true - } - })(class User {}); - }); + beforeEach(() => { + User = attributes({ + id: { + type: String, + guid: true + } + })(class User {}); + }); - context('when value is a valid guid', () => { - it('is valid', () => { - const user = new User({ - id: '759535af-3314-4ace-81b9-a519c29d0e17' + context('when value is a valid guid', () => { + it('is valid', () => { + const user = new User({ + id: '759535af-3314-4ace-81b9-a519c29d0e17' + }); + + assertValid(user); }); + }); - assertValid(user); + context('when value is not a valid guid', () => { + it('is not valid and has errors set', () => { + const user = new User({ + id: 'Not a valid guid' + }); + + assertInvalid(user, 'id'); + }); }); }); - context('when value is not a valid guid', () => { - it('is not valid and has errors set', () => { - const user = new User({ - id: 'Not a valid guid' + context('when validating a specific guid version', () => { + var User; + + beforeEach(() => { + User = attributes({ + id: { + type: String, + guid: { + version: ['uuidv4'] + } + } + })(class User {}); + }); + + context('when value is a valid guid', () => { + it('is valid', () => { + const uuidv4 = 'f35e1cf1-4ac9-4fbb-9c06-151dc8ff9107'; + + const user = new User({ + id: uuidv4 + }); + + assertValid(user); }); + }); - assertInvalid(user, 'id'); + context('when value is not a valid guid', () => { + it('is not valid and has errors set', () => { + const uuidv1 = 'c130564e-36d9-11e9-b210-d663bd873d93'; + + const user = new User({ + id: uuidv1 + }); + + assertInvalid(user, 'id'); + }); }); }); }); From baeafac8da510f3c00f842e26f542ea9262ef9f2 Mon Sep 17 00:00:00 2001 From: Talysson Date: Fri, 22 Feb 2019 16:59:40 -0300 Subject: [PATCH 6/6] Make linter happy --- src/validation/utils.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/validation/utils.js b/src/validation/utils.js index e981a91..589e917 100644 --- a/src/validation/utils.js +++ b/src/validation/utils.js @@ -9,7 +9,7 @@ exports.mapToJoi = function mapToJoi(typeDescriptor, { initial, mappings }) { return joiSchema; } - if(passValueToJoi && (!isFunction(passValueToJoi) || passValueToJoi(attributeDescriptor))) { + if(shouldPassValueToJoi(passValueToJoi, attributeDescriptor)) { return joiSchema[joiMethod](attributeDescriptor); } @@ -17,6 +17,10 @@ exports.mapToJoi = function mapToJoi(typeDescriptor, { initial, mappings }) { }, initial); }; +function shouldPassValueToJoi(passValueToJoi, attributeDescriptor) { + return passValueToJoi && (!isFunction(passValueToJoi) || passValueToJoi(attributeDescriptor)); +} + function mapValueOrReference(valueOrReference) { if(isPlainObject(valueOrReference)) { return joi.ref(valueOrReference.attr);