1
+ const Config = require ( '../lib/Config' ) ;
1
2
const DatabaseController = require ( '../lib/Controllers/DatabaseController.js' ) ;
2
3
const validateQuery = DatabaseController . _validateQuery ;
3
4
4
- describe ( 'DatabaseController' , function ( ) {
5
- describe ( 'validateQuery' , function ( ) {
6
- it ( 'should not restructure simple cases of SERVER-13732' , done => {
5
+ describe ( 'DatabaseController' , ( ) => {
6
+ describe ( 'validateQuery' , ( ) => {
7
+ it ( 'should not restructure simple cases of SERVER-13732' , ( ) => {
7
8
const query = {
8
9
$or : [ { a : 1 } , { a : 2 } ] ,
9
10
_rperm : { $in : [ 'a' , 'b' ] } ,
@@ -15,10 +16,9 @@ describe('DatabaseController', function () {
15
16
_rperm : { $in : [ 'a' , 'b' ] } ,
16
17
foo : 3 ,
17
18
} ) ;
18
- done ( ) ;
19
19
} ) ;
20
20
21
- it ( 'should not restructure SERVER-13732 queries with $nears' , done => {
21
+ it ( 'should not restructure SERVER-13732 queries with $nears' , ( ) => {
22
22
let query = { $or : [ { a : 1 } , { b : 1 } ] , c : { $nearSphere : { } } } ;
23
23
validateQuery ( query ) ;
24
24
expect ( query ) . toEqual ( {
@@ -28,10 +28,9 @@ describe('DatabaseController', function () {
28
28
query = { $or : [ { a : 1 } , { b : 1 } ] , c : { $near : { } } } ;
29
29
validateQuery ( query ) ;
30
30
expect ( query ) . toEqual ( { $or : [ { a : 1 } , { b : 1 } ] , c : { $near : { } } } ) ;
31
- done ( ) ;
32
31
} ) ;
33
32
34
- it ( 'should not push refactored keys down a tree for SERVER-13732' , done => {
33
+ it ( 'should not push refactored keys down a tree for SERVER-13732' , ( ) => {
35
34
const query = {
36
35
a : 1 ,
37
36
$or : [ { $or : [ { b : 1 } , { b : 2 } ] } , { $or : [ { c : 1 } , { c : 2 } ] } ] ,
@@ -41,22 +40,18 @@ describe('DatabaseController', function () {
41
40
a : 1 ,
42
41
$or : [ { $or : [ { b : 1 } , { b : 2 } ] } , { $or : [ { c : 1 } , { c : 2 } ] } ] ,
43
42
} ) ;
44
-
45
- done ( ) ;
46
43
} ) ;
47
44
48
- it ( 'should reject invalid queries' , done => {
45
+ it ( 'should reject invalid queries' , ( ) => {
49
46
expect ( ( ) => validateQuery ( { $or : { a : 1 } } ) ) . toThrow ( ) ;
50
- done ( ) ;
51
47
} ) ;
52
48
53
- it ( 'should accept valid queries' , done => {
49
+ it ( 'should accept valid queries' , ( ) => {
54
50
expect ( ( ) => validateQuery ( { $or : [ { a : 1 } , { b : 2 } ] } ) ) . not . toThrow ( ) ;
55
- done ( ) ;
56
51
} ) ;
57
52
} ) ;
58
53
59
- describe ( 'addPointerPermissions' , function ( ) {
54
+ describe ( 'addPointerPermissions' , ( ) => {
60
55
const CLASS_NAME = 'Foo' ;
61
56
const USER_ID = 'userId' ;
62
57
const ACL_GROUP = [ USER_ID ] ;
@@ -69,7 +64,7 @@ describe('DatabaseController', function () {
69
64
'getExpectedType' ,
70
65
] ) ;
71
66
72
- it ( 'should not decorate query if no pointer CLPs are present' , done => {
67
+ it ( 'should not decorate query if no pointer CLPs are present' , ( ) => {
73
68
const clp = buildCLP ( ) ;
74
69
const query = { a : 'b' } ;
75
70
@@ -87,11 +82,9 @@ describe('DatabaseController', function () {
87
82
) ;
88
83
89
84
expect ( output ) . toEqual ( { ...query } ) ;
90
-
91
- done ( ) ;
92
85
} ) ;
93
86
94
- it ( 'should decorate query if a pointer CLP entry is present' , done => {
87
+ it ( 'should decorate query if a pointer CLP entry is present' , ( ) => {
95
88
const clp = buildCLP ( [ 'user' ] ) ;
96
89
const query = { a : 'b' } ;
97
90
@@ -112,11 +105,9 @@ describe('DatabaseController', function () {
112
105
) ;
113
106
114
107
expect ( output ) . toEqual ( { ...query , user : createUserPointer ( USER_ID ) } ) ;
115
-
116
- done ( ) ;
117
108
} ) ;
118
109
119
- it ( 'should decorate query if an array CLP entry is present' , done => {
110
+ it ( 'should decorate query if an array CLP entry is present' , ( ) => {
120
111
const clp = buildCLP ( [ 'users' ] ) ;
121
112
const query = { a : 'b' } ;
122
113
@@ -140,11 +131,9 @@ describe('DatabaseController', function () {
140
131
...query ,
141
132
users : { $all : [ createUserPointer ( USER_ID ) ] } ,
142
133
} ) ;
143
-
144
- done ( ) ;
145
134
} ) ;
146
135
147
- it ( 'should decorate query if an object CLP entry is present' , done => {
136
+ it ( 'should decorate query if an object CLP entry is present' , ( ) => {
148
137
const clp = buildCLP ( [ 'user' ] ) ;
149
138
const query = { a : 'b' } ;
150
139
@@ -168,11 +157,9 @@ describe('DatabaseController', function () {
168
157
...query ,
169
158
user : createUserPointer ( USER_ID ) ,
170
159
} ) ;
171
-
172
- done ( ) ;
173
160
} ) ;
174
161
175
- it ( 'should decorate query if a pointer CLP is present and the same field is part of the query' , done => {
162
+ it ( 'should decorate query if a pointer CLP is present and the same field is part of the query' , ( ) => {
176
163
const clp = buildCLP ( [ 'user' ] ) ;
177
164
const query = { a : 'b' , user : 'a' } ;
178
165
@@ -195,11 +182,9 @@ describe('DatabaseController', function () {
195
182
expect ( output ) . toEqual ( {
196
183
$and : [ { user : createUserPointer ( USER_ID ) } , { ...query } ] ,
197
184
} ) ;
198
-
199
- done ( ) ;
200
185
} ) ;
201
186
202
- it ( 'should transform the query to an $or query if multiple array/pointer CLPs are present' , done => {
187
+ it ( 'should transform the query to an $or query if multiple array/pointer CLPs are present' , ( ) => {
203
188
const clp = buildCLP ( [ 'user' , 'users' , 'userObject' ] ) ;
204
189
const query = { a : 'b' } ;
205
190
@@ -232,11 +217,9 @@ describe('DatabaseController', function () {
232
217
{ ...query , userObject : createUserPointer ( USER_ID ) } ,
233
218
] ,
234
219
} ) ;
235
-
236
- done ( ) ;
237
220
} ) ;
238
221
239
- it ( 'should not return a $or operation if the query involves one of the two fields also used as array/pointer permissions' , done => {
222
+ it ( 'should not return a $or operation if the query involves one of the two fields also used as array/pointer permissions' , ( ) => {
240
223
const clp = buildCLP ( [ 'users' , 'user' ] ) ;
241
224
const query = { a : 'b' , user : createUserPointer ( USER_ID ) } ;
242
225
schemaController . testPermissionsForClassName
@@ -257,10 +240,9 @@ describe('DatabaseController', function () {
257
240
ACL_GROUP
258
241
) ;
259
242
expect ( output ) . toEqual ( { ...query , user : createUserPointer ( USER_ID ) } ) ;
260
- done ( ) ;
261
243
} ) ;
262
244
263
- it ( 'should not return a $or operation if the query involves one of the fields also used as array/pointer permissions' , done => {
245
+ it ( 'should not return a $or operation if the query involves one of the fields also used as array/pointer permissions' , ( ) => {
264
246
const clp = buildCLP ( [ 'user' , 'users' , 'userObject' ] ) ;
265
247
const query = { a : 'b' , user : createUserPointer ( USER_ID ) } ;
266
248
schemaController . testPermissionsForClassName
@@ -284,10 +266,9 @@ describe('DatabaseController', function () {
284
266
ACL_GROUP
285
267
) ;
286
268
expect ( output ) . toEqual ( { ...query , user : createUserPointer ( USER_ID ) } ) ;
287
- done ( ) ;
288
269
} ) ;
289
270
290
- it ( 'should throw an error if for some unexpected reason the property specified in the CLP is neither a pointer nor an array' , done => {
271
+ it ( 'should throw an error if for some unexpected reason the property specified in the CLP is neither a pointer nor an array' , ( ) => {
291
272
const clp = buildCLP ( [ 'user' ] ) ;
292
273
const query = { a : 'b' } ;
293
274
@@ -312,21 +293,18 @@ describe('DatabaseController', function () {
312
293
`An unexpected condition occurred when resolving pointer permissions: ${ CLASS_NAME } user`
313
294
)
314
295
) ;
315
-
316
- done ( ) ;
317
296
} ) ;
318
297
} ) ;
319
298
320
299
describe ( 'reduceOperations' , function ( ) {
321
300
const databaseController = new DatabaseController ( ) ;
322
301
323
- it ( 'objectToEntriesStrings' , done => {
302
+ it ( 'objectToEntriesStrings' , ( ) => {
324
303
const output = databaseController . objectToEntriesStrings ( { a : 1 , b : 2 , c : 3 } ) ;
325
304
expect ( output ) . toEqual ( [ '"a":1' , '"b":2' , '"c":3' ] ) ;
326
- done ( ) ;
327
305
} ) ;
328
306
329
- it ( 'reduceOrOperation' , done => {
307
+ it ( 'reduceOrOperation' , ( ) => {
330
308
expect ( databaseController . reduceOrOperation ( { a : 1 } ) ) . toEqual ( { a : 1 } ) ;
331
309
expect ( databaseController . reduceOrOperation ( { $or : [ { a : 1 } , { b : 2 } ] } ) ) . toEqual ( {
332
310
$or : [ { a : 1 } , { b : 2 } ] ,
@@ -341,10 +319,9 @@ describe('DatabaseController', function () {
341
319
expect (
342
320
databaseController . reduceOrOperation ( { $or : [ { b : 2 } , { a : 1 , b : 2 , c : 3 } ] } )
343
321
) . toEqual ( { b : 2 } ) ;
344
- done ( ) ;
345
322
} ) ;
346
323
347
- it ( 'reduceAndOperation' , done => {
324
+ it ( 'reduceAndOperation' , ( ) => {
348
325
expect ( databaseController . reduceAndOperation ( { a : 1 } ) ) . toEqual ( { a : 1 } ) ;
349
326
expect ( databaseController . reduceAndOperation ( { $and : [ { a : 1 } , { b : 2 } ] } ) ) . toEqual ( {
350
327
$and : [ { a : 1 } , { b : 2 } ] ,
@@ -358,7 +335,182 @@ describe('DatabaseController', function () {
358
335
expect (
359
336
databaseController . reduceAndOperation ( { $and : [ { a : 1 , b : 2 , c : 3 } , { b : 2 } ] } )
360
337
) . toEqual ( { a : 1 , b : 2 , c : 3 } ) ;
361
- done ( ) ;
338
+ } ) ;
339
+ } ) ;
340
+
341
+ describe ( 'disableCaseInsensitivity' , ( ) => {
342
+ const dummyStorageAdapter = {
343
+ find : ( ) => Promise . resolve ( [ ] ) ,
344
+ watch : ( ) => Promise . resolve ( ) ,
345
+ getAllClasses : ( ) => Promise . resolve ( [ ] ) ,
346
+ } ;
347
+
348
+ beforeEach ( ( ) => {
349
+ Config . get ( Parse . applicationId ) . schemaCache . clear ( ) ;
350
+ } ) ;
351
+
352
+ it ( 'should force caseInsensitive to false with disableCaseInsensitivity option' , async ( ) => {
353
+ const databaseController = new DatabaseController ( dummyStorageAdapter , {
354
+ disableCaseInsensitivity : true ,
355
+ } ) ;
356
+ const spy = spyOn ( dummyStorageAdapter , 'find' ) ;
357
+ spy . and . callThrough ( ) ;
358
+ await databaseController . find ( 'SomeClass' , { } , { caseInsensitive : true } ) ;
359
+ expect ( spy . calls . all ( ) [ 0 ] . args [ 3 ] . caseInsensitive ) . toEqual ( false ) ;
360
+ } ) ;
361
+
362
+ it ( 'should support caseInsensitive without disableCaseInsensitivity option' , async ( ) => {
363
+ const databaseController = new DatabaseController ( dummyStorageAdapter , { } ) ;
364
+ const spy = spyOn ( dummyStorageAdapter , 'find' ) ;
365
+ spy . and . callThrough ( ) ;
366
+ await databaseController . find ( '_User' , { } , { caseInsensitive : true } ) ;
367
+ expect ( spy . calls . all ( ) [ 0 ] . args [ 3 ] . caseInsensitive ) . toEqual ( true ) ;
368
+ } ) ;
369
+
370
+ it ( 'should create insensitive indexes without disableCaseInsensitivity' , async ( ) => {
371
+ await reconfigureServer ( {
372
+ databaseURI : 'mongodb://localhost:27017/disableCaseInsensitivityFalse' ,
373
+ databaseAdapter : undefined ,
374
+ } ) ;
375
+ const user = new Parse . User ( ) ;
376
+ await user . save ( { username :
'example' , password :
'password' , email :
'[email protected] ' } ) ;
377
+ const schemas = await Parse . Schema . all ( ) ;
378
+ const UserSchema = schemas . find ( ( { className } ) => className === '_User' ) ;
379
+ expect ( UserSchema . indexes ) . toEqual ( {
380
+ _id_ : { _id : 1 } ,
381
+ username_1 : { username : 1 } ,
382
+ case_insensitive_username : { username : 1 } ,
383
+ case_insensitive_email : { email : 1 } ,
384
+ email_1 : { email : 1 } ,
385
+ } ) ;
386
+ } ) ;
387
+
388
+ it ( 'should not create insensitive indexes with disableCaseInsensitivity' , async ( ) => {
389
+ await reconfigureServer ( {
390
+ disableCaseInsensitivity : true ,
391
+ databaseURI : 'mongodb://localhost:27017/disableCaseInsensitivityTrue' ,
392
+ databaseAdapter : undefined ,
393
+ } ) ;
394
+ const user = new Parse . User ( ) ;
395
+ await user . save ( { username :
'example' , password :
'password' , email :
'[email protected] ' } ) ;
396
+ const schemas = await Parse . Schema . all ( ) ;
397
+ const UserSchema = schemas . find ( ( { className } ) => className === '_User' ) ;
398
+ expect ( UserSchema . indexes ) . toEqual ( {
399
+ _id_ : { _id : 1 } ,
400
+ username_1 : { username : 1 } ,
401
+ email_1 : { email : 1 } ,
402
+ } ) ;
403
+ } ) ;
404
+ } ) ;
405
+
406
+ describe ( 'forceEmailAndUsernameToLowerCase' , ( ) => {
407
+ const dummyStorageAdapter = {
408
+ createObject : ( ) => Promise . resolve ( { ops : [ { } ] } ) ,
409
+ findOneAndUpdate : ( ) => Promise . resolve ( { } ) ,
410
+ watch : ( ) => Promise . resolve ( ) ,
411
+ getAllClasses : ( ) =>
412
+ Promise . resolve ( [
413
+ {
414
+ className : '_User' ,
415
+ fields : { username : 'String' , email : 'String' } ,
416
+ indexes : { } ,
417
+ classLevelPermissions : { protectedFields : { } } ,
418
+ } ,
419
+ ] ) ,
420
+ } ;
421
+ const dates = {
422
+ createdAt : { iso : undefined , __type : 'Date' } ,
423
+ updatedAt : { iso : undefined , __type : 'Date' } ,
424
+ } ;
425
+
426
+ it ( 'should not force email and username to lower case without forceEmailAndUsernameToLowerCase option on create' , async ( ) => {
427
+ const databaseController = new DatabaseController ( dummyStorageAdapter , { } ) ;
428
+ const spy = spyOn ( dummyStorageAdapter , 'createObject' ) ;
429
+ spy . and . callThrough ( ) ;
430
+ await databaseController . create ( '_User' , {
431
+ username : 'EXAMPLE' ,
432
+
433
+ } ) ;
434
+ expect ( spy . calls . all ( ) [ 0 ] . args [ 2 ] ) . toEqual ( {
435
+ username : 'EXAMPLE' ,
436
+
437
+ ...dates ,
438
+ } ) ;
439
+ } ) ;
440
+
441
+ it ( 'should force email and username to lower case with forceEmailAndUsernameToLowerCase option on create' , async ( ) => {
442
+ const databaseController = new DatabaseController ( dummyStorageAdapter , {
443
+ forceEmailAndUsernameToLowerCase : true ,
444
+ } ) ;
445
+ const spy = spyOn ( dummyStorageAdapter , 'createObject' ) ;
446
+ spy . and . callThrough ( ) ;
447
+ await databaseController . create ( '_User' , {
448
+ username : 'EXAMPLE' ,
449
+
450
+ } ) ;
451
+ expect ( spy . calls . all ( ) [ 0 ] . args [ 2 ] ) . toEqual ( {
452
+ username : 'example' ,
453
+
454
+ ...dates ,
455
+ } ) ;
456
+ } ) ;
457
+
458
+ it ( 'should not force email and username to lower case without forceEmailAndUsernameToLowerCase option on update' , async ( ) => {
459
+ const databaseController = new DatabaseController ( dummyStorageAdapter , { } ) ;
460
+ const spy = spyOn ( dummyStorageAdapter , 'findOneAndUpdate' ) ;
461
+ spy . and . callThrough ( ) ;
462
+ await databaseController . update (
463
+ '_User' ,
464
+ { id : 'example' } ,
465
+ { username :
'EXAMPLE' , email :
'[email protected] ' }
466
+ ) ;
467
+ expect ( spy . calls . all ( ) [ 0 ] . args [ 3 ] ) . toEqual ( {
468
+ username : 'EXAMPLE' ,
469
+
470
+ } ) ;
471
+ } ) ;
472
+
473
+ it ( 'should force email and username to lower case with forceEmailAndUsernameToLowerCase option on update' , async ( ) => {
474
+ const databaseController = new DatabaseController ( dummyStorageAdapter , {
475
+ forceEmailAndUsernameToLowerCase : true ,
476
+ } ) ;
477
+ const spy = spyOn ( dummyStorageAdapter , 'findOneAndUpdate' ) ;
478
+ spy . and . callThrough ( ) ;
479
+ await databaseController . update (
480
+ '_User' ,
481
+ { id : 'example' } ,
482
+ { username :
'EXAMPLE' , email :
'[email protected] ' }
483
+ ) ;
484
+ expect ( spy . calls . all ( ) [ 0 ] . args [ 3 ] ) . toEqual ( {
485
+ username : 'example' ,
486
+
487
+ } ) ;
488
+ } ) ;
489
+
490
+ it ( 'should not find a case insensitive user by username or email with forceEmailAndUsernameToLowerCase' , async ( ) => {
491
+ await reconfigureServer ( { forceEmailAndUsernameToLowerCase : true } ) ;
492
+ const user = new Parse . User ( ) ;
493
+ await user . save ( { username :
'EXAMPLE' , email :
'[email protected] ' , password :
'password' } ) ;
494
+
495
+ const query = new Parse . Query ( Parse . User ) ;
496
+ query . equalTo ( 'username' , 'EXAMPLE' ) ;
497
+ const result = await query . find ( ) ;
498
+ expect ( result . length ) . toEqual ( 0 ) ;
499
+
500
+ const query2 = new Parse . Query ( Parse . User ) ;
501
+ query2 . equalTo ( 'email' , '[email protected] ' ) ;
502
+ const result2 = await query2 . find ( ) ;
503
+ expect ( result2 . length ) . toEqual ( 0 ) ;
504
+
505
+ const query3 = new Parse . Query ( Parse . User ) ;
506
+ query3 . equalTo ( 'username' , 'example' ) ;
507
+ const result3 = await query3 . find ( ) ;
508
+ expect ( result3 . length ) . toEqual ( 1 ) ;
509
+
510
+ const query4 = new Parse . Query ( Parse . User ) ;
511
+ query4 . equalTo ( 'email' , '[email protected] ' ) ;
512
+ const result4 = await query4 . find ( ) ;
513
+ expect ( result4 . length ) . toEqual ( 1 ) ;
362
514
} ) ;
363
515
} ) ;
364
516
} ) ;
0 commit comments