From 8c15e14ef1bab27d0337ff46a6f21c7e8abf041a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sat, 19 Jan 2019 23:44:22 -0200 Subject: [PATCH 1/6] External resources: JSON Schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- ext/spec_0_2.json | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 ext/spec_0_2.json diff --git a/ext/spec_0_2.json b/ext/spec_0_2.json new file mode 100644 index 0000000..aa892a1 --- /dev/null +++ b/ext/spec_0_2.json @@ -0,0 +1,74 @@ +{ + "$ref": "#/definitions/event", + "definitions": { + "specversion": { + "type": "string", + "minLength": 1, + "const": "0.2" + }, + "contenttype": { + "type": "string" + }, + "data": { + "type": [ + "object", + "string" + ] + }, + "event": { + "properties": { + "specversion": { + "$ref": "#/definitions/specversion" + }, + "contenttype": { + "$ref": "#/definitions/contenttype" + }, + "data": { + "$ref": "#/definitions/data" + }, + "id": { + "$ref": "#/definitions/id" + }, + "time": { + "$ref": "#/definitions/time" + }, + "type": { + "$ref": "#/definitions/type" + }, + "extensions": { + "$ref": "#/definitions/extensions" + }, + "source": { + "$ref": "#/definitions/source" + } + }, + "required": [ + "specversion", + "id", + "type", + "source" + ], + "type": "object" + }, + "id": { + "type": "string", + "minLength": 1 + }, + "time": { + "format": "date-time", + "type": "string" + }, + "type": { + "type": "string", + "minLength": 1 + }, + "extensions": { + "type": "object" + }, + "source": { + "format": "uri-reference", + "type": "string" + } + }, + "type": "object" +} From 6f066de09184d664e591a7883ba425ddba251b40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sat, 19 Jan 2019 23:45:27 -0200 Subject: [PATCH 2/6] Ignore .swp vim files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 8c8b239..deb216d 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,6 @@ typings/ # FuseBox cache .fusebox/ +# Vim +*.swp + From 2bd26d6b8fd4221b899e5f00da4858d9519a2baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sat, 19 Jan 2019 23:45:58 -0200 Subject: [PATCH 3/6] Employ JSON Schema to validate payloads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/specs/spec_0_2.js | 26 ++++++++++++-------------- package.json | 1 + test/cloudevent_spec_0_2.js | 14 +++++++++++--- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/lib/specs/spec_0_2.js b/lib/specs/spec_0_2.js index 9f790fc..3467a45 100644 --- a/lib/specs/spec_0_2.js +++ b/lib/specs/spec_0_2.js @@ -1,5 +1,13 @@ var uuid = require("uuid/v4"); var empty = require("is-empty"); +var Ajv = require("ajv"); + +const schema = require("../../ext/spec_0_2.json"); + +// Default options +const ajv = new Ajv(); + +const validate = ajv.compile(schema); function Spec02(){ this.payload = { @@ -13,22 +21,12 @@ function Spec02(){ */ Spec02.prototype.check = function(){ - if(empty(this.payload["type"])) { - throw {message: "'type' is invalid"}; + var valid = validate(this.payload); + + if(!valid) { + throw {message: "invalid payload"}; } - if(empty(this.payload["specversion"])) { - throw {message: "'specversion' is invalid"}; - } - - if(this.payload["specversion"] !== "0.2") { - throw {message: "'specversion' value is invalid: '" - + this.payload["specversion"] + "'"}; - } - - if(empty(this.payload["id"])) { - throw {message: "'id' is invalid"}; - } }; Spec02.prototype.type = function(_type){ diff --git a/package.json b/package.json index 7b96490..d746d37 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ }, "homepage": "https://github.com/cloudevents/sdk-javascript#readme", "dependencies": { + "ajv": "^6.7.0", "axios": "0.18.0", "is-empty": "1.2.0", "uri-js": "4.2.2", diff --git a/test/cloudevent_spec_0_2.js b/test/cloudevent_spec_0_2.js index af751d9..e8fa997 100644 --- a/test/cloudevent_spec_0_2.js +++ b/test/cloudevent_spec_0_2.js @@ -73,7 +73,7 @@ describe("CloudEvents Spec 0.2 - JavaScript SDK", () => { cloudevent.type(""); expect(cloudevent.format.bind(cloudevent)) .to - .throw("'type' is invalid"); + .throw("invalid payload"); }); it("must be a non-empty string", () => { @@ -95,7 +95,15 @@ describe("CloudEvents Spec 0.2 - JavaScript SDK", () => { cloudevent.spec.payload.specversion = ""; expect(cloudevent.format.bind(cloudevent)) .to - .throw("'specversion' is invalid"); + .throw("invalid payload"); + cloudevent.spec.payload.specversion = "0.2"; + }); + + it("should throw an error when the value is not '0.2'", () => { + cloudevent.spec.payload.specversion = "0.4"; + expect(cloudevent.format.bind(cloudevent)) + .to + .throw("invalid payload"); cloudevent.spec.payload.specversion = "0.2"; }); }); @@ -105,7 +113,7 @@ describe("CloudEvents Spec 0.2 - JavaScript SDK", () => { cloudevent.id(""); expect(cloudevent.format.bind(cloudevent)) .to - .throw("'id' is invalid"); + .throw("invalid payload"); }); it("must be a non-empty string", () => { cloudevent.id("my.id-0x0090"); From b1c32064c0c1386f01df728850102cf0106db3f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 20 Jan 2019 21:08:46 -0200 Subject: [PATCH 4/6] Fix for-in issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/binary_0_2.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/bindings/http/binary_0_2.js b/lib/bindings/http/binary_0_2.js index 58e39cb..c398a0b 100644 --- a/lib/bindings/http/binary_0_2.js +++ b/lib/bindings/http/binary_0_2.js @@ -36,7 +36,9 @@ HTTPBinary.prototype.emit = function(cloudevent){ // Have extensions? var exts = cloudevent.getExtensions(); for(var ext in exts){ - _headers["ce-" + ext] = exts[ext]; + if({}.hasOwnProperty.call(exts, ext)){ + _headers["ce-" + ext] = exts[ext]; + } } // Return the Promise From d25cfc352ac2b29d9a2a984570ae0dc48ddee49f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 20 Jan 2019 21:39:46 -0200 Subject: [PATCH 5/6] Fix object injection issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/specs/spec_0_2.js | 18 +++++++++++++++++- test/cloudevent_spec_0_2.js | 18 +++++++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/lib/specs/spec_0_2.js b/lib/specs/spec_0_2.js index 3467a45..958dd6f 100644 --- a/lib/specs/spec_0_2.js +++ b/lib/specs/spec_0_2.js @@ -2,6 +2,18 @@ var uuid = require("uuid/v4"); var empty = require("is-empty"); var Ajv = require("ajv"); +// Reserved attributes names +const reserved = { + type: "type", + specversion: "specversion", + source: "source", + id: "id", + time: "time", + schemaurl: "schemaurl", + contenttype: "contenttype", + data: "data" +}; + const schema = require("../../ext/spec_0_2.json"); // Default options @@ -93,7 +105,11 @@ Spec02.prototype.getData = function() { }; Spec02.prototype.addExtension = function(key, value){ - this.payload[key] = value; + if(!reserved.hasOwnProperty(key)){ + this.payload[key] = value; + } else { + throw {message: "Reserved attribute name: '" + key + "'"}; + } return this; }; diff --git a/test/cloudevent_spec_0_2.js b/test/cloudevent_spec_0_2.js index e8fa997..6c7102c 100644 --- a/test/cloudevent_spec_0_2.js +++ b/test/cloudevent_spec_0_2.js @@ -9,9 +9,10 @@ const contenttype = "application/json"; const data = {}; const extensions = {}; -var cloudevent = new Cloudevent(Cloudevent.specs["0.2"]) - .type(type) - .source(source); +var cloudevent = + new Cloudevent(Cloudevent.specs["0.2"]) + .type(type) + .source(source); describe("CloudEvents Spec 0.2 - JavaScript SDK", () => { @@ -65,6 +66,17 @@ describe("CloudEvents Spec 0.2 - JavaScript SDK", () => { cloudevent.addExtension("extension2", "value2"); expect(cloudevent.format()["extension2"]).to.equal("value2"); }); + + it("should throw an error when employ reserved name as extension", () => { + + var cevt = + new Cloudevent(Cloudevent.specs["0.2"]) + .type(type) + .source(source); + expect(cevt.addExtension.bind(cevt, "id")) + .to + .throw("Reserved attribute name: 'id'"); + }); }); describe("The Constraints check", () => { From c8ccd85bc8c1143bbb563212a72ac8dc9dd8e516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 20 Jan 2019 21:43:53 -0200 Subject: [PATCH 6/6] Fix cyclomatic complexity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/binary_0_2.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/bindings/http/binary_0_2.js b/lib/bindings/http/binary_0_2.js index c398a0b..8d249e5 100644 --- a/lib/bindings/http/binary_0_2.js +++ b/lib/bindings/http/binary_0_2.js @@ -17,9 +17,7 @@ HTTPBinary.prototype.emit = function(cloudevent){ // Always set stuff in _config var _headers = _config["headers"]; - if(cloudevent.getContenttype()) { - _headers["Content-Type"] = cloudevent.getContenttype(); - } + _headers["Content-Type"] = cloudevent.getContenttype(); _headers["ce-type"] = cloudevent.getType(); _headers["ce-specversion"] = cloudevent.getSpecversion();