From fbd684926eecaa349ad4a7c2790cc391ee98281b Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 30 Jul 2015 18:28:41 -0700 Subject: [PATCH] Config - Support additionalProperties field of object schemas --- spec/config-spec.coffee | 41 +++++++++++++++++++++++++++++++++++++++++ src/config.coffee | 20 +++++++++++++++++--- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/spec/config-spec.coffee b/spec/config-spec.coffee index cd6e3651d..1821b7e01 100644 --- a/spec/config-spec.coffee +++ b/spec/config-spec.coffee @@ -1429,6 +1429,47 @@ describe "Config", -> expect(atom.config.get('foo.bar.anInt')).toEqual 12 expect(atom.config.get('foo.bar.nestedObject.nestedBool')).toEqual true + describe "when the value has additionalProperties set to false", -> + it 'does not allow other properties to be set on the object', -> + atom.config.setSchema('foo.bar', + type: 'object' + properties: + anInt: + type: 'integer' + default: 12 + additionalProperties: false + ) + + expect(atom.config.set('foo.bar', {anInt: 5, somethingElse: 'ok'})).toBe true + expect(atom.config.get('foo.bar.anInt')).toBe 5 + expect(atom.config.get('foo.bar.somethingElse')).toBeUndefined() + + expect(atom.config.set('foo.bar.somethingElse', {anInt: 5})).toBe false + expect(atom.config.get('foo.bar.somethingElse')).toBeUndefined() + + describe 'when the value has an additionalProperties schema', -> + it 'validates properties of the object against that schema', -> + atom.config.setSchema('foo.bar', + type: 'object' + properties: + anInt: + type: 'integer' + default: 12 + additionalProperties: + type: 'string' + ) + + expect(atom.config.set('foo.bar', {anInt: 5, somethingElse: 'ok'})).toBe true + expect(atom.config.get('foo.bar.anInt')).toBe 5 + expect(atom.config.get('foo.bar.somethingElse')).toBe 'ok' + + expect(atom.config.set('foo.bar.somethingElse', 7)).toBe false + expect(atom.config.get('foo.bar.somethingElse')).toBe 'ok' + + expect(atom.config.set('foo.bar', {anInt: 6, somethingElse: 7})).toBe true + expect(atom.config.get('foo.bar.anInt')).toBe 6 + expect(atom.config.get('foo.bar.somethingElse')).toBe undefined + describe 'when the value has an "array" type', -> beforeEach -> schema = diff --git a/src/config.coffee b/src/config.coffee index c3983fcbe..f26599a0b 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -673,7 +673,12 @@ class Config if schema.type is 'object' childSchema = schema.properties?[key] unless childSchema? - return null + if isPlainObject(schema.additionalProperties) + childSchema = schema.additionalProperties + else if schema.additionalProperties is false + return false + else + return null else return false schema = childSchema @@ -1085,17 +1090,26 @@ Config.addSchemaEnforcers throw new Error("Validation failed at #{keyPath}, #{JSON.stringify(value)} must be an object") unless isPlainObject(value) return value unless schema.properties? + defaultChildSchema = null + allowsAdditionalProperties = true + if isPlainObject(schema.additionalProperties) + defaultChildSchema = schema.additionalProperties + if schema.additionalProperties is false + allowsAdditionalProperties = false + newValue = {} for prop, propValue of value - childSchema = schema.properties[prop] + childSchema = schema.properties[prop] ? defaultChildSchema if childSchema? try newValue[prop] = @executeSchemaEnforcers("#{keyPath}.#{prop}", propValue, childSchema) catch error console.warn "Error setting item in object: #{error.message}" - else + else if allowsAdditionalProperties # Just pass through un-schema'd values newValue[prop] = propValue + else + console.warn "Illegal object key: #{keyPath}.#{prop}" newValue