From 4371ca164cb4dceee36af4c7142a4a191bf63ad7 Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Mon, 25 Apr 2016 22:45:16 -0700 Subject: [PATCH] Pass parse format schema to transformWhere --- .../Storage/Mongo/MongoStorageAdapter.js | 5 +- src/Adapters/Storage/Mongo/MongoTransform.js | 10 +- src/Controllers/DatabaseController.js | 100 ++++++++++++------ 3 files changed, 77 insertions(+), 38 deletions(-) diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 803b3c63..a6a642da 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -174,14 +174,15 @@ export class MongoStorageAdapter { // If there is some other error, reject with INTERNAL_SERVER_ERROR. // Currently accepts the schemaController, and validate for lecacy reasons - deleteObjectsByQuery(className, query, schemaController, validate) { + deleteObjectsByQuery(className, query, schemaController, validate, parseFormatSchema) { return this.adaptiveCollection(className) .then(collection => { let mongoWhere = transform.transformWhere( schemaController, className, query, - { validate } + { validate }, + parseFormatSchema ); return collection.deleteMany(mongoWhere) }) diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index 5c724c57..ac056a20 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -139,7 +139,7 @@ const valueAsDate = value => { return false; } -function transformQueryKeyValue(schema, className, key, value, { validate } = {}) { +function transformQueryKeyValue(schema, className, key, value, { validate } = {}, parseFormatSchema) { switch(key) { case 'createdAt': if (valueAsDate(value)) { @@ -168,12 +168,12 @@ function transformQueryKeyValue(schema, className, key, value, { validate } = {} if (!(value instanceof Array)) { throw new Parse.Error(Parse.Error.INVALID_QUERY, 'bad $or format - use an array value'); } - return {key: '$or', value: value.map(subQuery => transformWhere(schema, className, subQuery))}; + return {key: '$or', value: value.map(subQuery => transformWhere(schema, className, subQuery, parseFormatSchema))}; case '$and': if (!(value instanceof Array)) { throw new Parse.Error(Parse.Error.INVALID_QUERY, 'bad $and format - use an array value'); } - return {key: '$and', value: value.map(subQuery => transformWhere(schema, className, subQuery))}; + return {key: '$and', value: value.map(subQuery => transformWhere(schema, className, subQuery, parseFormatSchema))}; default: // Other auth data const authDataMatch = key.match(/^authData\.([a-zA-Z0-9_]+)\.id$/); @@ -218,13 +218,13 @@ function transformQueryKeyValue(schema, className, key, value, { validate } = {} // restWhere is the "where" clause in REST API form. // Returns the mongo form of the query. // Throws a Parse.Error if the input query is invalid. -function transformWhere(schema, className, restWhere, { validate = true } = {}) { +function transformWhere(schema, className, restWhere, { validate = true } = {}, parseFormatSchema) { let mongoWhere = {}; if (restWhere['ACL']) { throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); } for (let restKey in restWhere) { - let out = transformQueryKeyValue(schema, className, restKey, restWhere[restKey], { validate }); + let out = transformQueryKeyValue(schema, className, restKey, restWhere[restKey], { validate }, parseFormatSchema); mongoWhere[out.key] = out.value; } return mongoWhere; diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index 907da41e..b6f6b9a6 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -174,25 +174,37 @@ DatabaseController.prototype.update = function(className, query, update, { if (acl) { query = addWriteACL(query, acl); } - var mongoWhere = this.transform.transformWhere( - schemaController, - className, - query, - {validate: !this.skipValidation} - ); - mongoUpdate = this.transform.transformUpdate( - schemaController, - className, - update, - {validate: !this.skipValidation} - ); - if (many) { - return collection.updateMany(mongoWhere, mongoUpdate); - } else if (upsert) { - return collection.upsertOne(mongoWhere, mongoUpdate); - } else { - return collection.findOneAndUpdate(mongoWhere, mongoUpdate); - } + return schemaController.getOneSchema(className) + .catch(error => { + // If the schema doesn't exist, pretend it exists with no fields. This behaviour + // will likely need revisiting. + if (error === undefined) { + return { fields: {} }; + } + throw error; + }) + .then(parseFormatSchema => { + var mongoWhere = this.transform.transformWhere( + schemaController, + className, + query, + {validate: !this.skipValidation}, + parseFormatSchema + ); + mongoUpdate = this.transform.transformUpdate( + schemaController, + className, + update, + {validate: !this.skipValidation} + ); + if (many) { + return collection.updateMany(mongoWhere, mongoUpdate); + } else if (upsert) { + return collection.upsertOne(mongoWhere, mongoUpdate); + } else { + return collection.findOneAndUpdate(mongoWhere, mongoUpdate); + } + }); }) .then(result => { if (!result) { @@ -322,7 +334,22 @@ DatabaseController.prototype.destroy = function(className, query, { acl } = {}) if (acl) { query = addWriteACL(query, acl); } - return this.adapter.deleteObjectsByQuery(className, query, schemaController, !this.skipValidation) + return schemaController.getOneSchema(className) + .catch(error => { + // If the schema doesn't exist, pretend it exists with no fields. This behaviour + // will likely need revisiting. + if (error === undefined) { + return { fields: {} }; + } + throw error; + }) + .then(parseFormatSchema => this.adapter.deleteObjectsByQuery( + className, + query, + schemaController, + !this.skipValidation, + parseFormatSchema + )) .catch(error => { // When deleting sessions while changing passwords, don't throw an error if they don't have any sessions. if (className === "_Session" && error.code === Parse.Error.OBJECT_NOT_FOUND) { @@ -627,18 +654,29 @@ DatabaseController.prototype.find = function(className, query, { if (!isMaster) { query = addReadACL(query, aclGroup); } - let mongoWhere = this.transform.transformWhere(schemaController, className, query); - if (count) { - delete mongoOptions.limit; - return collection.count(mongoWhere, mongoOptions); - } else { - return collection.find(mongoWhere, mongoOptions) - .then((mongoResults) => { - return mongoResults.map((r) => { - return this.untransformObject(schemaController, isMaster, aclGroup, className, r); + return schemaController.getOneSchema(className) + .catch(error => { + // If the schema doesn't exist, pretend it exists with no fields. This behaviour + // will likely need revisiting. + if (error === undefined) { + return { fields: {} }; + } + throw error; + }) + .then(parseFormatSchema => { + let mongoWhere = this.transform.transformWhere(schemaController, className, query, parseFormatSchema); + if (count) { + delete mongoOptions.limit; + return collection.count(mongoWhere, mongoOptions); + } else { + return collection.find(mongoWhere, mongoOptions) + .then((mongoResults) => { + return mongoResults.map((r) => { + return this.untransformObject(schemaController, isMaster, aclGroup, className, r); + }); }); - }); - } + } + }); }); }); };