@@ -4,60 +4,56 @@ import * as middleware from '../middlewares';
4
4
import Parse from 'parse/node' ;
5
5
import UsersRouter from './UsersRouter' ;
6
6
7
- const ALLOWED_KEYS = [
8
- 'where' ,
9
- 'distinct' ,
10
- 'project' ,
7
+ const BASE_KEYS = [ 'where' , 'distinct' ] ;
8
+
9
+ const PIPELINE_KEYS = [
10
+ 'addFields' ,
11
+ 'bucket' ,
12
+ 'bucketAuto' ,
13
+ 'collStats' ,
14
+ 'count' ,
15
+ 'currentOp' ,
16
+ 'facet' ,
17
+ 'geoNear' ,
18
+ 'graphLookup' ,
19
+ 'group' ,
20
+ 'indexStats' ,
21
+ 'limit' ,
22
+ 'listLocalSessions' ,
23
+ 'listSessions' ,
24
+ 'lookup' ,
11
25
'match' ,
26
+ 'out' ,
27
+ 'project' ,
12
28
'redact' ,
13
- 'limit' ,
14
- 'skip' ,
15
- 'unwind' ,
16
- 'group' ,
29
+ 'replaceRoot' ,
17
30
'sample' ,
31
+ 'skip' ,
18
32
'sort' ,
19
- 'geoNear' ,
20
- 'lookup' ,
21
- 'out' ,
22
- 'indexStats' ,
23
- 'facet' ,
24
- 'bucket' ,
25
- 'bucketAuto' ,
26
33
'sortByCount' ,
27
- 'addFields' ,
28
- 'replaceRoot' ,
29
- 'count' ,
30
- 'graphLookup' ,
34
+ 'unwind' ,
31
35
] ;
32
36
37
+ const ALLOWED_KEYS = [ ...BASE_KEYS , ...PIPELINE_KEYS ] ;
38
+
33
39
export class AggregateRouter extends ClassesRouter {
34
40
35
41
handleFind ( req ) {
36
42
const body = Object . assign ( req . body , ClassesRouter . JSONFromQuery ( req . query ) ) ;
37
43
const options = { } ;
38
- const pipeline = [ ] ;
44
+ let pipeline = [ ] ;
39
45
40
- for ( const key in body ) {
41
- if ( ALLOWED_KEYS . indexOf ( key ) === - 1 ) {
42
- throw new Parse . Error ( Parse . Error . INVALID_QUERY , `Invalid parameter for query: ${ key } ` ) ;
46
+ if ( Array . isArray ( body ) ) {
47
+ pipeline = body . map ( ( stage ) => {
48
+ const stageName = Object . keys ( stage ) [ 0 ] ;
49
+ return this . transformStage ( stageName , stage ) ;
50
+ } ) ;
51
+ } else {
52
+ const stages = [ ] ;
53
+ for ( const stageName in body ) {
54
+ stages . push ( this . transformStage ( stageName , body ) ) ;
43
55
}
44
- if ( key === 'group' ) {
45
- if ( body [ key ] . hasOwnProperty ( '_id' ) ) {
46
- throw new Parse . Error (
47
- Parse . Error . INVALID_QUERY ,
48
- `Invalid parameter for query: group. Please use objectId instead of _id`
49
- ) ;
50
- }
51
- if ( ! body [ key ] . hasOwnProperty ( 'objectId' ) ) {
52
- throw new Parse . Error (
53
- Parse . Error . INVALID_QUERY ,
54
- `Invalid parameter for query: group. objectId is required`
55
- ) ;
56
- }
57
- body [ key ] . _id = body [ key ] . objectId ;
58
- delete body [ key ] . objectId ;
59
- }
60
- pipeline . push ( { [ `$${ key } ` ] : body [ key ] } ) ;
56
+ pipeline = stages ;
61
57
}
62
58
if ( body . distinct ) {
63
59
options . distinct = String ( body . distinct ) ;
@@ -76,6 +72,32 @@ export class AggregateRouter extends ClassesRouter {
76
72
} ) ;
77
73
}
78
74
75
+ transformStage ( stageName , stage ) {
76
+ if ( ALLOWED_KEYS . indexOf ( stageName ) === - 1 ) {
77
+ throw new Parse . Error (
78
+ Parse . Error . INVALID_QUERY ,
79
+ `Invalid parameter for query: ${ stageName } `
80
+ ) ;
81
+ }
82
+ if ( stageName === 'group' ) {
83
+ if ( stage [ stageName ] . hasOwnProperty ( '_id' ) ) {
84
+ throw new Parse . Error (
85
+ Parse . Error . INVALID_QUERY ,
86
+ `Invalid parameter for query: group. Please use objectId instead of _id`
87
+ ) ;
88
+ }
89
+ if ( ! stage [ stageName ] . hasOwnProperty ( 'objectId' ) ) {
90
+ throw new Parse . Error (
91
+ Parse . Error . INVALID_QUERY ,
92
+ `Invalid parameter for query: group. objectId is required`
93
+ ) ;
94
+ }
95
+ stage [ stageName ] . _id = stage [ stageName ] . objectId ;
96
+ delete stage [ stageName ] . objectId ;
97
+ }
98
+ return { [ `$${ stageName } ` ] : stage [ stageName ] } ;
99
+ }
100
+
79
101
mountRoutes ( ) {
80
102
this . route ( 'GET' , '/aggregate/:className' , middleware . promiseEnforceMasterKeyAccess , req => { return this . handleFind ( req ) ; } ) ;
81
103
}
0 commit comments