fix: afterSave trigger removes pointer in Parse object (#7913)
This commit is contained in:
@@ -1598,6 +1598,32 @@ describe('Cloud Code', () => {
|
||||
expect(obj.get('count')).toBe(0);
|
||||
});
|
||||
|
||||
it('pointer should not be cleared by triggers', async () => {
|
||||
Parse.Cloud.afterSave('MyObject', () => {});
|
||||
const foo = await new Parse.Object('Test', { foo: 'bar' }).save();
|
||||
const obj = await new Parse.Object('MyObject', { foo }).save();
|
||||
const foo2 = obj.get('foo');
|
||||
expect(foo2.get('foo')).toBe('bar');
|
||||
});
|
||||
|
||||
it('can set a pointer in triggers', async () => {
|
||||
Parse.Cloud.beforeSave('MyObject', () => {});
|
||||
Parse.Cloud.afterSave(
|
||||
'MyObject',
|
||||
async ({ object }) => {
|
||||
const foo = await new Parse.Object('Test', { foo: 'bar' }).save();
|
||||
object.set({ foo });
|
||||
await object.save(null, { useMasterKey: true });
|
||||
},
|
||||
{
|
||||
skipWithMasterKey: true,
|
||||
}
|
||||
);
|
||||
const obj = await new Parse.Object('MyObject').save();
|
||||
const foo2 = obj.get('foo');
|
||||
expect(foo2.get('foo')).toBe('bar');
|
||||
});
|
||||
|
||||
it('beforeSave should not sanitize database', async done => {
|
||||
const { adapter } = Config.get(Parse.applicationId).database;
|
||||
const spy = spyOn(adapter, 'findOneAndUpdate').and.callThrough();
|
||||
|
||||
@@ -429,4 +429,26 @@ describe('RestQuery.each', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('test afterSave should not affect save response', async () => {
|
||||
Parse.Cloud.beforeSave('TestObject2', ({ object }) => {
|
||||
object.set('addedBeforeSave', true);
|
||||
});
|
||||
Parse.Cloud.afterSave('TestObject2', ({ object }) => {
|
||||
object.set('addedAfterSave', true);
|
||||
object.unset('initialToRemove');
|
||||
});
|
||||
const { response } = await rest.create(config, nobody, 'TestObject2', {
|
||||
initialSave: true,
|
||||
initialToRemove: true,
|
||||
});
|
||||
expect(Object.keys(response).sort()).toEqual([
|
||||
'addedAfterSave',
|
||||
'addedBeforeSave',
|
||||
'createdAt',
|
||||
'initialToRemove',
|
||||
'objectId',
|
||||
'updatedAt',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -150,9 +150,15 @@ const defaultColumns: { [string]: SchemaFields } = Object.freeze({
|
||||
},
|
||||
});
|
||||
|
||||
// fields required for read or write operations on their respective classes.
|
||||
const requiredColumns = Object.freeze({
|
||||
_Product: ['productIdentifier', 'icon', 'order', 'title', 'subtitle'],
|
||||
_Role: ['name', 'ACL'],
|
||||
read: {
|
||||
_User: ['username'],
|
||||
},
|
||||
write: {
|
||||
_Product: ['productIdentifier', 'icon', 'order', 'title', 'subtitle'],
|
||||
_Role: ['name', 'ACL'],
|
||||
}
|
||||
});
|
||||
|
||||
const invalidColumns = ['length'];
|
||||
@@ -1269,7 +1275,7 @@ export default class SchemaController {
|
||||
|
||||
// Validates that all the properties are set for the object
|
||||
validateRequiredColumns(className: string, object: any, query: any) {
|
||||
const columns = requiredColumns[className];
|
||||
const columns = requiredColumns.write[className];
|
||||
if (!columns || columns.length == 0) {
|
||||
return Promise.resolve(this);
|
||||
}
|
||||
@@ -1600,4 +1606,5 @@ export {
|
||||
convertSchemaToAdapterSchema,
|
||||
VolatileClassesSchemas,
|
||||
SchemaController,
|
||||
requiredColumns,
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@ var ClientSDK = require('./ClientSDK');
|
||||
import RestQuery from './RestQuery';
|
||||
import _ from 'lodash';
|
||||
import logger from './logger';
|
||||
import { requiredColumns } from './Controllers/SchemaController';
|
||||
|
||||
// query and data are both provided in REST API format. So data
|
||||
// types are encoded by plain old objects.
|
||||
@@ -1556,7 +1557,7 @@ RestWrite.prototype.runAfterSaveTrigger = function () {
|
||||
this.response.response = result;
|
||||
} else {
|
||||
this.response.response = this._updateResponseWithData(
|
||||
(result || updatedObject)._toFullJSON(),
|
||||
(result || updatedObject).toJSON(),
|
||||
this.data
|
||||
);
|
||||
}
|
||||
@@ -1665,6 +1666,21 @@ RestWrite.prototype._updateResponseWithData = function (response, data) {
|
||||
this.storage.fieldsChangedByTrigger.push(key);
|
||||
}
|
||||
}
|
||||
const skipKeys = [
|
||||
'objectId',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
...(requiredColumns.read[this.className] || []),
|
||||
];
|
||||
for (const key in response) {
|
||||
if (skipKeys.includes(key)) {
|
||||
continue;
|
||||
}
|
||||
const value = response[key];
|
||||
if (value == null || (value.__type && value.__type === 'Pointer') || data[key] === value) {
|
||||
delete response[key];
|
||||
}
|
||||
}
|
||||
if (_.isEmpty(this.storage.fieldsChangedByTrigger)) {
|
||||
return response;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user