Fix for #1840, Strip operations from results, forwards delete operations to SDKs (#1946)

* Adding a test demonstrating issue #1840.

* Fixes #1840

* Adds failing test with other use case

- That test fails on parse.com as well

* Bumps parse to 1.9.0

* exclude pg db

* Exclude pg on other test

* Adds clientSDK compatibility check for forward deletion

- Mark js1.9.0 as compatible

* Strips all operations from result

- fix for #1606
This commit is contained in:
Florent Vilmart
2016-07-15 09:24:53 -04:00
committed by GitHub
parent fcfe2a0376
commit 069275d3df
7 changed files with 216 additions and 39 deletions

40
src/ClientSDK.js Normal file
View File

@@ -0,0 +1,40 @@
var semver = require('semver');
function compatible(compatibleSDK) {
return function(clientSDK) {
if (typeof clientSDK === 'string') {
clientSDK = fromString(clientSDK);
}
// REST API, or custom SDK
if (!clientSDK) {
return true;
}
let clientVersion = clientSDK.version;
let compatiblityVersion = compatibleSDK[clientSDK.sdk];
return semver.satisfies(clientVersion, compatiblityVersion);
}
}
function supportsForwardDelete(clientSDK) {
return compatible({
js: '>=1.9.0'
})(clientSDK);
}
function fromString(version) {
let versionRE = /([-a-zA-Z]+)([0-9\.]+)/;
let match = version.toLowerCase().match(versionRE);
if (match && match.length === 3) {
return {
sdk: match[1],
version: match[2]
}
}
return undefined;
}
module.exports = {
compatible,
supportsForwardDelete,
fromString
}

View File

@@ -11,6 +11,7 @@ var cryptoUtils = require('./cryptoUtils');
var passwordCrypto = require('./password');
var Parse = require('parse/node');
var triggers = require('./triggers');
var ClientSDK = require('./ClientSDK');
import RestQuery from './RestQuery';
import _ from 'lodash';
@@ -774,9 +775,7 @@ RestWrite.prototype.runDatabaseOperation = function() {
.then(response => {
response.updatedAt = this.updatedAt;
if (this.storage.changedByTrigger) {
Object.keys(this.data).forEach(fieldName => {
response[fieldName] = response[fieldName] || this.data[fieldName];
});
this.updateResponseWithData(response, this.data);
}
this.response = { response };
});
@@ -834,9 +833,7 @@ RestWrite.prototype.runDatabaseOperation = function() {
response.username = this.data.username;
}
if (this.storage.changedByTrigger) {
Object.keys(this.data).forEach(fieldName => {
response[fieldName] = response[fieldName] || this.data[fieldName];
});
this.updateResponseWithData(response, this.data);
}
this.response = {
status: 201,
@@ -925,5 +922,24 @@ RestWrite.prototype.cleanUserAuthData = function() {
}
};
RestWrite.prototype.updateResponseWithData = function(response, data) {
let clientSupportsDelete = ClientSDK.supportsForwardDelete(this.clientSDK);
Object.keys(data).forEach(fieldName => {
let dataValue = data[fieldName];
let responseValue = response[fieldName];
response[fieldName] = responseValue || dataValue;
// Strips operations from responses
if (response[fieldName] && response[fieldName].__op) {
delete response[fieldName];
if (clientSupportsDelete && dataValue.__op == 'Delete') {
response[fieldName] = dataValue;
}
}
});
return response;
}
export default RestWrite;
module.exports = RestWrite;

View File

@@ -5,17 +5,7 @@ var Parse = require('parse/node').Parse;
var auth = require('./Auth');
var Config = require('./Config');
function clientSDKFromVersion(version) {
let versionRE = /([-a-zA-Z]+)([0-9\.]+)/;
let match = version.toLowerCase().match(versionRE);
if (match && match.length === 3) {
return {
sdk: match[1],
version: match[2]
}
}
}
var ClientSDK = require('./ClientSDK');
// Checks that the request is authorized for this app and checks user
// auth too.
@@ -106,7 +96,7 @@ function handleParseHeaders(req, res, next) {
}
if (info.clientVersion) {
info.clientSDK = clientSDKFromVersion(info.clientVersion);
info.clientSDK = ClientSDK.fromString(info.clientVersion);
}
if (fileViaJSON) {
@@ -300,5 +290,4 @@ module.exports = {
handleParseHeaders: handleParseHeaders,
enforceMasterKeyAccess: enforceMasterKeyAccess,
promiseEnforceMasterKeyAccess,
clientSDKFromVersion
};