@@ -4,60 +4,56 @@ import * as middleware from '../middlewares';
44import Parse from 'parse/node' ;
55import UsersRouter from './UsersRouter' ;
66
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' ,
1125 'match' ,
26+ 'out' ,
27+ 'project' ,
1228 'redact' ,
13- 'limit' ,
14- 'skip' ,
15- 'unwind' ,
16- 'group' ,
29+ 'replaceRoot' ,
1730 'sample' ,
31+ 'skip' ,
1832 'sort' ,
19- 'geoNear' ,
20- 'lookup' ,
21- 'out' ,
22- 'indexStats' ,
23- 'facet' ,
24- 'bucket' ,
25- 'bucketAuto' ,
2633 'sortByCount' ,
27- 'addFields' ,
28- 'replaceRoot' ,
29- 'count' ,
30- 'graphLookup' ,
34+ 'unwind' ,
3135] ;
3236
37+ const ALLOWED_KEYS = [ ...BASE_KEYS , ...PIPELINE_KEYS ] ;
38+
3339export class AggregateRouter extends ClassesRouter {
3440
3541 handleFind ( req ) {
3642 const body = Object . assign ( req . body , ClassesRouter . JSONFromQuery ( req . query ) ) ;
3743 const options = { } ;
38- const pipeline = [ ] ;
44+ let pipeline = [ ] ;
3945
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 ) ) ;
4355 }
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 ;
6157 }
6258 if ( body . distinct ) {
6359 options . distinct = String ( body . distinct ) ;
@@ -76,6 +72,32 @@ export class AggregateRouter extends ClassesRouter {
7672 } ) ;
7773 }
7874
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+
79101 mountRoutes ( ) {
80102 this . route ( 'GET' , '/aggregate/:className' , middleware . promiseEnforceMasterKeyAccess , req => { return this . handleFind ( req ) ; } ) ;
81103 }
0 commit comments