From 0d856c1f23cccfce69a695edff99813928bc23d7 Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Tue, 17 May 2016 00:56:04 -0700 Subject: [PATCH 1/9] remove extra lines --- src/Adapters/Storage/Mongo/MongoTransform.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index 31c3a919..230929bd 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -112,6 +112,7 @@ const transformInteriorValue = restValue => { if (typeof restValue === 'object' && Object.keys(restValue).some(key => key.includes('$') || key.includes('.'))) { throw new Parse.Error(Parse.Error.INVALID_NESTED_KEY, "Nested keys should not contain the '$' or '.' characters"); } + // Handle atomic values var value = transformInteriorAtom(restValue); if (value !== CannotTransform) { From b24ff151d5586750d718352709701b5fbb4874f8 Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Tue, 17 May 2016 15:57:25 -0700 Subject: [PATCH 2/9] Correct validation of inner keys --- src/Adapters/Storage/Mongo/MongoTransform.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index 230929bd..31c3a919 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -112,7 +112,6 @@ const transformInteriorValue = restValue => { if (typeof restValue === 'object' && Object.keys(restValue).some(key => key.includes('$') || key.includes('.'))) { throw new Parse.Error(Parse.Error.INVALID_NESTED_KEY, "Nested keys should not contain the '$' or '.' characters"); } - // Handle atomic values var value = transformInteriorAtom(restValue); if (value !== CannotTransform) { From 66b8a8474e83ba40d4af9b82d03175ca03ac6606 Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Wed, 18 May 2016 13:35:49 -0700 Subject: [PATCH 3/9] Lift query key validation out of transformQueryKeyValue --- src/Adapters/Storage/Mongo/MongoTransform.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index 31c3a919..5be57583 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -141,7 +141,7 @@ const valueAsDate = value => { return false; } -function transformQueryKeyValue(className, key, value, { validate } = {}, schema) { +function transformQueryKeyValue(className, key, value, schema) { switch(key) { case 'createdAt': if (valueAsDate(value)) { @@ -184,9 +184,6 @@ function transformQueryKeyValue(className, key, value, { validate } = {}, schema // Special-case auth data. return {key: `_auth_data_${provider}.id`, value}; } - if (validate && !key.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) { - throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'invalid key name: ' + key); - } } const expectedTypeIsArray = @@ -224,13 +221,17 @@ function transformQueryKeyValue(className, key, value, { validate } = {}, schema // 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, { validate = true } = {}, schema) { 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(className, restKey, restWhere[restKey], { validate }, schema); + if (validate && !specialQuerykeys.includes(restKey) && !restKey.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid key name: ${restKey}`); + } + let out = transformQueryKeyValue(className, restKey, restWhere[restKey], schema); mongoWhere[out.key] = out.value; } return mongoWhere; From 559205bc64d4983116fcc335bdc598c4135cf1bb Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Wed, 18 May 2016 13:49:31 -0700 Subject: [PATCH 4/9] Lift no-query-ACL validation out of transformWhere --- src/Adapters/Storage/Mongo/MongoStorageAdapter.js | 3 +++ src/Adapters/Storage/Mongo/MongoTransform.js | 9 ++++++--- src/Controllers/DatabaseController.js | 6 ++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 81af4e97..9096d4b8 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -184,6 +184,9 @@ export class MongoStorageAdapter { deleteObjectsByQuery(className, query, validate, schema) { return this.adaptiveCollection(className) .then(collection => { + if (query.ACL) { + throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); + } let mongoWhere = transform.transformWhere(className, query, { validate }, schema); return collection.deleteMany(mongoWhere) }) diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index 5be57583..a7aee55a 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -170,11 +170,17 @@ function transformQueryKeyValue(className, key, value, schema) { if (!(value instanceof Array)) { throw new Parse.Error(Parse.Error.INVALID_QUERY, 'bad $or format - use an array value'); } + if (value.some(subQuery => subQuery.ACL)) { + throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); + } return {key: '$or', value: value.map(subQuery => transformWhere(className, subQuery, {}, schema))}; case '$and': if (!(value instanceof Array)) { throw new Parse.Error(Parse.Error.INVALID_QUERY, 'bad $and format - use an array value'); } + if (value.some(subQuery => subQuery.ACL)) { + throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); + } return {key: '$and', value: value.map(subQuery => transformWhere(className, subQuery, {}, schema))}; default: // Other auth data @@ -224,9 +230,6 @@ function transformQueryKeyValue(className, key, value, schema) { const specialQuerykeys = ['$and', '$or', '_rperm', '_wperm', '_perishable_token', '_email_verify_token']; function transformWhere(className, restWhere, { validate = true } = {}, schema) { let mongoWhere = {}; - if (restWhere['ACL']) { - throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); - } for (let restKey in restWhere) { if (validate && !specialQuerykeys.includes(restKey) && !restKey.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) { throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid key name: ${restKey}`); diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index fefd5afe..ac0ada29 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -184,6 +184,9 @@ DatabaseController.prototype.update = function(className, query, update, { throw error; }) .then(parseFormatSchema => { + if (query.ACL) { + throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); + } var mongoWhere = this.transform.transformWhere(className, query, {validate: !this.skipValidation}, parseFormatSchema); mongoUpdate = this.transform.transformUpdate( schemaController, @@ -668,6 +671,9 @@ DatabaseController.prototype.find = function(className, query, { if (!isMaster) { query = addReadACL(query, aclGroup); } + if (query.ACL) { + throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); + } let mongoWhere = this.transform.transformWhere(className, query, {}, schema); if (count) { delete mongoOptions.limit; From ea0921351159a2938f85a4c89b681ba1f56fe980 Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Wed, 18 May 2016 16:26:59 -0700 Subject: [PATCH 5/9] lift query key validation out of transformWhere --- src/Adapters/Storage/Mongo/MongoStorageAdapter.js | 6 +++++- src/Adapters/Storage/Mongo/MongoTransform.js | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 9096d4b8..949ef1cc 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -25,6 +25,7 @@ const storageAdapterAllCollections = mongoAdapter => { }); } +const specialQuerykeys = ['$and', '$or', '_rperm', '_wperm', '_perishable_token', '_email_verify_token']; export class MongoStorageAdapter { // Private _uri: string; @@ -187,7 +188,10 @@ export class MongoStorageAdapter { if (query.ACL) { throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); } - let mongoWhere = transform.transformWhere(className, query, { validate }, schema); + if (validate && Object.keys(query).some(restKey => !specialQuerykeys.includes(restKey) && !restKey.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/))) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid key name: ${restKey}`); + } + let mongoWhere = transform.transformWhere(className, query, schema); return collection.deleteMany(mongoWhere) }) .then(({ result }) => { diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index a7aee55a..279888c9 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -172,6 +172,11 @@ function transformQueryKeyValue(className, key, value, schema) { } if (value.some(subQuery => subQuery.ACL)) { throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); + Object.keys(subQuery).forEach(restKey => { + if (!specialQuerykeys.includes(restKey) && !restKey.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid key name: ${restKey}`); + } + }); } return {key: '$or', value: value.map(subQuery => transformWhere(className, subQuery, {}, schema))}; case '$and': @@ -180,6 +185,11 @@ function transformQueryKeyValue(className, key, value, schema) { } if (value.some(subQuery => subQuery.ACL)) { throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); + Object.keys(subQuery).forEach(restKey => { + if (!specialQuerykeys.includes(restKey) && !restKey.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid key name: ${restKey}`); + } + }); } return {key: '$and', value: value.map(subQuery => transformWhere(className, subQuery, {}, schema))}; default: From 15fc186a517db3ed7f7d4f0e1550e5b1e9d13c01 Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Wed, 18 May 2016 18:05:04 -0700 Subject: [PATCH 6/9] Extract query validation logic --- .../Storage/Mongo/MongoStorageAdapter.js | 7 +-- src/Adapters/Storage/Mongo/MongoTransform.js | 60 ++++++++++--------- src/Controllers/DatabaseController.js | 12 ++-- src/Routers/GlobalConfigRouter.js | 2 +- 4 files changed, 38 insertions(+), 43 deletions(-) diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 949ef1cc..d6b0f1ab 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -185,12 +185,7 @@ export class MongoStorageAdapter { deleteObjectsByQuery(className, query, validate, schema) { return this.adaptiveCollection(className) .then(collection => { - if (query.ACL) { - throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); - } - if (validate && Object.keys(query).some(restKey => !specialQuerykeys.includes(restKey) && !restKey.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/))) { - throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid key name: ${restKey}`); - } + 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 279888c9..e92cacee 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -167,31 +167,9 @@ function transformQueryKeyValue(className, key, value, schema) { case '_perishable_token': case '_email_verify_token': return {key, value} case '$or': - if (!(value instanceof Array)) { - throw new Parse.Error(Parse.Error.INVALID_QUERY, 'bad $or format - use an array value'); - } - if (value.some(subQuery => subQuery.ACL)) { - throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); - Object.keys(subQuery).forEach(restKey => { - if (!specialQuerykeys.includes(restKey) && !restKey.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) { - throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid key name: ${restKey}`); - } - }); - } - return {key: '$or', value: value.map(subQuery => transformWhere(className, subQuery, {}, schema))}; + return {key: '$or', value: value.map(subQuery => transformWhere(className, subQuery, schema))}; case '$and': - if (!(value instanceof Array)) { - throw new Parse.Error(Parse.Error.INVALID_QUERY, 'bad $and format - use an array value'); - } - if (value.some(subQuery => subQuery.ACL)) { - throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); - Object.keys(subQuery).forEach(restKey => { - if (!specialQuerykeys.includes(restKey) && !restKey.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) { - throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid key name: ${restKey}`); - } - }); - } - return {key: '$and', value: value.map(subQuery => transformWhere(className, subQuery, {}, schema))}; + return {key: '$and', value: value.map(subQuery => transformWhere(className, subQuery, schema))}; default: // Other auth data const authDataMatch = key.match(/^authData\.([a-zA-Z0-9_]+)\.id$/); @@ -233,17 +211,42 @@ 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, { validate = true } = {}, schema) { +function transformWhere(className, restWhere, schema) { let mongoWhere = {}; for (let restKey in restWhere) { - if (validate && !specialQuerykeys.includes(restKey) && !restKey.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) { - throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid key name: ${restKey}`); - } let out = transformQueryKeyValue(className, restKey, restWhere[restKey], schema); mongoWhere[out.key] = out.value; } @@ -1045,6 +1048,7 @@ var FileCoder = { module.exports = { transformKey, + validateQuery, parseObjectToMongoObjectForCreate, transformUpdate, transformWhere, diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index ac0ada29..2657806b 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -184,10 +184,8 @@ DatabaseController.prototype.update = function(className, query, update, { throw error; }) .then(parseFormatSchema => { - if (query.ACL) { - throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); - } - var mongoWhere = this.transform.transformWhere(className, query, {validate: !this.skipValidation}, parseFormatSchema); + this.transform.validateQuery(query); + var mongoWhere = this.transform.transformWhere(className, query, parseFormatSchema); mongoUpdate = this.transform.transformUpdate( schemaController, className, @@ -671,10 +669,8 @@ DatabaseController.prototype.find = function(className, query, { if (!isMaster) { query = addReadACL(query, aclGroup); } - if (query.ACL) { - throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.'); - } - let mongoWhere = this.transform.transformWhere(className, query, {}, schema); + this.transform.validateQuery(query); + let mongoWhere = this.transform.transformWhere(className, query, schema); if (count) { delete mongoOptions.limit; return collection.count(mongoWhere, mongoOptions); diff --git a/src/Routers/GlobalConfigRouter.js b/src/Routers/GlobalConfigRouter.js index ab498522..5ab89b0b 100644 --- a/src/Routers/GlobalConfigRouter.js +++ b/src/Routers/GlobalConfigRouter.js @@ -24,7 +24,7 @@ export class GlobalConfigRouter extends PromiseRouter { return acc; }, {}); let database = req.config.database.WithoutValidation(); - return database.update('_GlobalConfig', {_id: 1}, update, {upsert: true}).then(() => { + return database.update('_GlobalConfig', {objectId: 1}, update, {upsert: true}).then(() => { return Promise.resolve({ response: { result: true } }); }); } From 643bdc8227bb9e1d67f02af4a627a87b01b84856 Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Wed, 18 May 2016 18:10:57 -0700 Subject: [PATCH 7/9] 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; From 5165c80570477f1ad37dca74491cdd74254ee81b Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Wed, 18 May 2016 18:35:02 -0700 Subject: [PATCH 8/9] Remove validate parameter from deleteObjectsByQuery --- src/Adapters/Storage/Mongo/MongoStorageAdapter.js | 4 ++-- src/Controllers/DatabaseController.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index c860819d..b47c32a6 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -181,8 +181,8 @@ export class MongoStorageAdapter { // If no objects match, reject with OBJECT_NOT_FOUND. If objects are found and deleted, resolve with undefined. // If there is some other error, reject with INTERNAL_SERVER_ERROR. - // Currently accepts validate for legacy reasons. Currently accepts the schema, that may not actually be necessary. - deleteObjectsByQuery(className, query, validate, schema) { + // Currently accepts the schema, that may not actually be necessary. + deleteObjectsByQuery(className, query, schema) { return this.adaptiveCollection(className) .then(collection => { let mongoWhere = transform.transformWhere(className, query, schema); diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index 0af8fb92..522a2f14 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -368,7 +368,7 @@ DatabaseController.prototype.destroy = function(className, query, { acl } = {}) } throw error; }) - .then(parseFormatSchema => this.adapter.deleteObjectsByQuery(className, query, !this.skipValidation, parseFormatSchema)) + .then(parseFormatSchema => this.adapter.deleteObjectsByQuery(className, query, 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) { From c416cad43fc3eb1e5e5ae139f772a0ed9cb080e7 Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Wed, 18 May 2016 18:59:52 -0700 Subject: [PATCH 9/9] remove extra special keys list --- src/Adapters/Storage/Mongo/MongoStorageAdapter.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index b47c32a6..e194dfe0 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -25,7 +25,6 @@ const storageAdapterAllCollections = mongoAdapter => { }); } -const specialQuerykeys = ['$and', '$or', '_rperm', '_wperm', '_perishable_token', '_email_verify_token']; export class MongoStorageAdapter { // Private _uri: string;