@@ -37,6 +37,30 @@ describe('request complexity', () => {
3737 return where ;
3838 }
3939
40+ function buildNestedOrQuery ( depth ) {
41+ let where = { username : 'test' } ;
42+ for ( let i = 0 ; i < depth ; i ++ ) {
43+ where = { $or : [ where , { username : 'test' } ] } ;
44+ }
45+ return where ;
46+ }
47+
48+ function buildNestedAndQuery ( depth ) {
49+ let where = { username : 'test' } ;
50+ for ( let i = 0 ; i < depth ; i ++ ) {
51+ where = { $and : [ where , { username : 'test' } ] } ;
52+ }
53+ return where ;
54+ }
55+
56+ function buildNestedNorQuery ( depth ) {
57+ let where = { username : 'test' } ;
58+ for ( let i = 0 ; i < depth ; i ++ ) {
59+ where = { $nor : [ where , { username : 'test' } ] } ;
60+ }
61+ return where ;
62+ }
63+
4064 describe ( 'config validation' , ( ) => {
4165 it ( 'should accept valid requestComplexity config' , async ( ) => {
4266 await expectAsync (
@@ -45,6 +69,7 @@ describe('request complexity', () => {
4569 includeDepth : 10 ,
4670 includeCount : 100 ,
4771 subqueryDepth : 5 ,
72+ queryDepth : 10 ,
4873 graphQLDepth : 15 ,
4974 graphQLFields : 300 ,
5075 } ,
@@ -59,6 +84,7 @@ describe('request complexity', () => {
5984 includeDepth : - 1 ,
6085 includeCount : - 1 ,
6186 subqueryDepth : - 1 ,
87+ queryDepth : - 1 ,
6288 graphQLDepth : - 1 ,
6389 graphQLFields : - 1 ,
6490 } ,
@@ -112,6 +138,7 @@ describe('request complexity', () => {
112138 expect ( config . requestComplexity . includeDepth ) . toBe ( 3 ) ;
113139 expect ( config . requestComplexity . includeCount ) . toBe ( 50 ) ;
114140 expect ( config . requestComplexity . subqueryDepth ) . toBe ( 5 ) ;
141+ expect ( config . requestComplexity . queryDepth ) . toBe ( 10 ) ;
115142 expect ( config . requestComplexity . graphQLDepth ) . toBe ( 50 ) ;
116143 expect ( config . requestComplexity . graphQLFields ) . toBe ( 200 ) ;
117144 } ) ;
@@ -123,6 +150,7 @@ describe('request complexity', () => {
123150 includeDepth : 5 ,
124151 includeCount : 50 ,
125152 subqueryDepth : 5 ,
153+ queryDepth : 10 ,
126154 graphQLDepth : 50 ,
127155 graphQLFields : 200 ,
128156 } ) ;
@@ -216,6 +244,106 @@ describe('request complexity', () => {
216244 } ) ;
217245 } ) ;
218246
247+ describe ( 'query depth' , ( ) => {
248+ let config ;
249+
250+ beforeEach ( async ( ) => {
251+ await reconfigureServer ( {
252+ requestComplexity : { queryDepth : 3 } ,
253+ } ) ;
254+ config = Config . get ( 'test' ) ;
255+ } ) ;
256+
257+ it ( 'should allow $or within depth limit' , async ( ) => {
258+ const where = buildNestedOrQuery ( 3 ) ;
259+ await expectAsync (
260+ rest . find ( config , auth . nobody ( config ) , '_User' , where )
261+ ) . toBeResolved ( ) ;
262+ } ) ;
263+
264+ it ( 'should reject $or exceeding depth limit' , async ( ) => {
265+ const where = buildNestedOrQuery ( 4 ) ;
266+ await expectAsync (
267+ rest . find ( config , auth . nobody ( config ) , '_User' , where )
268+ ) . toBeRejectedWith (
269+ jasmine . objectContaining ( {
270+ message : jasmine . stringMatching ( / Q u e r y c o n d i t i o n n e s t i n g d e p t h e x c e e d s m a x i m u m a l l o w e d d e p t h o f 3 / ) ,
271+ } )
272+ ) ;
273+ } ) ;
274+
275+ it ( 'should reject $and exceeding depth limit' , async ( ) => {
276+ const where = buildNestedAndQuery ( 4 ) ;
277+ await expectAsync (
278+ rest . find ( config , auth . nobody ( config ) , '_User' , where )
279+ ) . toBeRejectedWith (
280+ jasmine . objectContaining ( {
281+ message : jasmine . stringMatching ( / Q u e r y c o n d i t i o n n e s t i n g d e p t h e x c e e d s m a x i m u m a l l o w e d d e p t h o f 3 / ) ,
282+ } )
283+ ) ;
284+ } ) ;
285+
286+ it ( 'should reject $nor exceeding depth limit' , async ( ) => {
287+ const where = buildNestedNorQuery ( 4 ) ;
288+ await expectAsync (
289+ rest . find ( config , auth . nobody ( config ) , '_User' , where )
290+ ) . toBeRejectedWith (
291+ jasmine . objectContaining ( {
292+ message : jasmine . stringMatching ( / Q u e r y c o n d i t i o n n e s t i n g d e p t h e x c e e d s m a x i m u m a l l o w e d d e p t h o f 3 / ) ,
293+ } )
294+ ) ;
295+ } ) ;
296+
297+ it ( 'should reject mixed nested operators exceeding depth limit' , async ( ) => {
298+ // $or > $and > $nor > $or = depth 4
299+ const where = {
300+ $or : [
301+ {
302+ $and : [
303+ {
304+ $nor : [
305+ { $or : [ { username : 'a' } , { username : 'b' } ] } ,
306+ ] ,
307+ } ,
308+ ] ,
309+ } ,
310+ ] ,
311+ } ;
312+ await expectAsync (
313+ rest . find ( config , auth . nobody ( config ) , '_User' , where )
314+ ) . toBeRejectedWith (
315+ jasmine . objectContaining ( {
316+ message : jasmine . stringMatching ( / Q u e r y c o n d i t i o n n e s t i n g d e p t h e x c e e d s m a x i m u m a l l o w e d d e p t h o f 3 / ) ,
317+ } )
318+ ) ;
319+ } ) ;
320+
321+ it ( 'should allow with master key even when exceeding limit' , async ( ) => {
322+ const where = buildNestedOrQuery ( 4 ) ;
323+ await expectAsync (
324+ rest . find ( config , auth . master ( config ) , '_User' , where )
325+ ) . toBeResolved ( ) ;
326+ } ) ;
327+
328+ it ( 'should allow with maintenance key even when exceeding limit' , async ( ) => {
329+ const where = buildNestedOrQuery ( 4 ) ;
330+ await expectAsync (
331+ rest . find ( config , auth . maintenance ( config ) , '_User' , where )
332+ ) . toBeResolved ( ) ;
333+ } ) ;
334+
335+ it ( 'should allow unlimited when queryDepth is -1' , async ( ) => {
336+ await reconfigureServer ( {
337+ requestComplexity : { queryDepth : - 1 } ,
338+ } ) ;
339+ config = Config . get ( 'test' ) ;
340+ const where = buildNestedOrQuery ( 15 ) ;
341+ await expectAsync (
342+ rest . find ( config , auth . nobody ( config ) , '_User' , where )
343+ ) . toBeResolved ( ) ;
344+ } ) ;
345+ } ) ;
346+
219347 describe ( 'include limits' , ( ) => {
220348 let config ;
221349
0 commit comments