@@ -282,14 +282,18 @@ describe('Cloud Code', () => {
282
282
} ) ;
283
283
284
284
describe ( 'beforeFind security with returned objects' , ( ) => {
285
- it ( 'should not expose objects not readable by current user' , async ( ) => {
286
- const userA = new Parse . User ( ) ;
287
- userA . setUsername ( 'userA' ) ;
285
+ let userA ;
286
+ let userB ;
287
+ let secret ;
288
+
289
+ beforeEach ( async ( ) => {
290
+ userA = new Parse . User ( ) ;
291
+ userA . setUsername ( 'userA_' + Date . now ( ) ) ;
288
292
userA . setPassword ( 'passA' ) ;
289
293
await userA . signUp ( ) ;
290
294
291
- const userB = new Parse . User ( ) ;
292
- userB . setUsername ( 'userB' ) ;
295
+ userB = new Parse . User ( ) ;
296
+ userB . setUsername ( 'userB_' + Date . now ( ) ) ;
293
297
userB . setPassword ( 'passB' ) ;
294
298
await userB . signUp ( ) ;
295
299
@@ -300,7 +304,7 @@ describe('Cloud Code', () => {
300
304
acl . setReadAccess ( userB . id , true ) ;
301
305
acl . setWriteAccess ( userB . id , true ) ;
302
306
303
- const secret = new Parse . Object ( 'SecretDoc' ) ;
307
+ secret = new Parse . Object ( 'SecretDoc' ) ;
304
308
secret . set ( 'title' , 'top' ) ;
305
309
secret . set ( 'content' , 'classified' ) ;
306
310
secret . setACL ( acl ) ;
@@ -309,13 +313,37 @@ describe('Cloud Code', () => {
309
313
Parse . Cloud . beforeFind ( 'SecretDoc' , ( ) => {
310
314
return [ secret ] ;
311
315
} ) ;
316
+ } ) ;
312
317
313
- // Query as userA should NOT see the secret
318
+ it ( 'should not expose objects not readable by current user' , async ( ) => {
314
319
const q = new Parse . Query ( 'SecretDoc' ) ;
315
320
const results = await q . find ( { sessionToken : userA . getSessionToken ( ) } ) ;
316
321
expect ( results . length ) . toBe ( 0 ) ;
317
322
} ) ;
318
323
324
+ it ( 'should allow authorized user to see their objects' , async ( ) => {
325
+ const q = new Parse . Query ( 'SecretDoc' ) ;
326
+ const results = await q . find ( { sessionToken : userB . getSessionToken ( ) } ) ;
327
+ expect ( results . length ) . toBe ( 1 ) ;
328
+ expect ( results [ 0 ] . id ) . toBe ( secret . id ) ;
329
+ expect ( results [ 0 ] . get ( 'title' ) ) . toBe ( 'top' ) ;
330
+ expect ( results [ 0 ] . get ( 'content' ) ) . toBe ( 'classified' ) ;
331
+ } ) ;
332
+
333
+ it ( 'should return OBJECT_NOT_FOUND on get() for unauthorized user' , async ( ) => {
334
+ const q = new Parse . Query ( 'SecretDoc' ) ;
335
+ await expectAsync (
336
+ q . get ( secret . id , { sessionToken : userA . getSessionToken ( ) } )
337
+ ) . toBeRejectedWith ( jasmine . objectContaining ( { code : Parse . Error . OBJECT_NOT_FOUND } ) ) ;
338
+ } ) ;
339
+
340
+ it ( 'should allow master key to bypass ACL filtering when returning objects' , async ( ) => {
341
+ const q = new Parse . Query ( 'SecretDoc' ) ;
342
+ const results = await q . find ( { useMasterKey : true } ) ;
343
+ expect ( results . length ) . toBe ( 1 ) ;
344
+ expect ( results [ 0 ] . id ) . toBe ( secret . id ) ;
345
+ } ) ;
346
+
319
347
it ( 'should apply protectedFields masking after re-filtering' , async ( ) => {
320
348
// Configure protectedFields for SecretMask: mask `secretField` for everyone
321
349
const protectedFields = { SecretMask : { '*' : [ 'secretField' ] } } ;
@@ -460,11 +488,15 @@ describe('Cloud Code', () => {
460
488
className ,
461
489
[ mockObject ] ,
462
490
testConfig ,
463
- { limit : 5 , skip : 0 } ,
491
+ { limit : 5 , skip : 1 } ,
464
492
{ }
465
493
) ;
466
494
467
495
expect ( receivedQuery ) . toBeInstanceOf ( Parse . Query ) ;
496
+ const qJSON = receivedQuery . toJSON ( ) ;
497
+ expect ( qJSON . limit ) . toBe ( 5 ) ;
498
+ expect ( qJSON . skip ) . toBe ( 1 ) ;
499
+ expect ( qJSON . where ) . toEqual ( { } ) ;
468
500
expect ( result ) . toBeDefined ( ) ;
469
501
} ) ;
470
502
0 commit comments