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'
This commit is contained in:
IlyaDiallo
2017-06-14 20:51:41 +02:00
committed by Natan Rolnik
parent f0949a1310
commit 92fa6f2b8a
2 changed files with 32 additions and 5 deletions

View File

@@ -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 => {

View File

@@ -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) {
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 = {};
}
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;