Fix issue with pointers getting un-hydrated when there is a beforeSave (#1884)
* Add failing test and simplify RestWrite * simplify and add test stubs * Fix issue
This commit is contained in:
@@ -557,4 +557,36 @@ describe('Cloud Code', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('trivial beforeSave should not affect fetched pointers (regression test for #1238)', done => {
|
||||||
|
Parse.Cloud.beforeSave('BeforeSaveUnchanged', (req, res) => {
|
||||||
|
res.success();
|
||||||
|
});
|
||||||
|
|
||||||
|
var TestObject = Parse.Object.extend("TestObject");
|
||||||
|
var NoBeforeSaveObject = Parse.Object.extend("NoBeforeSave");
|
||||||
|
var BeforeSaveObject = Parse.Object.extend("BeforeSaveUnchanged");
|
||||||
|
|
||||||
|
var aTestObject = new TestObject();
|
||||||
|
aTestObject.set("foo", "bar");
|
||||||
|
aTestObject.save()
|
||||||
|
.then(aTestObject => {
|
||||||
|
var aNoBeforeSaveObj = new NoBeforeSaveObject();
|
||||||
|
aNoBeforeSaveObj.set("aTestObject", aTestObject);
|
||||||
|
expect(aNoBeforeSaveObj.get("aTestObject").get("foo")).toEqual("bar");
|
||||||
|
return aNoBeforeSaveObj.save();
|
||||||
|
})
|
||||||
|
.then(aNoBeforeSaveObj => {
|
||||||
|
expect(aNoBeforeSaveObj.get("aTestObject").get("foo")).toEqual("bar");
|
||||||
|
|
||||||
|
var aBeforeSaveObj = new BeforeSaveObject();
|
||||||
|
aBeforeSaveObj.set("aTestObject", aTestObject);
|
||||||
|
expect(aBeforeSaveObj.get("aTestObject").get("foo")).toEqual("bar");
|
||||||
|
return aBeforeSaveObj.save();
|
||||||
|
})
|
||||||
|
.then(aBeforeSaveObj => {
|
||||||
|
expect(aBeforeSaveObj.get("aTestObject").get("foo")).toEqual("bar");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ var passwordCrypto = require('./password');
|
|||||||
var Parse = require('parse/node');
|
var Parse = require('parse/node');
|
||||||
var triggers = require('./triggers');
|
var triggers = require('./triggers');
|
||||||
import RestQuery from './RestQuery';
|
import RestQuery from './RestQuery';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
// query and data are both provided in REST API format. So data
|
// query and data are both provided in REST API format. So data
|
||||||
// types are encoded by plain old objects.
|
// types are encoded by plain old objects.
|
||||||
@@ -165,8 +166,10 @@ RestWrite.prototype.runBeforeTrigger = function() {
|
|||||||
return triggers.maybeRunTrigger(triggers.Types.beforeSave, this.auth, updatedObject, originalObject, this.config);
|
return triggers.maybeRunTrigger(triggers.Types.beforeSave, this.auth, updatedObject, originalObject, this.config);
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
if (response && response.object) {
|
if (response && response.object) {
|
||||||
|
if (!_.isEqual(this.data, response.object)) {
|
||||||
|
this.storage.changedByTrigger = true;
|
||||||
|
}
|
||||||
this.data = response.object;
|
this.data = response.object;
|
||||||
this.storage['changedByTrigger'] = true;
|
|
||||||
// We should delete the objectId for an update write
|
// We should delete the objectId for an update write
|
||||||
if (this.query && this.query.objectId) {
|
if (this.query && this.query.objectId) {
|
||||||
delete this.data.objectId
|
delete this.data.objectId
|
||||||
@@ -733,19 +736,16 @@ RestWrite.prototype.runDatabaseOperation = function() {
|
|||||||
this.data.ACL[this.query.objectId] = { read: true, write: true };
|
this.data.ACL[this.query.objectId] = { read: true, write: true };
|
||||||
}
|
}
|
||||||
// Run an update
|
// Run an update
|
||||||
return this.config.database.update(
|
return this.config.database.update(this.className, this.query, this.data, this.runOptions)
|
||||||
this.className, this.query, this.data, this.runOptions).then((resp) => {
|
.then(response => {
|
||||||
resp.updatedAt = this.updatedAt;
|
response.updatedAt = this.updatedAt;
|
||||||
if (this.storage['changedByTrigger']) {
|
if (this.storage.changedByTrigger) {
|
||||||
resp = Object.keys(this.data).reduce((memo, key) => {
|
Object.keys(this.data).forEach(fieldName => {
|
||||||
memo[key] = resp[key] || this.data[key];
|
response[fieldName] = response[fieldName] || this.data[fieldName];
|
||||||
return memo;
|
});
|
||||||
}, resp);
|
}
|
||||||
}
|
this.response = { response };
|
||||||
this.response = {
|
});
|
||||||
response: resp
|
|
||||||
};
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
// Set the default ACL for the new _User
|
// Set the default ACL for the new _User
|
||||||
if (this.className === '_User') {
|
if (this.className === '_User') {
|
||||||
@@ -762,23 +762,20 @@ RestWrite.prototype.runDatabaseOperation = function() {
|
|||||||
|
|
||||||
// Run a create
|
// Run a create
|
||||||
return this.config.database.create(this.className, this.data, this.runOptions)
|
return this.config.database.create(this.className, this.data, this.runOptions)
|
||||||
.then((resp) => {
|
.then(response => {
|
||||||
Object.assign(resp, {
|
response.objectId = this.data.objectId;
|
||||||
objectId: this.data.objectId,
|
response.createdAt = this.data.createdAt;
|
||||||
createdAt: this.data.createdAt
|
if (this.storage.changedByTrigger) {
|
||||||
|
Object.keys(this.data).forEach(fieldName => {
|
||||||
|
response[fieldName] = response[fieldName] || this.data[fieldName];
|
||||||
});
|
});
|
||||||
if (this.storage['changedByTrigger']) {
|
}
|
||||||
resp = Object.keys(this.data).reduce((memo, key) => {
|
this.response = {
|
||||||
memo[key] = resp[key] || this.data[key];
|
status: 201,
|
||||||
return memo;
|
response,
|
||||||
}, resp);
|
location: this.location()
|
||||||
}
|
};
|
||||||
this.response = {
|
});
|
||||||
status: 201,
|
|
||||||
response: resp,
|
|
||||||
location: this.location()
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user