fix: updating object includes unchanged keys in client response for certain key types (#8159)

This commit is contained in:
dblythy
2022-09-18 02:20:50 +10:00
committed by GitHub
parent 41e44302b4
commit 37af1d78fc
3 changed files with 160 additions and 57 deletions

View File

@@ -951,57 +951,154 @@ describe('miscellaneous', function () {
);
});
it('should return the updated fields on PUT', done => {
it('return the updated fields on PUT', async () => {
const obj = new Parse.Object('GameScore');
obj
.save({ a: 'hello', c: 1, d: ['1'], e: ['1'], f: ['1', '2'] })
.then(() => {
const headers = {
'Content-Type': 'application/json',
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
'X-Parse-Installation-Id': 'yolo',
};
request({
method: 'PUT',
headers: headers,
url: 'http://localhost:8378/1/classes/GameScore/' + obj.id,
body: JSON.stringify({
a: 'b',
c: { __op: 'Increment', amount: 2 },
d: { __op: 'Add', objects: ['2'] },
e: { __op: 'AddUnique', objects: ['1', '2'] },
f: { __op: 'Remove', objects: ['2'] },
selfThing: {
__type: 'Pointer',
className: 'GameScore',
objectId: obj.id,
},
}),
}).then(response => {
try {
const body = response.data;
expect(body.a).toBeUndefined();
expect(body.c).toEqual(3); // 2+1
expect(body.d.length).toBe(2);
expect(body.d.indexOf('1') > -1).toBe(true);
expect(body.d.indexOf('2') > -1).toBe(true);
expect(body.e.length).toBe(2);
expect(body.e.indexOf('1') > -1).toBe(true);
expect(body.e.indexOf('2') > -1).toBe(true);
expect(body.f.length).toBe(1);
expect(body.f.indexOf('1') > -1).toBe(true);
// return nothing on other self
expect(body.selfThing).toBeUndefined();
// updatedAt is always set
expect(body.updatedAt).not.toBeUndefined();
} catch (e) {
fail(e);
}
done();
});
const pointer = new Parse.Object('Child');
await pointer.save();
obj.set(
'point',
new Parse.GeoPoint({
latitude: 37.4848,
longitude: -122.1483,
})
.catch(done.fail);
);
obj.set('array', ['obj1', 'obj2']);
obj.set('objects', { a: 'b' });
obj.set('string', 'abc');
obj.set('bool', true);
obj.set('number', 1);
obj.set('date', new Date());
obj.set('pointer', pointer);
const headers = {
'Content-Type': 'application/json',
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
'X-Parse-Installation-Id': 'yolo',
};
const saveResponse = await request({
method: 'POST',
headers: headers,
url: 'http://localhost:8378/1/classes/GameScore',
body: JSON.stringify({
a: 'hello',
c: 1,
d: ['1'],
e: ['1'],
f: ['1', '2'],
...obj.toJSON(),
}),
});
expect(Object.keys(saveResponse.data).sort()).toEqual(['createdAt', 'objectId']);
obj.id = saveResponse.data.objectId;
const response = await request({
method: 'PUT',
headers: headers,
url: 'http://localhost:8378/1/classes/GameScore/' + obj.id,
body: JSON.stringify({
a: 'b',
c: { __op: 'Increment', amount: 2 },
d: { __op: 'Add', objects: ['2'] },
e: { __op: 'AddUnique', objects: ['1', '2'] },
f: { __op: 'Remove', objects: ['2'] },
selfThing: {
__type: 'Pointer',
className: 'GameScore',
objectId: obj.id,
},
}),
});
const body = response.data;
expect(Object.keys(body).sort()).toEqual(['c', 'd', 'e', 'f', 'updatedAt']);
expect(body.a).toBeUndefined();
expect(body.c).toEqual(3); // 2+1
expect(body.d.length).toBe(2);
expect(body.d.indexOf('1') > -1).toBe(true);
expect(body.d.indexOf('2') > -1).toBe(true);
expect(body.e.length).toBe(2);
expect(body.e.indexOf('1') > -1).toBe(true);
expect(body.e.indexOf('2') > -1).toBe(true);
expect(body.f.length).toBe(1);
expect(body.f.indexOf('1') > -1).toBe(true);
expect(body.selfThing).toBeUndefined();
expect(body.updatedAt).not.toBeUndefined();
});
it('should response should not change with triggers', async () => {
const obj = new Parse.Object('GameScore');
const pointer = new Parse.Object('Child');
Parse.Cloud.beforeSave('GameScore', request => {
return request.object;
});
Parse.Cloud.afterSave('GameScore', request => {
return request.object;
});
await pointer.save();
obj.set(
'point',
new Parse.GeoPoint({
latitude: 37.4848,
longitude: -122.1483,
})
);
obj.set('array', ['obj1', 'obj2']);
obj.set('objects', { a: 'b' });
obj.set('string', 'abc');
obj.set('bool', true);
obj.set('number', 1);
obj.set('date', new Date());
obj.set('pointer', pointer);
const headers = {
'Content-Type': 'application/json',
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
'X-Parse-Installation-Id': 'yolo',
};
const saveResponse = await request({
method: 'POST',
headers: headers,
url: 'http://localhost:8378/1/classes/GameScore',
body: JSON.stringify({
a: 'hello',
c: 1,
d: ['1'],
e: ['1'],
f: ['1', '2'],
...obj.toJSON(),
}),
});
expect(Object.keys(saveResponse.data).sort()).toEqual(['createdAt', 'objectId']);
obj.id = saveResponse.data.objectId;
const response = await request({
method: 'PUT',
headers: headers,
url: 'http://localhost:8378/1/classes/GameScore/' + obj.id,
body: JSON.stringify({
a: 'b',
c: { __op: 'Increment', amount: 2 },
d: { __op: 'Add', objects: ['2'] },
e: { __op: 'AddUnique', objects: ['1', '2'] },
f: { __op: 'Remove', objects: ['2'] },
selfThing: {
__type: 'Pointer',
className: 'GameScore',
objectId: obj.id,
},
}),
});
const body = response.data;
expect(Object.keys(body).sort()).toEqual(['c', 'd', 'e', 'f', 'updatedAt']);
expect(body.a).toBeUndefined();
expect(body.c).toEqual(3); // 2+1
expect(body.d.length).toBe(2);
expect(body.d.indexOf('1') > -1).toBe(true);
expect(body.d.indexOf('2') > -1).toBe(true);
expect(body.e.length).toBe(2);
expect(body.e.indexOf('1') > -1).toBe(true);
expect(body.e.indexOf('2') > -1).toBe(true);
expect(body.f.length).toBe(1);
expect(body.f.indexOf('1') > -1).toBe(true);
expect(body.selfThing).toBeUndefined();
expect(body.updatedAt).not.toBeUndefined();
});
it('test cloud function error handling', done => {

View File

@@ -521,7 +521,6 @@ describe('RestQuery.each', () => {
'createdAt',
'initialToRemove',
'objectId',
'updatedAt',
]);
});
});

View File

@@ -12,6 +12,7 @@ var passwordCrypto = require('./password');
var Parse = require('parse/node');
var triggers = require('./triggers');
var ClientSDK = require('./ClientSDK');
const util = require('util');
import RestQuery from './RestQuery';
import _ from 'lodash';
import logger from './logger';
@@ -1677,18 +1678,24 @@ RestWrite.prototype._updateResponseWithData = function (response, data) {
this.storage.fieldsChangedByTrigger.push(key);
}
}
const skipKeys = [
'objectId',
'createdAt',
'updatedAt',
...(requiredColumns.read[this.className] || []),
];
const skipKeys = [...(requiredColumns.read[this.className] || [])];
if (!this.query) {
skipKeys.push('objectId', 'createdAt');
} else {
skipKeys.push('updatedAt');
delete response.objectId;
}
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) {
if (
value == null ||
(value.__type && value.__type === 'Pointer') ||
util.isDeepStrictEqual(data[key], value) ||
util.isDeepStrictEqual((this.originalData || {})[key], value)
) {
delete response[key];
}
}