From 643bdc8227bb9e1d67f02af4a627a87b01b84856 Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Wed, 18 May 2016 18:10:57 -0700 Subject: [PATCH] Move query validation out of mongo adapter --- .../Storage/Mongo/MongoStorageAdapter.js | 1 - src/Adapters/Storage/Mongo/MongoTransform.js | 31 ----------------- src/Controllers/DatabaseController.js | 34 +++++++++++++++++-- 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index d6b0f1ab..c860819d 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -185,7 +185,6 @@ export class MongoStorageAdapter { deleteObjectsByQuery(className, query, validate, schema) { return this.adaptiveCollection(className) .then(collection => { - transform.validateQuery(query); let mongoWhere = transform.transformWhere(className, query, schema); return collection.deleteMany(mongoWhere) }) diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index e92cacee..33aa666b 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -211,39 +211,9 @@ function transformQueryKeyValue(className, key, value, schema) { } } -const validateQuery = query => { - if (query.ACL) { - throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); - } - - if (query.$or) { - if (query.$or instanceof Array) { - query.$or.forEach(validateQuery); - } else { - throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Bad $or format - use an array value.'); - } - } - - if (query.$and) { - if (query.$and instanceof Array) { - query.$and.forEach(validateQuery); - } else { - throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Bad $and format - use an array value.'); - } - } - - Object.keys(query).forEach(key => { - if (!specialQuerykeys.includes(key) && !key.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) { - throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid key name: ${key}`); - } - }); -} - // Main exposed method to help run queries. // 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. -const specialQuerykeys = ['$and', '$or', '_rperm', '_wperm', '_perishable_token', '_email_verify_token']; function transformWhere(className, restWhere, schema) { let mongoWhere = {}; for (let restKey in restWhere) { @@ -1048,7 +1018,6 @@ var FileCoder = { module.exports = { transformKey, - validateQuery, parseObjectToMongoObjectForCreate, transformUpdate, transformWhere, diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index 2657806b..0af8fb92 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -24,6 +24,35 @@ function addReadACL(query, acl) { return newQuery; } +const specialQuerykeys = ['$and', '$or', '_rperm', '_wperm', '_perishable_token', '_email_verify_token']; +const validateQuery = query => { + if (query.ACL) { + throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); + } + + if (query.$or) { + if (query.$or instanceof Array) { + query.$or.forEach(validateQuery); + } else { + throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Bad $or format - use an array value.'); + } + } + + if (query.$and) { + if (query.$and instanceof Array) { + query.$and.forEach(validateQuery); + } else { + throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Bad $and format - use an array value.'); + } + } + + Object.keys(query).forEach(key => { + if (!specialQuerykeys.includes(key) && !key.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid key name: ${key}`); + } + }); +} + function DatabaseController(adapter, { skipValidation } = {}) { this.adapter = adapter; @@ -174,6 +203,7 @@ DatabaseController.prototype.update = function(className, query, update, { if (acl) { query = addWriteACL(query, acl); } + validateQuery(query); return schemaController.getOneSchema(className) .catch(error => { // If the schema doesn't exist, pretend it exists with no fields. This behaviour @@ -184,7 +214,6 @@ DatabaseController.prototype.update = function(className, query, update, { throw error; }) .then(parseFormatSchema => { - this.transform.validateQuery(query); var mongoWhere = this.transform.transformWhere(className, query, parseFormatSchema); mongoUpdate = this.transform.transformUpdate( schemaController, @@ -329,6 +358,7 @@ DatabaseController.prototype.destroy = function(className, query, { acl } = {}) if (acl) { query = addWriteACL(query, acl); } + validateQuery(query); return schemaController.getOneSchema(className) .catch(error => { // If the schema doesn't exist, pretend it exists with no fields. This behaviour @@ -669,7 +699,7 @@ DatabaseController.prototype.find = function(className, query, { if (!isMaster) { query = addReadACL(query, aclGroup); } - this.transform.validateQuery(query); + validateQuery(query); let mongoWhere = this.transform.transformWhere(className, query, schema); if (count) { delete mongoOptions.limit;