Skip to content

Commit

Permalink
Feature request (issue #18). Add a required field to Schema declaration.
Browse files Browse the repository at this point in the history
  • Loading branch information
sebelga committed Oct 20, 2016
1 parent f672ed0 commit c6a9c02
Showing 2 changed files with 66 additions and 21 deletions.
61 changes: 41 additions & 20 deletions lib/model.js
Original file line number Diff line number Diff line change
@@ -754,11 +754,22 @@

validate(cb) {
let errors = {};
var self = this;
var schema = this.schema;
const self = this;
const schema = this.schema;

let skip;
let schemaHasProperty;
let propertyValue;
let isRequired;

Object.keys(this.entityData).forEach((k) => {
let skip = false;
skip = false;
schemaHasProperty = schema.paths.hasOwnProperty(k);
propertyValue = self.entityData[k];

if (typeof propertyValue === 'string') {
propertyValue = propertyValue.trim();
}

if (schema.virtuals.hasOwnProperty(k)) {
// Virtual, remove it and skip the rest
@@ -767,55 +778,54 @@
}

// Properties dict
if (!schema.paths.hasOwnProperty(k) && schema.options.explicitOnly === false) {
if (!schemaHasProperty && schema.options.explicitOnly === false) {
// No more validation, key does not exist but it is allowed
skip = true;
}

if (!skip && !schema.paths.hasOwnProperty(k)) {
if (!skip && !schemaHasProperty) {
errors.properties = new Error ('Property not allowed {' + k + '} for ' + this.entityKind + ' Entity');
}

// Properties type
if (!skip && schema.paths.hasOwnProperty(k) && self.entityData[k] !== null && schema.paths[k].hasOwnProperty('type')) {
if (!skip && schemaHasProperty && propertyValue !== null && schema.paths[k].hasOwnProperty('type')) {
var typeValid = true;
if (schema.paths[k].type === 'datetime') {
// Validate datetime "format"
let error = validateDateTime(self.entityData[k], k);
let error = validateDateTime(propertyValue, k);
if (error !== null) {
errors.datetime = error;
}
} else {
let value = self.entityData[k];
if (schema.paths[k].type === 'array') {
// Array
typeValid = is.array(value);
typeValid = is.array(propertyValue);
} else if (schema.paths[k].type === 'int') {
// Integer
let isIntInstance = value.constructor.name === 'Int';
let isIntInstance = propertyValue.constructor.name === 'Int';
if (isIntInstance) {
typeValid = !isNaN(parseInt(value.value));
typeValid = !isNaN(parseInt(propertyValue.value));
} else {
typeValid = isInt(value);
typeValid = isInt(propertyValue);
}
} else if (schema.paths[k].type === 'double') {
// Double
let isIntInstance = value.constructor.name === 'Double';
let isIntInstance = propertyValue.constructor.name === 'Double';
if (isIntInstance) {

typeValid = isFloat(parseFloat(value.value, 10)) || isInt(parseFloat(value.value, 10));
typeValid = isFloat(parseFloat(propertyValue.value, 10)) || isInt(parseFloat(propertyValue.value, 10));
} else {
typeValid = isFloat(value) || isInt(value);
typeValid = isFloat(propertyValue) || isInt(propertyValue);
}
} else if (schema.paths[k].type === 'buffer') {
// Double
typeValid = value instanceof Buffer;
typeValid = propertyValue instanceof Buffer;
} else if (schema.paths[k].type === 'geoPoint') {
// GeoPoint
typeValid = value.constructor.name === 'GeoPoint';
typeValid = propertyValue.constructor.name === 'GeoPoint';
} else {
// Other
typeValid = typeof value === schema.paths[k].type;
typeValid = typeof propertyValue === schema.paths[k].type;
}

if (!typeValid) {
@@ -827,7 +837,18 @@
}

// Value Validation
if (!skip && schema.paths.hasOwnProperty(k) && schema.paths[k].hasOwnProperty('validate') && self.entityData[k] && self.entityData[k] !== '' && self.entityData[k] !== null) {

// ...Required
isRequired = schemaHasProperty && schema.paths[k].hasOwnProperty('required') && schema.paths[k].required === true;

if (!skip && isRequired && !!propertyValue === false) {
errors[k] = new GstoreError.ValidatorError({
message: 'Property {' + k + '} is required'
});
}

// ...Wrong format
if (!skip && schemaHasProperty && schema.paths[k].hasOwnProperty('validate') && self.entityData[k] && self.entityData[k] !== '' && self.entityData[k] !== null) {
if (!validator[schema.paths[k].validate](self.entityData[k])) {
errors[k] = new GstoreError.ValidatorError({
message: 'Wrong format for property {' + k + '}'
@@ -836,7 +857,7 @@
}

// Preset values
if (!skip && schema.paths.hasOwnProperty(k) && schema.paths[k].hasOwnProperty('values') && self.entityData[k] !== '') {
if (!skip && schemaHasProperty && schema.paths[k].hasOwnProperty('values') && self.entityData[k] !== '') {
if (schema.paths[k].values.indexOf(self.entityData[k]) < 0) {
errors[k] = new Error('Value not allowed for ' + k + '. It must be in the range: ' + schema.paths[k].values);
}
26 changes: 25 additions & 1 deletion test/model-test.js
Original file line number Diff line number Diff line change
@@ -1609,6 +1609,30 @@ describe('Model', function() {
expect(valid.success).be.true;
});

it('required property', () => {
schema = new Schema({
name: {type: 'string'},
email: {type: 'string', required:true}
});

ModelInstance = Model.compile('Blog', schema, gstore);

let model = new ModelInstance({name:'John Snow'});
let model2 = new ModelInstance({name:'John Snow', email:''});
let model3 = new ModelInstance({name:'John Snow', email:' '});
let model4 = new ModelInstance({name:'John Snow', email: null});

let valid = model.validate();
let valid2 = model2.validate();
let valid3 = model3.validate();
let valid4 = model4.validate();

expect(valid.success).be.false;
expect(valid2.success).be.false;
expect(valid3.success).be.false;
expect(valid4.success).be.false;
});

it ('no type validation', () => {
let model = new ModelInstance({street:123});
let model2 = new ModelInstance({street:'123'});
@@ -1794,7 +1818,7 @@ describe('Model', function() {
expect(valid6.success).be.false;
});

it ('--> is URL ok', () => {
it ('--> is URL ok', () => {
let model = new ModelInstance({website:'http://google.com'});
let model2 = new ModelInstance({website:'google.com'});

0 comments on commit c6a9c02

Please sign in to comment.