mongodb 3.2.5 → 3.3.0-beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/HISTORY.md +0 -10
  2. package/index.js +4 -4
  3. package/lib/admin.js +56 -56
  4. package/lib/aggregation_cursor.js +7 -3
  5. package/lib/bulk/common.js +18 -13
  6. package/lib/change_stream.js +196 -89
  7. package/lib/collection.js +217 -169
  8. package/lib/command_cursor.js +17 -7
  9. package/lib/core/auth/auth_provider.js +158 -0
  10. package/lib/core/auth/defaultAuthProviders.js +29 -0
  11. package/lib/core/auth/gssapi.js +241 -0
  12. package/lib/core/auth/mongo_credentials.js +81 -0
  13. package/lib/core/auth/mongocr.js +51 -0
  14. package/lib/core/auth/plain.js +35 -0
  15. package/lib/core/auth/scram.js +293 -0
  16. package/lib/core/auth/sspi.js +131 -0
  17. package/lib/core/auth/x509.js +26 -0
  18. package/lib/core/connection/apm.js +236 -0
  19. package/lib/core/connection/command_result.js +36 -0
  20. package/lib/core/connection/commands.js +507 -0
  21. package/lib/core/connection/connect.js +370 -0
  22. package/lib/core/connection/connection.js +624 -0
  23. package/lib/core/connection/logger.js +246 -0
  24. package/lib/core/connection/msg.js +219 -0
  25. package/lib/core/connection/pool.js +1285 -0
  26. package/lib/core/connection/utils.js +57 -0
  27. package/lib/core/cursor.js +752 -0
  28. package/lib/core/error.js +186 -0
  29. package/lib/core/index.js +50 -0
  30. package/lib/core/sdam/monitoring.js +228 -0
  31. package/lib/core/sdam/server.js +467 -0
  32. package/lib/core/sdam/server_description.js +163 -0
  33. package/lib/core/sdam/server_selectors.js +244 -0
  34. package/lib/core/sdam/srv_polling.js +135 -0
  35. package/lib/core/sdam/topology.js +1151 -0
  36. package/lib/core/sdam/topology_description.js +408 -0
  37. package/lib/core/sessions.js +711 -0
  38. package/lib/core/tools/smoke_plugin.js +61 -0
  39. package/lib/core/topologies/mongos.js +1337 -0
  40. package/lib/core/topologies/read_preference.js +202 -0
  41. package/lib/core/topologies/replset.js +1507 -0
  42. package/lib/core/topologies/replset_state.js +1121 -0
  43. package/lib/core/topologies/server.js +984 -0
  44. package/lib/core/topologies/shared.js +453 -0
  45. package/lib/core/transactions.js +167 -0
  46. package/lib/core/uri_parser.js +631 -0
  47. package/lib/core/utils.js +165 -0
  48. package/lib/core/wireprotocol/command.js +170 -0
  49. package/lib/core/wireprotocol/compression.js +73 -0
  50. package/lib/core/wireprotocol/constants.js +13 -0
  51. package/lib/core/wireprotocol/get_more.js +86 -0
  52. package/lib/core/wireprotocol/index.js +18 -0
  53. package/lib/core/wireprotocol/kill_cursors.js +70 -0
  54. package/lib/core/wireprotocol/query.js +224 -0
  55. package/lib/core/wireprotocol/shared.js +115 -0
  56. package/lib/core/wireprotocol/write_command.js +50 -0
  57. package/lib/cursor.js +40 -46
  58. package/lib/db.js +141 -95
  59. package/lib/dynamic_loaders.js +32 -0
  60. package/lib/error.js +12 -10
  61. package/lib/gridfs/chunk.js +2 -2
  62. package/lib/gridfs/grid_store.js +31 -25
  63. package/lib/gridfs-stream/index.js +4 -4
  64. package/lib/gridfs-stream/upload.js +1 -1
  65. package/lib/mongo_client.js +37 -15
  66. package/lib/operations/add_user.js +96 -0
  67. package/lib/operations/aggregate.js +24 -13
  68. package/lib/operations/aggregate_operation.js +127 -0
  69. package/lib/operations/bulk_write.js +104 -0
  70. package/lib/operations/close.js +47 -0
  71. package/lib/operations/collection_ops.js +28 -287
  72. package/lib/operations/collections.js +55 -0
  73. package/lib/operations/command.js +120 -0
  74. package/lib/operations/command_v2.js +43 -0
  75. package/lib/operations/common_functions.js +372 -0
  76. package/lib/operations/{mongo_client_ops.js → connect.js} +185 -157
  77. package/lib/operations/count.js +72 -0
  78. package/lib/operations/count_documents.js +46 -0
  79. package/lib/operations/create_collection.js +118 -0
  80. package/lib/operations/create_index.js +92 -0
  81. package/lib/operations/create_indexes.js +61 -0
  82. package/lib/operations/cursor_ops.js +3 -4
  83. package/lib/operations/db_ops.js +15 -12
  84. package/lib/operations/delete_many.js +25 -0
  85. package/lib/operations/delete_one.js +25 -0
  86. package/lib/operations/distinct.js +85 -0
  87. package/lib/operations/drop.js +53 -0
  88. package/lib/operations/drop_index.js +42 -0
  89. package/lib/operations/drop_indexes.js +23 -0
  90. package/lib/operations/estimated_document_count.js +33 -0
  91. package/lib/operations/execute_db_admin_command.js +34 -0
  92. package/lib/operations/execute_operation.js +165 -0
  93. package/lib/operations/explain.js +23 -0
  94. package/lib/operations/find_and_modify.js +98 -0
  95. package/lib/operations/find_one.js +33 -0
  96. package/lib/operations/find_one_and_delete.js +16 -0
  97. package/lib/operations/find_one_and_replace.js +18 -0
  98. package/lib/operations/find_one_and_update.js +19 -0
  99. package/lib/operations/geo_haystack_search.js +79 -0
  100. package/lib/operations/has_next.js +40 -0
  101. package/lib/operations/index_exists.js +39 -0
  102. package/lib/operations/index_information.js +23 -0
  103. package/lib/operations/indexes.js +22 -0
  104. package/lib/operations/insert_many.js +63 -0
  105. package/lib/operations/insert_one.js +75 -0
  106. package/lib/operations/is_capped.js +19 -0
  107. package/lib/operations/list_indexes.js +66 -0
  108. package/lib/operations/map_reduce.js +189 -0
  109. package/lib/operations/next.js +32 -0
  110. package/lib/operations/operation.js +63 -0
  111. package/lib/operations/options_operation.js +32 -0
  112. package/lib/operations/profiling_level.js +31 -0
  113. package/lib/operations/re_index.js +28 -0
  114. package/lib/operations/remove_user.js +52 -0
  115. package/lib/operations/rename.js +61 -0
  116. package/lib/operations/replace_one.js +47 -0
  117. package/lib/operations/set_profiling_level.js +48 -0
  118. package/lib/operations/stats.js +45 -0
  119. package/lib/operations/to_array.js +68 -0
  120. package/lib/operations/update_many.js +29 -0
  121. package/lib/operations/update_one.js +44 -0
  122. package/lib/operations/validate_collection.js +40 -0
  123. package/lib/read_concern.js +55 -0
  124. package/lib/topologies/mongos.js +3 -3
  125. package/lib/topologies/native_topology.js +22 -2
  126. package/lib/topologies/replset.js +3 -3
  127. package/lib/topologies/server.js +4 -4
  128. package/lib/topologies/topology_base.js +6 -6
  129. package/lib/url_parser.js +4 -3
  130. package/lib/utils.js +46 -59
  131. package/lib/write_concern.js +66 -0
  132. package/package.json +15 -6
  133. package/lib/.DS_Store +0 -0
@@ -1,11 +1,12 @@
1
1
  'use strict';
2
2
 
3
3
  const inherits = require('util').inherits;
4
- const ReadPreference = require('mongodb-core').ReadPreference;
5
- const MongoError = require('mongodb-core').MongoError;
4
+ const ReadPreference = require('./core').ReadPreference;
5
+ const MongoError = require('./core').MongoError;
6
6
  const Readable = require('stream').Readable;
7
7
  const CoreCursor = require('./cursor');
8
8
  const SUPPORTS = require('./utils').SUPPORTS;
9
+ const MongoDBNamespace = require('./utils').MongoDBNamespace;
9
10
 
10
11
  /**
11
12
  * @fileOverview The **CommandCursor** class is an internal class that embodies a
@@ -54,10 +55,12 @@ const SUPPORTS = require('./utils').SUPPORTS;
54
55
  * @fires CommandCursor#readable
55
56
  * @return {CommandCursor} an CommandCursor instance.
56
57
  */
57
- var CommandCursor = function(bson, ns, cmd, options, topology, topologyOptions) {
58
+ var CommandCursor = function(topology, ns, cmd, options) {
58
59
  CoreCursor.apply(this, Array.prototype.slice.call(arguments, 0));
59
60
  var state = CommandCursor.INIT;
60
61
  var streamOptions = {};
62
+ const bson = topology.s.bson;
63
+ const topologyOptions = topology.s.options;
61
64
 
62
65
  // MaxTimeMS
63
66
  var maxTimeMS = null;
@@ -79,7 +82,7 @@ var CommandCursor = function(bson, ns, cmd, options, topology, topologyOptions)
79
82
  // BSON
80
83
  bson: bson,
81
84
  // Namespace
82
- ns: ns,
85
+ namespace: MongoDBNamespace.fromString(ns),
83
86
  // Command
84
87
  cmd: cmd,
85
88
  // Options
@@ -95,6 +98,13 @@ var CommandCursor = function(bson, ns, cmd, options, topology, topologyOptions)
95
98
  };
96
99
  };
97
100
 
101
+ Object.defineProperty(CommandCursor.prototype, 'namespace', {
102
+ enumerable: true,
103
+ get: function() {
104
+ return this.s.namespace.toString();
105
+ }
106
+ });
107
+
98
108
  /**
99
109
  * CommandCursor stream data event, fired for each document in the cursor.
100
110
  *
@@ -142,14 +152,14 @@ var methodsToInherit = [
142
152
  'kill',
143
153
  'setCursorBatchSize',
144
154
  '_find',
145
- '_getmore',
155
+ '_initializeCursor',
156
+ '_getMore',
146
157
  '_killcursor',
147
158
  'isDead',
148
159
  'explain',
149
160
  'isNotified',
150
161
  'isKilled',
151
- '_endSession',
152
- '_initImplicitSession'
162
+ '_endSession'
153
163
  ];
154
164
 
155
165
  // Only inherit the types we need
@@ -0,0 +1,158 @@
1
+ 'use strict';
2
+
3
+ const MongoError = require('../error').MongoError;
4
+
5
+ /**
6
+ * Creates a new AuthProvider, which dictates how to authenticate for a given
7
+ * mechanism.
8
+ * @class
9
+ */
10
+ class AuthProvider {
11
+ constructor(bson) {
12
+ this.bson = bson;
13
+ this.authStore = [];
14
+ }
15
+
16
+ /**
17
+ * Authenticate
18
+ * @method
19
+ * @param {SendAuthCommand} sendAuthCommand Writes an auth command directly to a specific connection
20
+ * @param {Connection[]} connections Connections to authenticate using this authenticator
21
+ * @param {MongoCredentials} credentials Authentication credentials
22
+ * @param {authResultCallback} callback The callback to return the result from the authentication
23
+ */
24
+ auth(sendAuthCommand, connections, credentials, callback) {
25
+ // Total connections
26
+ let count = connections.length;
27
+
28
+ if (count === 0) {
29
+ callback(null, null);
30
+ return;
31
+ }
32
+
33
+ // Valid connections
34
+ let numberOfValidConnections = 0;
35
+ let errorObject = null;
36
+
37
+ const execute = connection => {
38
+ this._authenticateSingleConnection(sendAuthCommand, connection, credentials, (err, r) => {
39
+ // Adjust count
40
+ count = count - 1;
41
+
42
+ // If we have an error
43
+ if (err) {
44
+ errorObject = new MongoError(err);
45
+ } else if (r && (r.$err || r.errmsg)) {
46
+ errorObject = new MongoError(r);
47
+ } else {
48
+ numberOfValidConnections = numberOfValidConnections + 1;
49
+ }
50
+
51
+ // Still authenticating against other connections.
52
+ if (count !== 0) {
53
+ return;
54
+ }
55
+
56
+ // We have authenticated all connections
57
+ if (numberOfValidConnections > 0) {
58
+ // Store the auth details
59
+ this.addCredentials(credentials);
60
+ // Return correct authentication
61
+ callback(null, true);
62
+ } else {
63
+ if (errorObject == null) {
64
+ errorObject = new MongoError(`failed to authenticate using ${credentials.mechanism}`);
65
+ }
66
+ callback(errorObject, false);
67
+ }
68
+ });
69
+ };
70
+
71
+ const executeInNextTick = _connection => process.nextTick(() => execute(_connection));
72
+
73
+ // For each connection we need to authenticate
74
+ while (connections.length > 0) {
75
+ executeInNextTick(connections.shift());
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Implementation of a single connection authenticating. Is meant to be overridden.
81
+ * Will error if called directly
82
+ * @ignore
83
+ */
84
+ _authenticateSingleConnection(/*sendAuthCommand, connection, credentials, callback*/) {
85
+ throw new Error('_authenticateSingleConnection must be overridden');
86
+ }
87
+
88
+ /**
89
+ * Adds credentials to store only if it does not exist
90
+ * @param {MongoCredentials} credentials credentials to add to store
91
+ */
92
+ addCredentials(credentials) {
93
+ const found = this.authStore.some(cred => cred.equals(credentials));
94
+
95
+ if (!found) {
96
+ this.authStore.push(credentials);
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Re authenticate pool
102
+ * @method
103
+ * @param {SendAuthCommand} sendAuthCommand Writes an auth command directly to a specific connection
104
+ * @param {Connection[]} connections Connections to authenticate using this authenticator
105
+ * @param {authResultCallback} callback The callback to return the result from the authentication
106
+ */
107
+ reauthenticate(sendAuthCommand, connections, callback) {
108
+ const authStore = this.authStore.slice(0);
109
+ let count = authStore.length;
110
+ if (count === 0) {
111
+ return callback(null, null);
112
+ }
113
+
114
+ for (let i = 0; i < authStore.length; i++) {
115
+ this.auth(sendAuthCommand, connections, authStore[i], function(err) {
116
+ count = count - 1;
117
+ if (count === 0) {
118
+ callback(err, null);
119
+ }
120
+ });
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Remove credentials that have been previously stored in the auth provider
126
+ * @method
127
+ * @param {string} source Name of database we are removing authStore details about
128
+ * @return {object}
129
+ */
130
+ logout(source) {
131
+ this.authStore = this.authStore.filter(credentials => credentials.source !== source);
132
+ }
133
+ }
134
+
135
+ /**
136
+ * A function that writes authentication commands to a specific connection
137
+ * @callback SendAuthCommand
138
+ * @param {Connection} connection The connection to write to
139
+ * @param {Command} command A command with a toBin method that can be written to a connection
140
+ * @param {AuthWriteCallback} callback Callback called when command response is received
141
+ */
142
+
143
+ /**
144
+ * A callback for a specific auth command
145
+ * @callback AuthWriteCallback
146
+ * @param {Error} err If command failed, an error from the server
147
+ * @param {object} r The response from the server
148
+ */
149
+
150
+ /**
151
+ * This is a result from an authentication strategy
152
+ *
153
+ * @callback authResultCallback
154
+ * @param {error} error An error object. Set to null if no error present
155
+ * @param {boolean} result The result of the authentication process
156
+ */
157
+
158
+ module.exports = { AuthProvider };
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ const MongoCR = require('./mongocr');
4
+ const X509 = require('./x509');
5
+ const Plain = require('./plain');
6
+ const GSSAPI = require('./gssapi');
7
+ const SSPI = require('./sspi');
8
+ const ScramSHA1 = require('./scram').ScramSHA1;
9
+ const ScramSHA256 = require('./scram').ScramSHA256;
10
+
11
+ /**
12
+ * Returns the default authentication providers.
13
+ *
14
+ * @param {BSON} bson Bson definition
15
+ * @returns {Object} a mapping of auth names to auth types
16
+ */
17
+ function defaultAuthProviders(bson) {
18
+ return {
19
+ mongocr: new MongoCR(bson),
20
+ x509: new X509(bson),
21
+ plain: new Plain(bson),
22
+ gssapi: new GSSAPI(bson),
23
+ sspi: new SSPI(bson),
24
+ 'scram-sha-1': new ScramSHA1(bson),
25
+ 'scram-sha-256': new ScramSHA256(bson)
26
+ };
27
+ }
28
+
29
+ module.exports = { defaultAuthProviders };
@@ -0,0 +1,241 @@
1
+ 'use strict';
2
+
3
+ const AuthProvider = require('./auth_provider').AuthProvider;
4
+ const retrieveKerberos = require('../utils').retrieveKerberos;
5
+ let kerberos;
6
+
7
+ /**
8
+ * Creates a new GSSAPI authentication mechanism
9
+ * @class
10
+ * @extends AuthProvider
11
+ */
12
+ class GSSAPI extends AuthProvider {
13
+ /**
14
+ * Implementation of authentication for a single connection
15
+ * @override
16
+ */
17
+ _authenticateSingleConnection(sendAuthCommand, connection, credentials, callback) {
18
+ const source = credentials.source;
19
+ const username = credentials.username;
20
+ const password = credentials.password;
21
+ const mechanismProperties = credentials.mechanismProperties;
22
+ const gssapiServiceName =
23
+ mechanismProperties['gssapiservicename'] ||
24
+ mechanismProperties['gssapiServiceName'] ||
25
+ 'mongodb';
26
+
27
+ GSSAPIInitialize(
28
+ this,
29
+ kerberos.processes.MongoAuthProcess,
30
+ source,
31
+ username,
32
+ password,
33
+ source,
34
+ gssapiServiceName,
35
+ sendAuthCommand,
36
+ connection,
37
+ mechanismProperties,
38
+ callback
39
+ );
40
+ }
41
+
42
+ /**
43
+ * Authenticate
44
+ * @override
45
+ * @method
46
+ */
47
+ auth(sendAuthCommand, connections, credentials, callback) {
48
+ if (kerberos == null) {
49
+ try {
50
+ kerberos = retrieveKerberos();
51
+ } catch (e) {
52
+ return callback(e, null);
53
+ }
54
+ }
55
+
56
+ super.auth(sendAuthCommand, connections, credentials, callback);
57
+ }
58
+ }
59
+
60
+ //
61
+ // Initialize step
62
+ var GSSAPIInitialize = function(
63
+ self,
64
+ MongoAuthProcess,
65
+ db,
66
+ username,
67
+ password,
68
+ authdb,
69
+ gssapiServiceName,
70
+ sendAuthCommand,
71
+ connection,
72
+ options,
73
+ callback
74
+ ) {
75
+ // Create authenticator
76
+ var mongo_auth_process = new MongoAuthProcess(
77
+ connection.host,
78
+ connection.port,
79
+ gssapiServiceName,
80
+ options
81
+ );
82
+
83
+ // Perform initialization
84
+ mongo_auth_process.init(username, password, function(err) {
85
+ if (err) return callback(err, false);
86
+
87
+ // Perform the first step
88
+ mongo_auth_process.transition('', function(err, payload) {
89
+ if (err) return callback(err, false);
90
+
91
+ // Call the next db step
92
+ MongoDBGSSAPIFirstStep(
93
+ self,
94
+ mongo_auth_process,
95
+ payload,
96
+ db,
97
+ username,
98
+ password,
99
+ authdb,
100
+ sendAuthCommand,
101
+ connection,
102
+ callback
103
+ );
104
+ });
105
+ });
106
+ };
107
+
108
+ //
109
+ // Perform first step against mongodb
110
+ var MongoDBGSSAPIFirstStep = function(
111
+ self,
112
+ mongo_auth_process,
113
+ payload,
114
+ db,
115
+ username,
116
+ password,
117
+ authdb,
118
+ sendAuthCommand,
119
+ connection,
120
+ callback
121
+ ) {
122
+ // Build the sasl start command
123
+ var command = {
124
+ saslStart: 1,
125
+ mechanism: 'GSSAPI',
126
+ payload: payload,
127
+ autoAuthorize: 1
128
+ };
129
+
130
+ // Write the commmand on the connection
131
+ sendAuthCommand(connection, '$external.$cmd', command, (err, doc) => {
132
+ if (err) return callback(err, false);
133
+ // Execute mongodb transition
134
+ mongo_auth_process.transition(doc.payload, function(err, payload) {
135
+ if (err) return callback(err, false);
136
+
137
+ // MongoDB API Second Step
138
+ MongoDBGSSAPISecondStep(
139
+ self,
140
+ mongo_auth_process,
141
+ payload,
142
+ doc,
143
+ db,
144
+ username,
145
+ password,
146
+ authdb,
147
+ sendAuthCommand,
148
+ connection,
149
+ callback
150
+ );
151
+ });
152
+ });
153
+ };
154
+
155
+ //
156
+ // Perform first step against mongodb
157
+ var MongoDBGSSAPISecondStep = function(
158
+ self,
159
+ mongo_auth_process,
160
+ payload,
161
+ doc,
162
+ db,
163
+ username,
164
+ password,
165
+ authdb,
166
+ sendAuthCommand,
167
+ connection,
168
+ callback
169
+ ) {
170
+ // Build Authentication command to send to MongoDB
171
+ var command = {
172
+ saslContinue: 1,
173
+ conversationId: doc.conversationId,
174
+ payload: payload
175
+ };
176
+
177
+ // Execute the command
178
+ // Write the commmand on the connection
179
+ sendAuthCommand(connection, '$external.$cmd', command, (err, doc) => {
180
+ if (err) return callback(err, false);
181
+ // Call next transition for kerberos
182
+ mongo_auth_process.transition(doc.payload, function(err, payload) {
183
+ if (err) return callback(err, false);
184
+
185
+ // Call the last and third step
186
+ MongoDBGSSAPIThirdStep(
187
+ self,
188
+ mongo_auth_process,
189
+ payload,
190
+ doc,
191
+ db,
192
+ username,
193
+ password,
194
+ authdb,
195
+ sendAuthCommand,
196
+ connection,
197
+ callback
198
+ );
199
+ });
200
+ });
201
+ };
202
+
203
+ var MongoDBGSSAPIThirdStep = function(
204
+ self,
205
+ mongo_auth_process,
206
+ payload,
207
+ doc,
208
+ db,
209
+ username,
210
+ password,
211
+ authdb,
212
+ sendAuthCommand,
213
+ connection,
214
+ callback
215
+ ) {
216
+ // Build final command
217
+ var command = {
218
+ saslContinue: 1,
219
+ conversationId: doc.conversationId,
220
+ payload: payload
221
+ };
222
+
223
+ // Execute the command
224
+ sendAuthCommand(connection, '$external.$cmd', command, (err, r) => {
225
+ if (err) return callback(err, false);
226
+ mongo_auth_process.transition(null, function(err) {
227
+ if (err) return callback(err, null);
228
+ callback(null, r);
229
+ });
230
+ });
231
+ };
232
+
233
+ /**
234
+ * This is a result from a authentication strategy
235
+ *
236
+ * @callback authResultCallback
237
+ * @param {error} error An error object. Set to null if no error present
238
+ * @param {boolean} result The result of the authentication process
239
+ */
240
+
241
+ module.exports = GSSAPI;
@@ -0,0 +1,81 @@
1
+ 'use strict';
2
+
3
+ // Resolves the default auth mechanism according to
4
+ // https://github.com/mongodb/specifications/blob/master/source/auth/auth.rst
5
+ function getDefaultAuthMechanism(ismaster) {
6
+ if (ismaster) {
7
+ // If ismaster contains saslSupportedMechs, use scram-sha-256
8
+ // if it is available, else scram-sha-1
9
+ if (Array.isArray(ismaster.saslSupportedMechs)) {
10
+ return ismaster.saslSupportedMechs.indexOf('SCRAM-SHA-256') >= 0
11
+ ? 'scram-sha-256'
12
+ : 'scram-sha-1';
13
+ }
14
+
15
+ // Fallback to legacy selection method. If wire version >= 3, use scram-sha-1
16
+ if (ismaster.maxWireVersion >= 3) {
17
+ return 'scram-sha-1';
18
+ }
19
+ }
20
+
21
+ // Default for wireprotocol < 3
22
+ return 'mongocr';
23
+ }
24
+
25
+ /**
26
+ * A representation of the credentials used by MongoDB
27
+ * @class
28
+ * @property {string} mechanism The method used to authenticate
29
+ * @property {string} [username] The username used for authentication
30
+ * @property {string} [password] The password used for authentication
31
+ * @property {string} [source] The database that the user should authenticate against
32
+ * @property {object} [mechanismProperties] Special properties used by some types of auth mechanisms
33
+ */
34
+ class MongoCredentials {
35
+ /**
36
+ * Creates a new MongoCredentials object
37
+ * @param {object} [options]
38
+ * @param {string} [options.username] The username used for authentication
39
+ * @param {string} [options.password] The password used for authentication
40
+ * @param {string} [options.source] The database that the user should authenticate against
41
+ * @param {string} [options.mechanism] The method used to authenticate
42
+ * @param {object} [options.mechanismProperties] Special properties used by some types of auth mechanisms
43
+ */
44
+ constructor(options) {
45
+ options = options || {};
46
+ this.username = options.username;
47
+ this.password = options.password;
48
+ this.source = options.source || options.db;
49
+ this.mechanism = options.mechanism || 'default';
50
+ this.mechanismProperties = options.mechanismProperties;
51
+ }
52
+
53
+ /**
54
+ * Determines if two MongoCredentials objects are equivalent
55
+ * @param {MongoCredentials} other another MongoCredentials object
56
+ * @returns {boolean} true if the two objects are equal.
57
+ */
58
+ equals(other) {
59
+ return (
60
+ this.mechanism === other.mechanism &&
61
+ this.username === other.username &&
62
+ this.password === other.password &&
63
+ this.source === other.source
64
+ );
65
+ }
66
+
67
+ /**
68
+ * If the authentication mechanism is set to "default", resolves the authMechanism
69
+ * based on the server version and server supported sasl mechanisms.
70
+ *
71
+ * @param {Object} [ismaster] An ismaster response from the server
72
+ */
73
+ resolveAuthMechanism(ismaster) {
74
+ // If the mechanism is not "default", then it does not need to be resolved
75
+ if (this.mechanism.toLowerCase() === 'default') {
76
+ this.mechanism = getDefaultAuthMechanism(ismaster);
77
+ }
78
+ }
79
+ }
80
+
81
+ module.exports = { MongoCredentials };
@@ -0,0 +1,51 @@
1
+ 'use strict';
2
+
3
+ const crypto = require('crypto');
4
+ const AuthProvider = require('./auth_provider').AuthProvider;
5
+
6
+ /**
7
+ * Creates a new MongoCR authentication mechanism
8
+ *
9
+ * @extends AuthProvider
10
+ */
11
+ class MongoCR extends AuthProvider {
12
+ /**
13
+ * Implementation of authentication for a single connection
14
+ * @override
15
+ */
16
+ _authenticateSingleConnection(sendAuthCommand, connection, credentials, callback) {
17
+ const username = credentials.username;
18
+ const password = credentials.password;
19
+ const source = credentials.source;
20
+
21
+ sendAuthCommand(connection, `${source}.$cmd`, { getnonce: 1 }, (err, r) => {
22
+ let nonce = null;
23
+ let key = null;
24
+
25
+ // Get nonce
26
+ if (err == null) {
27
+ nonce = r.nonce;
28
+ // Use node md5 generator
29
+ let md5 = crypto.createHash('md5');
30
+ // Generate keys used for authentication
31
+ md5.update(username + ':mongo:' + password, 'utf8');
32
+ const hash_password = md5.digest('hex');
33
+ // Final key
34
+ md5 = crypto.createHash('md5');
35
+ md5.update(nonce + username + hash_password, 'utf8');
36
+ key = md5.digest('hex');
37
+ }
38
+
39
+ const authenticateCommand = {
40
+ authenticate: 1,
41
+ user: username,
42
+ nonce,
43
+ key
44
+ };
45
+
46
+ sendAuthCommand(connection, `${source}.$cmd`, authenticateCommand, callback);
47
+ });
48
+ }
49
+ }
50
+
51
+ module.exports = MongoCR;
@@ -0,0 +1,35 @@
1
+ 'use strict';
2
+
3
+ const retrieveBSON = require('../connection/utils').retrieveBSON;
4
+ const AuthProvider = require('./auth_provider').AuthProvider;
5
+
6
+ // TODO: can we get the Binary type from this.bson instead?
7
+ const BSON = retrieveBSON();
8
+ const Binary = BSON.Binary;
9
+
10
+ /**
11
+ * Creates a new Plain authentication mechanism
12
+ *
13
+ * @extends AuthProvider
14
+ */
15
+ class Plain extends AuthProvider {
16
+ /**
17
+ * Implementation of authentication for a single connection
18
+ * @override
19
+ */
20
+ _authenticateSingleConnection(sendAuthCommand, connection, credentials, callback) {
21
+ const username = credentials.username;
22
+ const password = credentials.password;
23
+ const payload = new Binary(`\x00${username}\x00${password}`);
24
+ const command = {
25
+ saslStart: 1,
26
+ mechanism: 'PLAIN',
27
+ payload: payload,
28
+ autoAuthorize: 1
29
+ };
30
+
31
+ sendAuthCommand(connection, '$external.$cmd', command, callback);
32
+ }
33
+ }
34
+
35
+ module.exports = Plain;