From d5b1cce84b7726bad3a6afa3714403a41d3be77d Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Wed, 11 Nov 2020 22:21:59 -0600 Subject: [PATCH 1/4] fix(beforeSave): Return value instead of Parse.Op --- spec/CloudCode.spec.js | 3 ++- src/RestWrite.js | 20 ++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index e60b6db491..565e8d1d31 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -1481,8 +1481,9 @@ describe('Cloud Code', () => { it('beforeSave should not sanitize database', async done => { let count = 0; - Parse.Cloud.beforeSave('CloudIncrementNested', () => { + Parse.Cloud.beforeSave('CloudIncrementNested', req => { count += 1; + expect(typeof req.object.get('objectField').number).toBe('number'); }); const obj = new Parse.Object('CloudIncrementNested'); diff --git a/src/RestWrite.js b/src/RestWrite.js index 9467c6a2d1..38b318100c 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -1558,15 +1558,19 @@ RestWrite.prototype.buildUpdatedObject = function (extraData) { 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}) - const splittedKey = key.split('.'); - const parentProp = splittedKey[0]; - let parentVal = updatedObject.get(parentProp); - if (typeof parentVal !== 'object') { - parentVal = {}; + if (typeof data[key].__op === 'string') { + updatedObject.set(key, data[key]); + } else { + // subdocument key with dot notation { 'x.y': v } => { 'x': { 'y' : v } }) + const splittedKey = key.split('.'); + const parentProp = splittedKey[0]; + let parentVal = updatedObject.get(parentProp); + if (typeof parentVal !== 'object') { + parentVal = {}; + } + parentVal[splittedKey[1]] = data[key]; + updatedObject.set(parentProp, parentVal); } - parentVal[splittedKey[1]] = data[key]; - updatedObject.set(parentProp, parentVal); delete data[key]; } return data; From 65395c91145ab790f355229d16ef16e49d17c8bf Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Wed, 11 Nov 2020 22:41:28 -0600 Subject: [PATCH 2/4] afterSave test --- spec/CloudCode.spec.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index 565e8d1d31..1449ca8958 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -1485,6 +1485,9 @@ describe('Cloud Code', () => { count += 1; expect(typeof req.object.get('objectField').number).toBe('number'); }); + Parse.Cloud.afterSave('CloudIncrementNested', req => { + expect(typeof req.object.get('objectField').number).toBe('number'); + }); const obj = new Parse.Object('CloudIncrementNested'); obj.set('objectField', { number: 5 }); From 00fb3b6ad1625f9b9e4516eeda5f97cd5bd4b977 Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Thu, 12 Nov 2020 00:29:25 -0600 Subject: [PATCH 3/4] Improve Tests --- spec/CloudCode.spec.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index 1449ca8958..2e5d8f9802 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -1480,21 +1480,40 @@ describe('Cloud Code', () => { }); it('beforeSave should not sanitize database', async done => { + const { adapter } = Config.get(Parse.applicationId).database; + spyOn(adapter, 'findOneAndUpdate').and.callThrough(); + let count = 0; Parse.Cloud.beforeSave('CloudIncrementNested', req => { count += 1; + req.object.set('foo', 'baz'); expect(typeof req.object.get('objectField').number).toBe('number'); }); + Parse.Cloud.afterSave('CloudIncrementNested', req => { expect(typeof req.object.get('objectField').number).toBe('number'); }); const obj = new Parse.Object('CloudIncrementNested'); obj.set('objectField', { number: 5 }); + obj.set('foo', 'bar'); await obj.save(); obj.increment('objectField.number', 10); await obj.save(); + + const [ + , + , + , + /* className */ /* schema */ /* query */ update, + ] = adapter.findOneAndUpdate.calls.first().args; + expect(update).toEqual({ + 'objectField.number': { __op: 'Increment', amount: 10 }, + foo: 'baz', + updatedAt: obj.updatedAt.toISOString(), + }); + count === 2 ? done() : fail(); }); From 57b3a81d47b31c0e5da41dd8eff89837a5bee93d Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Thu, 12 Nov 2020 12:54:18 -0600 Subject: [PATCH 4/4] Fixed postgres test by saveArgumentsByValue --- spec/CloudCode.spec.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index 2e5d8f9802..0a672db17e 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -1481,7 +1481,8 @@ describe('Cloud Code', () => { it('beforeSave should not sanitize database', async done => { const { adapter } = Config.get(Parse.applicationId).database; - spyOn(adapter, 'findOneAndUpdate').and.callThrough(); + const spy = spyOn(adapter, 'findOneAndUpdate').and.callThrough(); + spy.calls.saveArgumentsByValue(); let count = 0; Parse.Cloud.beforeSave('CloudIncrementNested', req => {