1
- 'use strict' ;
2
-
3
- const { MongoParseError, MongoDriverError, MongoInvalidArgumentError } = require ( '../../src/error' ) ;
4
- const { loadSpecTests } = require ( '../spec' ) ;
5
- const { parseOptions } = require ( '../../src/connection_string' ) ;
6
- const { AuthMechanism } = require ( '../../src/cmap/auth/providers' ) ;
7
- const { expect } = require ( 'chai' ) ;
1
+ import { expect } from 'chai' ;
2
+ import * as dns from 'dns' ;
3
+ import * as sinon from 'sinon' ;
4
+ import { promisify } from 'util' ;
5
+
6
+ import { MongoCredentials } from '../../src/cmap/auth/mongo_credentials' ;
7
+ import { AUTH_MECHS_AUTH_SRC_EXTERNAL , AuthMechanism } from '../../src/cmap/auth/providers' ;
8
+ import { parseOptions , resolveSRVRecord } from '../../src/connection_string' ;
9
+ import { MongoDriverError , MongoInvalidArgumentError , MongoParseError } from '../../src/error' ;
10
+ import { MongoOptions } from '../../src/mongo_client' ;
11
+ import { loadSpecTests } from '../spec' ;
8
12
9
13
// NOTE: These are cases we could never check for unless we write our own
10
14
// url parser. The node parser simply won't let these through, so we
@@ -30,15 +34,17 @@ describe('Connection String', function () {
30
34
auth : { user : 'testing' , password : 'llamas' }
31
35
} ;
32
36
33
- expect ( ( ) => parseOptions ( 'mongodb://localhost' , optionsWithUser ) ) . to . throw ( MongoParseError ) ;
37
+ expect ( ( ) => parseOptions ( 'mongodb://localhost' , optionsWithUser as any ) ) . to . throw (
38
+ MongoParseError
39
+ ) ;
34
40
} ) ;
35
41
36
42
it ( 'should support auth passed with username' , function ( ) {
37
43
const optionsWithUsername = {
38
44
authMechanism : 'SCRAM-SHA-1' ,
39
45
auth : { username : 'testing' , password : 'llamas' }
40
46
} ;
41
- const options = parseOptions ( 'mongodb://localhost' , optionsWithUsername ) ;
47
+ const options = parseOptions ( 'mongodb://localhost' , optionsWithUsername as any ) ;
42
48
expect ( options . credentials ) . to . containSubset ( {
43
49
source : 'admin' ,
44
50
username : 'testing' ,
@@ -94,6 +100,13 @@ describe('Connection String', function () {
94
100
expect ( options . credentials . mechanism ) . to . equal ( AuthMechanism . MONGODB_GSSAPI ) ;
95
101
} ) ;
96
102
103
+ it ( 'should provide default authSource when valid AuthMechanism provided' , function ( ) {
104
+ const options = parseOptions (
105
+ 'mongodb+srv://jira-sync.pw0q4.mongodb.net/testDB?authMechanism=MONGODB-AWS&retryWrites=true&w=majority'
106
+ ) ;
107
+ expect ( options . credentials . source ) . to . equal ( '$external' ) ;
108
+ } ) ;
109
+
97
110
it ( 'should parse a numeric authSource with variable width' , function ( ) {
98
111
const options = parseOptions ( 'mongodb://test@localhost/?authSource=0001' ) ;
99
112
expect ( options . credentials . source ) . to . equal ( '0001' ) ;
@@ -127,7 +140,7 @@ describe('Connection String', function () {
127
140
} ) ;
128
141
129
142
it ( 'does not set the ssl option' , function ( ) {
130
- expect ( options . ssl ) . to . be . undefined ;
143
+ expect ( options ) . to . not . have . property ( 'ssl' ) ;
131
144
} ) ;
132
145
} ) ;
133
146
@@ -139,7 +152,7 @@ describe('Connection String', function () {
139
152
} ) ;
140
153
141
154
it ( 'does not set the ssl option' , function ( ) {
142
- expect ( options . ssl ) . to . be . undefined ;
155
+ expect ( options ) . to . not . have . property ( 'ssl' ) ;
143
156
} ) ;
144
157
} ) ;
145
158
} ) ;
@@ -163,7 +176,7 @@ describe('Connection String', function () {
163
176
} ) ;
164
177
165
178
it ( 'does not set the ssl option' , function ( ) {
166
- expect ( options . ssl ) . to . be . undefined ;
179
+ expect ( options ) . to . not . have . property ( 'ssl' ) ;
167
180
} ) ;
168
181
} ) ;
169
182
@@ -176,7 +189,7 @@ describe('Connection String', function () {
176
189
} ) ;
177
190
178
191
it ( 'does not set the ssl option' , function ( ) {
179
- expect ( options . ssl ) . to . be . undefined ;
192
+ expect ( options ) . to . not . have . property ( 'ssl' ) ;
180
193
} ) ;
181
194
} ) ;
182
195
@@ -188,7 +201,7 @@ describe('Connection String', function () {
188
201
} ) ;
189
202
190
203
it ( 'does not set the ssl option' , function ( ) {
191
- expect ( options . ssl ) . to . be . undefined ;
204
+ expect ( options ) . to . not . have . property ( 'ssl' ) ;
192
205
} ) ;
193
206
} ) ;
194
207
} ) ;
@@ -312,4 +325,110 @@ describe('Connection String', function () {
312
325
expect ( options . srvHost ) . to . equal ( 'test1.test.build.10gen.cc' ) ;
313
326
} ) ;
314
327
} ) ;
328
+
329
+ describe ( 'resolveSRVRecord()' , ( ) => {
330
+ const resolveSRVRecordAsync = promisify ( resolveSRVRecord ) ;
331
+
332
+ afterEach ( async ( ) => {
333
+ sinon . restore ( ) ;
334
+ } ) ;
335
+
336
+ function makeStub ( txtRecord : string ) {
337
+ const mockAddress = [
338
+ {
339
+ name : 'localhost.test.mock.test.build.10gen.cc' ,
340
+ port : 2017 ,
341
+ weight : 0 ,
342
+ priority : 0
343
+ }
344
+ ] ;
345
+
346
+ const mockRecord : string [ ] [ ] = [ [ txtRecord ] ] ;
347
+
348
+ // first call is for stubbing resolveSrv
349
+ // second call is for stubbing resolveTxt
350
+ sinon . stub ( dns , 'resolveSrv' ) . callsFake ( ( address , callback ) => {
351
+ return process . nextTick ( callback , null , mockAddress ) ;
352
+ } ) ;
353
+
354
+ sinon . stub ( dns , 'resolveTxt' ) . callsFake ( ( address , whatWeTest ) => {
355
+ whatWeTest ( null , mockRecord ) ;
356
+ } ) ;
357
+ }
358
+
359
+ for ( const mechanism of AUTH_MECHS_AUTH_SRC_EXTERNAL ) {
360
+ it ( `should set authSource to $external for ${ mechanism } external mechanism` , async function ( ) {
361
+ makeStub ( 'authSource=thisShouldNotBeAuthSource' ) ;
362
+ const credentials = new MongoCredentials ( {
363
+ source : '$external' ,
364
+ mechanism,
365
+ username : 'username' ,
366
+ password : mechanism === AuthMechanism . MONGODB_X509 ? undefined : 'password' ,
367
+ mechanismProperties : { }
368
+ } ) ;
369
+ credentials . validate ( ) ;
370
+
371
+ const options = {
372
+ credentials,
373
+ srvHost : 'test.mock.test.build.10gen.cc' ,
374
+ srvServiceName : 'mongodb' ,
375
+ userSpecifiedAuthSource : false
376
+ } as MongoOptions ;
377
+
378
+ await resolveSRVRecordAsync ( options ) ;
379
+ // check MongoCredentials instance (i.e. whether or not merge on options.credentials was called)
380
+ expect ( options ) . property ( 'credentials' ) . to . equal ( credentials ) ;
381
+ expect ( options ) . to . have . nested . property ( 'credentials.source' , '$external' ) ;
382
+ } ) ;
383
+ }
384
+
385
+ it ( 'should set a default authSource for non-external mechanisms with no user-specified source' , async function ( ) {
386
+ makeStub ( 'authSource=thisShouldBeAuthSource' ) ;
387
+
388
+ const credentials = new MongoCredentials ( {
389
+ source : 'admin' ,
390
+ mechanism : AuthMechanism . MONGODB_SCRAM_SHA256 ,
391
+ username : 'username' ,
392
+ password : 'password' ,
393
+ mechanismProperties : { }
394
+ } ) ;
395
+ credentials . validate ( ) ;
396
+
397
+ const options = {
398
+ credentials,
399
+ srvHost : 'test.mock.test.build.10gen.cc' ,
400
+ srvServiceName : 'mongodb' ,
401
+ userSpecifiedAuthSource : false
402
+ } as MongoOptions ;
403
+
404
+ await resolveSRVRecordAsync ( options ) ;
405
+ // check MongoCredentials instance (i.e. whether or not merge on options.credentials was called)
406
+ expect ( options ) . property ( 'credentials' ) . to . not . equal ( credentials ) ;
407
+ expect ( options ) . to . have . nested . property ( 'credentials.source' , 'thisShouldBeAuthSource' ) ;
408
+ } ) ;
409
+
410
+ it ( 'should retain credentials for any mechanism with no user-sepcificed source and no source in DNS' , async function ( ) {
411
+ makeStub ( '' ) ;
412
+ const credentials = new MongoCredentials ( {
413
+ source : 'admin' ,
414
+ mechanism : AuthMechanism . MONGODB_SCRAM_SHA256 ,
415
+ username : 'username' ,
416
+ password : 'password' ,
417
+ mechanismProperties : { }
418
+ } ) ;
419
+ credentials . validate ( ) ;
420
+
421
+ const options = {
422
+ credentials,
423
+ srvHost : 'test.mock.test.build.10gen.cc' ,
424
+ srvServiceName : 'mongodb' ,
425
+ userSpecifiedAuthSource : false
426
+ } as MongoOptions ;
427
+
428
+ await resolveSRVRecordAsync ( options as any ) ;
429
+ // check MongoCredentials instance (i.e. whether or not merge on options.credentials was called)
430
+ expect ( options ) . property ( 'credentials' ) . to . equal ( credentials ) ;
431
+ expect ( options ) . to . have . nested . property ( 'credentials.source' , 'admin' ) ;
432
+ } ) ;
433
+ } ) ;
315
434
} ) ;
0 commit comments