From ce04b5bf3a78be90538a400f7506d75b63e31902 Mon Sep 17 00:00:00 2001 From: Ilya Diallo Date: Wed, 7 Jun 2017 11:01:02 +0200 Subject: [PATCH 1/3] The 'beforeSave' trigger breaks requests using the dot notation for subdocuments (cf #567) --- spec/rest.spec.js | 8 +++++++- src/RestWrite.js | 29 +++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/spec/rest.spec.js b/spec/rest.spec.js index 6326180732..43209dd460 100644 --- a/spec/rest.spec.js +++ b/spec/rest.spec.js @@ -54,6 +54,12 @@ describe('rest create', () => { it('handles object and subdocument', done => { const obj = { subdoc: {foo: 'bar', wu: 'tan'} }; + + Parse.Cloud.beforeSave('MyClass', function(req, res) { + // this beforeSave trigger should do nothing but can mess with the object + res.success(); + }); + rest.create(config, auth.nobody(config), 'MyClass', obj) .then(() => database.adapter.find('MyClass', { fields: {} }, {}, {})) .then(results => { @@ -64,7 +70,7 @@ describe('rest create', () => { expect(mob.subdoc.wu).toBe('tan'); expect(typeof mob.objectId).toEqual('string'); const obj = { 'subdoc.wu': 'clan' }; - return rest.update(config, auth.nobody(config), 'MyClass', { objectId: mob.objectId }, obj) + return rest.update(config, auth.nobody(config), 'MyClass', { objectId: mob.objectId }, obj); }) .then(() => database.adapter.find('MyClass', { fields: {} }, {}, {})) .then(results => { diff --git a/src/RestWrite.js b/src/RestWrite.js index 24015024e4..30bb5107f3 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -153,12 +153,11 @@ RestWrite.prototype.runBeforeTrigger = function() { } let originalObject = null; - const updatedObject = triggers.inflate(extraData, this.originalData); + const updatedObject = this.buildUpdatedObject(extraData); if (this.query && this.query.objectId) { // This is an update for existing object. originalObject = triggers.inflate(extraData, this.originalData); } - updatedObject.set(this.sanitizedData()); return Promise.resolve().then(() => { return triggers.maybeRunTrigger(triggers.Types.beforeSave, this.auth, updatedObject, originalObject, this.config); @@ -1068,8 +1067,7 @@ RestWrite.prototype.runAfterTrigger = function() { // Build the inflated object, different from beforeSave, originalData is not empty // since developers can change data in the beforeSave. - const updatedObject = triggers.inflate(extraData, this.originalData); - updatedObject.set(this.sanitizedData()); + const updatedObject = this.buildUpdatedObject(extraData); updatedObject._handleSaveResponse(this.response.response, this.response.status || 200); // Notifiy LiveQueryServer if possible @@ -1104,6 +1102,29 @@ RestWrite.prototype.sanitizedData = function() { return Parse._decode(undefined, data); } +// Returns an updated copy of the object +RestWrite.prototype.buildUpdatedObject = function (extraData) { + var updatedObject = triggers.inflate(extraData, this.originalData); + Object.keys(this.data).reduce(function (data, key) { + if (key.indexOf(".") > 0) { + // subdocument key with dot notation ('x.y':v => 'x':{'y':v}) + var splittedKey = key.split("."); + var parentProp = splittedKey[0]; + var parentVal = updatedObject.get(parentProp); + if(typeof parentVal !== 'object') { + parentVal = {}; + } + parentVal[splittedKey[1]] = data[key]; + updatedObject.set(parentProp, parentVal); + delete data[key]; + } + return data; + }, deepcopy(this.data)); + + updatedObject.set(this.sanitizedData()); + return updatedObject; +}; + RestWrite.prototype.cleanUserAuthData = function() { if (this.response && this.response.response && this.className === '_User') { const user = this.response.response; From 2efb12cd2d09efdff2d576ae84eaff0c4336e35c Mon Sep 17 00:00:00 2001 From: Ilya Diallo Date: Wed, 14 Jun 2017 09:46:38 +0200 Subject: [PATCH 2/3] Convert 'var' to 'let' / 'const' --- src/RestWrite.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/RestWrite.js b/src/RestWrite.js index 30bb5107f3..92bd6bb677 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -1108,9 +1108,9 @@ RestWrite.prototype.buildUpdatedObject = function (extraData) { Object.keys(this.data).reduce(function (data, key) { if (key.indexOf(".") > 0) { // subdocument key with dot notation ('x.y':v => 'x':{'y':v}) - var splittedKey = key.split("."); - var parentProp = splittedKey[0]; - var parentVal = updatedObject.get(parentProp); + const splittedKey = key.split("."); + const parentProp = splittedKey[0]; + let parentVal = updatedObject.get(parentProp); if(typeof parentVal !== 'object') { parentVal = {}; } From ab34c1204aadc9c99628e9453517212bfef850fc Mon Sep 17 00:00:00 2001 From: Ilya Diallo Date: Wed, 14 Jun 2017 18:14:31 +0200 Subject: [PATCH 3/3] Convert 'var' to 'const' --- src/RestWrite.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RestWrite.js b/src/RestWrite.js index 92bd6bb677..d8e13a65af 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -1104,7 +1104,7 @@ RestWrite.prototype.sanitizedData = function() { // Returns an updated copy of the object RestWrite.prototype.buildUpdatedObject = function (extraData) { - var updatedObject = triggers.inflate(extraData, this.originalData); + const updatedObject = triggers.inflate(extraData, this.originalData); Object.keys(this.data).reduce(function (data, key) { if (key.indexOf(".") > 0) { // subdocument key with dot notation ('x.y':v => 'x':{'y':v})