Skip to content

Commit 92fa6f2

Browse files
IlyaDiallonatanrolnik
authored andcommitted
The 'beforeSave' trigger breaks the dot notation for subdocuments (cf #567) (#3912)
* The 'beforeSave' trigger breaks requests using the dot notation for subdocuments (cf #567) * Convert 'var' to 'let' / 'const' * Convert 'var' to 'const'
1 parent f0949a1 commit 92fa6f2

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

spec/rest.spec.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ describe('rest create', () => {
5454

5555
it('handles object and subdocument', done => {
5656
const obj = { subdoc: {foo: 'bar', wu: 'tan'} };
57+
58+
Parse.Cloud.beforeSave('MyClass', function(req, res) {
59+
// this beforeSave trigger should do nothing but can mess with the object
60+
res.success();
61+
});
62+
5763
rest.create(config, auth.nobody(config), 'MyClass', obj)
5864
.then(() => database.adapter.find('MyClass', { fields: {} }, {}, {}))
5965
.then(results => {
@@ -64,7 +70,7 @@ describe('rest create', () => {
6470
expect(mob.subdoc.wu).toBe('tan');
6571
expect(typeof mob.objectId).toEqual('string');
6672
const obj = { 'subdoc.wu': 'clan' };
67-
return rest.update(config, auth.nobody(config), 'MyClass', { objectId: mob.objectId }, obj)
73+
return rest.update(config, auth.nobody(config), 'MyClass', { objectId: mob.objectId }, obj);
6874
})
6975
.then(() => database.adapter.find('MyClass', { fields: {} }, {}, {}))
7076
.then(results => {

src/RestWrite.js

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,11 @@ RestWrite.prototype.runBeforeTrigger = function() {
153153
}
154154

155155
let originalObject = null;
156-
const updatedObject = triggers.inflate(extraData, this.originalData);
156+
const updatedObject = this.buildUpdatedObject(extraData);
157157
if (this.query && this.query.objectId) {
158158
// This is an update for existing object.
159159
originalObject = triggers.inflate(extraData, this.originalData);
160160
}
161-
updatedObject.set(this.sanitizedData());
162161

163162
return Promise.resolve().then(() => {
164163
return triggers.maybeRunTrigger(triggers.Types.beforeSave, this.auth, updatedObject, originalObject, this.config);
@@ -1068,8 +1067,7 @@ RestWrite.prototype.runAfterTrigger = function() {
10681067

10691068
// Build the inflated object, different from beforeSave, originalData is not empty
10701069
// since developers can change data in the beforeSave.
1071-
const updatedObject = triggers.inflate(extraData, this.originalData);
1072-
updatedObject.set(this.sanitizedData());
1070+
const updatedObject = this.buildUpdatedObject(extraData);
10731071
updatedObject._handleSaveResponse(this.response.response, this.response.status || 200);
10741072

10751073
// Notifiy LiveQueryServer if possible
@@ -1104,6 +1102,29 @@ RestWrite.prototype.sanitizedData = function() {
11041102
return Parse._decode(undefined, data);
11051103
}
11061104

1105+
// Returns an updated copy of the object
1106+
RestWrite.prototype.buildUpdatedObject = function (extraData) {
1107+
const updatedObject = triggers.inflate(extraData, this.originalData);
1108+
Object.keys(this.data).reduce(function (data, key) {
1109+
if (key.indexOf(".") > 0) {
1110+
// subdocument key with dot notation ('x.y':v => 'x':{'y':v})
1111+
const splittedKey = key.split(".");
1112+
const parentProp = splittedKey[0];
1113+
let parentVal = updatedObject.get(parentProp);
1114+
if(typeof parentVal !== 'object') {
1115+
parentVal = {};
1116+
}
1117+
parentVal[splittedKey[1]] = data[key];
1118+
updatedObject.set(parentProp, parentVal);
1119+
delete data[key];
1120+
}
1121+
return data;
1122+
}, deepcopy(this.data));
1123+
1124+
updatedObject.set(this.sanitizedData());
1125+
return updatedObject;
1126+
};
1127+
11071128
RestWrite.prototype.cleanUserAuthData = function() {
11081129
if (this.response && this.response.response && this.className === '_User') {
11091130
const user = this.response.response;

0 commit comments

Comments
 (0)