@@ -24,6 +24,35 @@ function addReadACL(query, acl) {
24
24
return newQuery ;
25
25
}
26
26
27
+ const specialQuerykeys = [ '$and' , '$or' , '_rperm' , '_wperm' , '_perishable_token' , '_email_verify_token' ] ;
28
+ const validateQuery = query => {
29
+ if ( query . ACL ) {
30
+ throw new Parse . Error ( Parse . Error . INVALID_QUERY , 'Cannot query on ACL.' ) ;
31
+ }
32
+
33
+ if ( query . $or ) {
34
+ if ( query . $or instanceof Array ) {
35
+ query . $or . forEach ( validateQuery ) ;
36
+ } else {
37
+ throw new Parse . Error ( Parse . Error . INVALID_QUERY , 'Bad $or format - use an array value.' ) ;
38
+ }
39
+ }
40
+
41
+ if ( query . $and ) {
42
+ if ( query . $and instanceof Array ) {
43
+ query . $and . forEach ( validateQuery ) ;
44
+ } else {
45
+ throw new Parse . Error ( Parse . Error . INVALID_QUERY , 'Bad $and format - use an array value.' ) ;
46
+ }
47
+ }
48
+
49
+ Object . keys ( query ) . forEach ( key => {
50
+ if ( ! specialQuerykeys . includes ( key ) && ! key . match ( / ^ [ a - z A - Z ] [ a - z A - Z 0 - 9 _ \. ] * $ / ) ) {
51
+ throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME , `Invalid key name: ${ key } ` ) ;
52
+ }
53
+ } ) ;
54
+ }
55
+
27
56
function DatabaseController ( adapter , { skipValidation } = { } ) {
28
57
this . adapter = adapter ;
29
58
@@ -174,6 +203,7 @@ DatabaseController.prototype.update = function(className, query, update, {
174
203
if ( acl ) {
175
204
query = addWriteACL ( query , acl ) ;
176
205
}
206
+ validateQuery ( query ) ;
177
207
return schemaController . getOneSchema ( className )
178
208
. catch ( error => {
179
209
// If the schema doesn't exist, pretend it exists with no fields. This behaviour
@@ -184,7 +214,7 @@ DatabaseController.prototype.update = function(className, query, update, {
184
214
throw error ;
185
215
} )
186
216
. then ( parseFormatSchema => {
187
- var mongoWhere = this . transform . transformWhere ( className , query , { validate : ! this . skipValidation } , parseFormatSchema ) ;
217
+ var mongoWhere = this . transform . transformWhere ( className , query , parseFormatSchema ) ;
188
218
mongoUpdate = this . transform . transformUpdate (
189
219
schemaController ,
190
220
className ,
@@ -328,6 +358,7 @@ DatabaseController.prototype.destroy = function(className, query, { acl } = {})
328
358
if ( acl ) {
329
359
query = addWriteACL ( query , acl ) ;
330
360
}
361
+ validateQuery ( query ) ;
331
362
return schemaController . getOneSchema ( className )
332
363
. catch ( error => {
333
364
// If the schema doesn't exist, pretend it exists with no fields. This behaviour
@@ -337,7 +368,7 @@ DatabaseController.prototype.destroy = function(className, query, { acl } = {})
337
368
}
338
369
throw error ;
339
370
} )
340
- . then ( parseFormatSchema => this . adapter . deleteObjectsByQuery ( className , query , ! this . skipValidation , parseFormatSchema ) )
371
+ . then ( parseFormatSchema => this . adapter . deleteObjectsByQuery ( className , query , parseFormatSchema ) )
341
372
. catch ( error => {
342
373
// When deleting sessions while changing passwords, don't throw an error if they don't have any sessions.
343
374
if ( className === "_Session" && error . code === Parse . Error . OBJECT_NOT_FOUND ) {
@@ -668,7 +699,8 @@ DatabaseController.prototype.find = function(className, query, {
668
699
if ( ! isMaster ) {
669
700
query = addReadACL ( query , aclGroup ) ;
670
701
}
671
- let mongoWhere = this . transform . transformWhere ( className , query , { } , schema ) ;
702
+ validateQuery ( query ) ;
703
+ let mongoWhere = this . transform . transformWhere ( className , query , schema ) ;
672
704
if ( count ) {
673
705
delete mongoOptions . limit ;
674
706
return collection . count ( mongoWhere , mongoOptions ) ;
0 commit comments