mongodb 2.2.26 → 2.2.30
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.
- package/HISTORY.md +47 -0
- package/README.md +1 -1
- package/lib/admin.js +17 -15
- package/lib/aggregation_cursor.js +9 -0
- package/lib/authenticate.js +109 -0
- package/lib/collection.js +3 -3
- package/lib/command_cursor.js +10 -1
- package/lib/cursor.js +16 -1
- package/lib/db.js +5 -104
- package/lib/gridfs/grid_store.js +6 -3
- package/lib/gridfs-stream/download.js +17 -7
- package/lib/gridfs-stream/upload.js +7 -0
- package/lib/mongo_client.js +105 -26
- package/lib/mongos.js +22 -15
- package/lib/replset.js +57 -56
- package/lib/server.js +29 -24
- package/lib/url_parser.js +7 -2
- package/lib/utils.js +8 -8
- package/package.json +2 -2
- package/yarn.lock +593 -652
package/HISTORY.md
CHANGED
|
@@ -1,3 +1,50 @@
|
|
|
1
|
+
2.2.30 2017-07-07
|
|
2
|
+
-----------------
|
|
3
|
+
* Update mongodb-core to 2.2.14
|
|
4
|
+
* MongoClient
|
|
5
|
+
* add `appname` to list of valid option names
|
|
6
|
+
* added test for passing appname as option
|
|
7
|
+
* NODE-1052 ensure user options are applied while parsing connection string uris
|
|
8
|
+
|
|
9
|
+
2.2.29 2017-06-19
|
|
10
|
+
-----------------
|
|
11
|
+
* Update mongodb-core to 2.1.13
|
|
12
|
+
* NODE-1039 ensure we force destroy server instances, forcing queue to be flushed.
|
|
13
|
+
* Use actual server type in standalone SDAM events.
|
|
14
|
+
* Allow multiple map calls (Issue #1521, https://github.com/Robbilie).
|
|
15
|
+
* Clone insertMany options before mutating (Issue #1522, https://github.com/vkarpov15).
|
|
16
|
+
* NODE-1034 Fix GridStore issue caused by Node 8.0.0 breaking backward compatible fs.read API.
|
|
17
|
+
* NODE-1026, use operator instead of skip function in order to avoid useless fetch stage.
|
|
18
|
+
|
|
19
|
+
2.2.28 2017-06-02
|
|
20
|
+
-----------------
|
|
21
|
+
* Update mongodb-core to 2.1.12
|
|
22
|
+
* NODE-1019 Set keepAlive to 300 seconds or 1/2 of socketTimeout if socketTimeout < keepAlive.
|
|
23
|
+
* Minor fix to report the correct state on error.
|
|
24
|
+
* NODE-1020 'family' was added to options to provide high priority for ipv6 addresses (Issue #1518, https://github.com/firej).
|
|
25
|
+
* Fix require_optional loading of bson-ext.
|
|
26
|
+
* Ensure no errors are thrown by replset if topology is destroyed before it finished connecting.
|
|
27
|
+
* NODE-999 SDAM fixes for Mongos and single Server event emitting.
|
|
28
|
+
* NODE-1014 Set socketTimeout to default to 360 seconds.
|
|
29
|
+
* NODE-1019 Set keepAlive to 300 seconds or 1/2 of socketTimeout if socketTimeout < keepAlive.
|
|
30
|
+
* Just handle Collection name errors distinctly from general callback errors avoiding double callbacks in Db.collection.
|
|
31
|
+
* NODE-999 SDAM fixes for Mongos and single Server event emitting.
|
|
32
|
+
* NODE-1000 Added guard condition for upload.js checkDone function in case of race condition caused by late arriving chunk write.
|
|
33
|
+
|
|
34
|
+
2.2.27 2017-05-22
|
|
35
|
+
-----------------
|
|
36
|
+
* Updated mongodb-core to 2.1.11
|
|
37
|
+
* NODE-987 Clear out old intervalIds on when calling topologyMonitor.
|
|
38
|
+
* NODE-987 Moved filtering to pingServer method and added test case.
|
|
39
|
+
* Check for connection destroyed just before writing out and flush out operations correctly if it is (Issue #179, https://github.com/jmholzinger).
|
|
40
|
+
* NODE-989 Refactored Replicaset monitoring to correcly monitor newly added servers, Also extracted setTimeout and setInterval to use custom wrappers Timeout and Interval.
|
|
41
|
+
* NODE-985 Deprecated Db.authenticate and Admin.authenticate and moved auth methods into authenticate.js to ensure MongoClient.connect does not print deprecation warnings.
|
|
42
|
+
* NODE-988 Merged readConcern and hint correctly on collection(...).find(...).count()
|
|
43
|
+
* Fix passing the readConcern option to MongoClient.connect (Issue #1514, https://github.com/bausmeier).
|
|
44
|
+
* NODE-996 Propegate all events up to a MongoClient instance.
|
|
45
|
+
* Allow saving doc with null `_id` (Issue #1517, https://github.com/vkarpov15).
|
|
46
|
+
* NODE-993 Expose hasNext for command cursor and add docs for both CommandCursor and Aggregation Cursor.
|
|
47
|
+
|
|
1
48
|
2.2.26 2017-04-18
|
|
2
49
|
-----------------
|
|
3
50
|
* Updated mongodb-core to 2.1.10
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](http://travis-ci.org/mongodb/node-mongodb-native)
|
|
4
4
|
[](https://coveralls.io/github/mongodb/node-mongodb-native?branch=2.1)
|
|
5
|
-
[](https://gitter.im/mongodb/node-mongodb-native?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
|
6
6
|
|
|
7
7
|
# Description
|
|
8
8
|
|
package/lib/admin.js
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
var toError = require('./utils').toError,
|
|
4
4
|
Define = require('./metadata'),
|
|
5
|
-
shallowClone = require('./utils').shallowClone
|
|
5
|
+
shallowClone = require('./utils').shallowClone,
|
|
6
|
+
assign = require('./utils').assign,
|
|
7
|
+
authenticate = require('./authenticate');
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* @fileOverview The **Admin** class is an internal class that allows convenient access to
|
|
@@ -239,23 +241,23 @@ define.classMethod('ping', {callback: true, promise:true});
|
|
|
239
241
|
* @param {string} [password] The password.
|
|
240
242
|
* @param {Admin~resultCallback} [callback] The command result callback
|
|
241
243
|
* @return {Promise} returns Promise if no callback passed
|
|
244
|
+
* @deprecated This method will no longer be available in the next major release 3.x as MongoDB 3.6 will only allow auth against users in the admin db and will no longer allow multiple credentials on a socket. Please authenticate using MongoClient.connect with auth credentials.
|
|
242
245
|
*/
|
|
243
246
|
Admin.prototype.authenticate = function(username, password, options, callback) {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
247
|
+
console.warn("Admin.prototype.authenticate method will no longer be available in the next major release 3.x as MongoDB 3.6 will only allow auth against users in the admin db and will no longer allow multiple credentials on a socket. Please authenticate using MongoClient.connect with auth credentials.");
|
|
248
|
+
var finalArguments = [this.s.db];
|
|
249
|
+
if(typeof username == 'string') finalArguments.push(username);
|
|
250
|
+
if(typeof password == 'string') finalArguments.push(password);
|
|
251
|
+
if(typeof options == 'function') {
|
|
252
|
+
finalArguments.push({ authdb: 'admin' });
|
|
253
|
+
finalArguments.push(options);
|
|
254
|
+
} else {
|
|
255
|
+
finalArguments.push(assign({}, options, { authdb: 'admin' }));
|
|
256
|
+
}
|
|
251
257
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
if(err) return reject(err);
|
|
256
|
-
resolve(r);
|
|
257
|
-
});
|
|
258
|
-
});
|
|
258
|
+
if(typeof callback == 'function') finalArguments.push(callback);
|
|
259
|
+
// Excute authenticate method
|
|
260
|
+
return authenticate.apply(this.s.db, finalArguments);
|
|
259
261
|
}
|
|
260
262
|
|
|
261
263
|
define.classMethod('authenticate', {callback: true, promise:true});
|
|
@@ -316,6 +316,7 @@ AggregationCursor.prototype.get = AggregationCursor.prototype.toArray;
|
|
|
316
316
|
define.classMethod('toArray', {callback: true, promise:true});
|
|
317
317
|
define.classMethod('each', {callback: true, promise:false});
|
|
318
318
|
define.classMethod('forEach', {callback: true, promise:false});
|
|
319
|
+
define.classMethod('hasNext', {callback: true, promise:true});
|
|
319
320
|
define.classMethod('next', {callback: true, promise:true});
|
|
320
321
|
define.classMethod('close', {callback: true, promise:true});
|
|
321
322
|
define.classMethod('isClosed', {callback: false, promise:false, returns: [Boolean]});
|
|
@@ -331,6 +332,14 @@ define.classMethod('readBufferedDocuments', {callback: false, promise:false, ret
|
|
|
331
332
|
* @return {Promise} returns Promise if no callback passed
|
|
332
333
|
*/
|
|
333
334
|
|
|
335
|
+
/**
|
|
336
|
+
* Check if there is any document still available in the cursor
|
|
337
|
+
* @function AggregationCursor.prototype.hasNext
|
|
338
|
+
* @param {AggregationCursor~resultCallback} [callback] The result callback.
|
|
339
|
+
* @throws {MongoError}
|
|
340
|
+
* @return {Promise} returns Promise if no callback passed
|
|
341
|
+
*/
|
|
342
|
+
|
|
334
343
|
/**
|
|
335
344
|
* The callback format for results
|
|
336
345
|
* @callback AggregationCursor~toArrayResultCallback
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
var shallowClone = require('./utils').shallowClone
|
|
2
|
+
, handleCallback = require('./utils').handleCallback
|
|
3
|
+
, MongoError = require('mongodb-core').MongoError;
|
|
4
|
+
|
|
5
|
+
var authenticate = function(self, username, password, options, callback) {
|
|
6
|
+
// Did the user destroy the topology
|
|
7
|
+
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));
|
|
8
|
+
|
|
9
|
+
// the default db to authenticate against is 'self'
|
|
10
|
+
// if authententicate is called from a retry context, it may be another one, like admin
|
|
11
|
+
var authdb = options.dbName ? options.dbName : self.databaseName;
|
|
12
|
+
authdb = self.authSource ? self.authSource : authdb;
|
|
13
|
+
authdb = options.authdb ? options.authdb : authdb;
|
|
14
|
+
authdb = options.authSource ? options.authSource : authdb;
|
|
15
|
+
|
|
16
|
+
// Callback
|
|
17
|
+
var _callback = function(err, result) {
|
|
18
|
+
if(self.listeners('authenticated').length > 0) {
|
|
19
|
+
self.emit('authenticated', err, result);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Return to caller
|
|
23
|
+
handleCallback(callback, err, result);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// authMechanism
|
|
27
|
+
var authMechanism = options.authMechanism || '';
|
|
28
|
+
authMechanism = authMechanism.toUpperCase();
|
|
29
|
+
|
|
30
|
+
// If classic auth delegate to auth command
|
|
31
|
+
if(authMechanism == 'MONGODB-CR') {
|
|
32
|
+
self.s.topology.auth('mongocr', authdb, username, password, function(err) {
|
|
33
|
+
if(err) return handleCallback(callback, err, false);
|
|
34
|
+
_callback(null, true);
|
|
35
|
+
});
|
|
36
|
+
} else if(authMechanism == 'PLAIN') {
|
|
37
|
+
self.s.topology.auth('plain', authdb, username, password, function(err) {
|
|
38
|
+
if(err) return handleCallback(callback, err, false);
|
|
39
|
+
_callback(null, true);
|
|
40
|
+
});
|
|
41
|
+
} else if(authMechanism == 'MONGODB-X509') {
|
|
42
|
+
self.s.topology.auth('x509', authdb, username, password, function(err) {
|
|
43
|
+
if(err) return handleCallback(callback, err, false);
|
|
44
|
+
_callback(null, true);
|
|
45
|
+
});
|
|
46
|
+
} else if(authMechanism == 'SCRAM-SHA-1') {
|
|
47
|
+
self.s.topology.auth('scram-sha-1', authdb, username, password, function(err) {
|
|
48
|
+
if(err) return handleCallback(callback, err, false);
|
|
49
|
+
_callback(null, true);
|
|
50
|
+
});
|
|
51
|
+
} else if(authMechanism == 'GSSAPI') {
|
|
52
|
+
if(process.platform == 'win32') {
|
|
53
|
+
self.s.topology.auth('sspi', authdb, username, password, options, function(err) {
|
|
54
|
+
if(err) return handleCallback(callback, err, false);
|
|
55
|
+
_callback(null, true);
|
|
56
|
+
});
|
|
57
|
+
} else {
|
|
58
|
+
self.s.topology.auth('gssapi', authdb, username, password, options, function(err) {
|
|
59
|
+
if(err) return handleCallback(callback, err, false);
|
|
60
|
+
_callback(null, true);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
} else if(authMechanism == 'DEFAULT') {
|
|
64
|
+
self.s.topology.auth('default', authdb, username, password, function(err) {
|
|
65
|
+
if(err) return handleCallback(callback, err, false);
|
|
66
|
+
_callback(null, true);
|
|
67
|
+
});
|
|
68
|
+
} else {
|
|
69
|
+
handleCallback(callback, MongoError.create({message: f("authentication mechanism %s not supported", options.authMechanism), driver:true}));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = function(self, username, password, options, callback) {
|
|
74
|
+
if(typeof options == 'function') callback = options, options = {};
|
|
75
|
+
// Shallow copy the options
|
|
76
|
+
options = shallowClone(options);
|
|
77
|
+
|
|
78
|
+
// Set default mechanism
|
|
79
|
+
if(!options.authMechanism) {
|
|
80
|
+
options.authMechanism = 'DEFAULT';
|
|
81
|
+
} else if(options.authMechanism != 'GSSAPI'
|
|
82
|
+
&& options.authMechanism != 'DEFAULT'
|
|
83
|
+
&& options.authMechanism != 'MONGODB-CR'
|
|
84
|
+
&& options.authMechanism != 'MONGODB-X509'
|
|
85
|
+
&& options.authMechanism != 'SCRAM-SHA-1'
|
|
86
|
+
&& options.authMechanism != 'PLAIN') {
|
|
87
|
+
return handleCallback(callback, MongoError.create({message: "only DEFAULT, GSSAPI, PLAIN, MONGODB-X509, SCRAM-SHA-1 or MONGODB-CR is supported by authMechanism", driver:true}));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// If we have a callback fallback
|
|
91
|
+
if(typeof callback == 'function') return authenticate(self, username, password, options, function(err, r) {
|
|
92
|
+
// Support failed auth method
|
|
93
|
+
if(err && err.message && err.message.indexOf('saslStart') != -1) err.code = 59;
|
|
94
|
+
// Reject error
|
|
95
|
+
if(err) return callback(err, r);
|
|
96
|
+
callback(null, r);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Return a promise
|
|
100
|
+
return new self.s.promiseLibrary(function(resolve, reject) {
|
|
101
|
+
authenticate(self, username, password, options, function(err, r) {
|
|
102
|
+
// Support failed auth method
|
|
103
|
+
if(err && err.message && err.message.indexOf('saslStart') != -1) err.code = 59;
|
|
104
|
+
// Reject error
|
|
105
|
+
if(err) return reject(err);
|
|
106
|
+
resolve(r);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
};
|
package/lib/collection.js
CHANGED
|
@@ -496,7 +496,7 @@ define.classMethod('insertOne', {callback: true, promise:true});
|
|
|
496
496
|
Collection.prototype.insertMany = function(docs, options, callback) {
|
|
497
497
|
var self = this;
|
|
498
498
|
if(typeof options == 'function') callback = options, options = {};
|
|
499
|
-
options = options
|
|
499
|
+
options = options ? shallowClone(options) : {ordered:true};
|
|
500
500
|
if(!Array.isArray(docs) && typeof callback == 'function') {
|
|
501
501
|
return callback(MongoError.create({message: 'docs parameter must be an array of documents', driver:true }));
|
|
502
502
|
} else if(!Array.isArray(docs)) {
|
|
@@ -736,7 +736,7 @@ var insertDocuments = function(self, docs, options, callback) {
|
|
|
736
736
|
// Add _id if not specified
|
|
737
737
|
if(forceServerObjectId !== true){
|
|
738
738
|
for(var i = 0; i < docs.length; i++) {
|
|
739
|
-
if(docs[i]._id
|
|
739
|
+
if(docs[i]._id === void 0) docs[i]._id = self.s.pkFactory.createPk();
|
|
740
740
|
}
|
|
741
741
|
}
|
|
742
742
|
|
|
@@ -2040,7 +2040,7 @@ var count = function(self, query, options, callback) {
|
|
|
2040
2040
|
if(typeof skip == 'number') cmd.skip = skip;
|
|
2041
2041
|
if(typeof limit == 'number') cmd.limit = limit;
|
|
2042
2042
|
if(typeof maxTimeMS == 'number') cmd.maxTimeMS = maxTimeMS;
|
|
2043
|
-
if(hint)
|
|
2043
|
+
if(hint) cmd.hint = hint;
|
|
2044
2044
|
|
|
2045
2045
|
options = shallowClone(options);
|
|
2046
2046
|
// Ensure we have the right read preference inheritance
|
package/lib/command_cursor.js
CHANGED
|
@@ -131,7 +131,7 @@ var CommandCursor = function(bson, ns, cmd, options, topology, topologyOptions)
|
|
|
131
131
|
inherits(CommandCursor, Readable);
|
|
132
132
|
|
|
133
133
|
// Set the methods to inherit from prototype
|
|
134
|
-
var methodsToInherit = ['_next', 'next', 'each', 'forEach', 'toArray'
|
|
134
|
+
var methodsToInherit = ['_next', 'next', 'hasNext', 'each', 'forEach', 'toArray'
|
|
135
135
|
, 'rewind', 'bufferedCount', 'readBufferedDocuments', 'close', 'isClosed', 'kill', 'setCursorBatchSize'
|
|
136
136
|
, '_find', '_getmore', '_killcursor', 'isDead', 'explain', 'isNotified', 'isKilled'];
|
|
137
137
|
|
|
@@ -207,6 +207,7 @@ define.classMethod('toArray', {callback: true, promise:true});
|
|
|
207
207
|
define.classMethod('each', {callback: true, promise:false});
|
|
208
208
|
define.classMethod('forEach', {callback: true, promise:false});
|
|
209
209
|
define.classMethod('next', {callback: true, promise:true});
|
|
210
|
+
define.classMethod('hasNext', {callback: true, promise:true});
|
|
210
211
|
define.classMethod('close', {callback: true, promise:true});
|
|
211
212
|
define.classMethod('isClosed', {callback: false, promise:false, returns: [Boolean]});
|
|
212
213
|
define.classMethod('rewind', {callback: false, promise:false});
|
|
@@ -221,6 +222,14 @@ define.classMethod('readBufferedDocuments', {callback: false, promise:false, ret
|
|
|
221
222
|
* @return {Promise} returns Promise if no callback passed
|
|
222
223
|
*/
|
|
223
224
|
|
|
225
|
+
/**
|
|
226
|
+
* Check if there is any document still available in the cursor
|
|
227
|
+
* @function CommandCursor.prototype.hasNext
|
|
228
|
+
* @param {CommandCursor~resultCallback} [callback] The result callback.
|
|
229
|
+
* @throws {MongoError}
|
|
230
|
+
* @return {Promise} returns Promise if no callback passed
|
|
231
|
+
*/
|
|
232
|
+
|
|
224
233
|
/**
|
|
225
234
|
* The callback format for results
|
|
226
235
|
* @callback CommandCursor~toArrayResultCallback
|
package/lib/cursor.js
CHANGED
|
@@ -941,6 +941,16 @@ var count = function(self, applySkipLimit, opts, callback) {
|
|
|
941
941
|
'count': self.s.ns.substr(delimiter+1), 'query': self.s.cmd.query
|
|
942
942
|
}
|
|
943
943
|
|
|
944
|
+
// Apply a readConcern if set
|
|
945
|
+
if(self.s.cmd.readConcern) {
|
|
946
|
+
command.readConcern = self.s.cmd.readConcern;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
// Apply a hint if set
|
|
950
|
+
if(self.s.cmd.hint) {
|
|
951
|
+
command.hint = self.s.cmd.hint;
|
|
952
|
+
}
|
|
953
|
+
|
|
944
954
|
if(typeof opts.maxTimeMS == 'number') {
|
|
945
955
|
command.maxTimeMS = opts.maxTimeMS;
|
|
946
956
|
} else if(self.s.cmd && typeof self.s.cmd.maxTimeMS == 'number') {
|
|
@@ -993,7 +1003,12 @@ define.classMethod('close', {callback: true, promise:true});
|
|
|
993
1003
|
* @return {Cursor}
|
|
994
1004
|
*/
|
|
995
1005
|
Cursor.prototype.map = function(transform) {
|
|
996
|
-
this.cursorState.transforms
|
|
1006
|
+
if(this.cursorState.transforms && this.cursorState.transforms.doc) {
|
|
1007
|
+
var oldTransform = this.cursorState.transforms.doc;
|
|
1008
|
+
this.cursorState.transforms.doc = function (doc) { return transform(oldTransform(doc)); };
|
|
1009
|
+
} else {
|
|
1010
|
+
this.cursorState.transforms = { doc: transform };
|
|
1011
|
+
}
|
|
997
1012
|
return this;
|
|
998
1013
|
}
|
|
999
1014
|
|
package/lib/db.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var EventEmitter = require('events').EventEmitter
|
|
4
|
+
, authenticate = require('./authenticate')
|
|
4
5
|
, inherits = require('util').inherits
|
|
5
6
|
, getSingleProperty = require('./utils').getSingleProperty
|
|
6
7
|
, shallowClone = require('./utils').shallowClone
|
|
@@ -461,6 +462,7 @@ Db.prototype.collection = function(name, options, callback) {
|
|
|
461
462
|
if(callback) callback(null, collection);
|
|
462
463
|
return collection;
|
|
463
464
|
} catch(err) {
|
|
465
|
+
// if(err instanceof MongoError && callback) return callback(err);
|
|
464
466
|
if(callback) return callback(err);
|
|
465
467
|
throw err;
|
|
466
468
|
}
|
|
@@ -1469,74 +1471,6 @@ Db.prototype.removeUser = function(username, options, callback) {
|
|
|
1469
1471
|
});
|
|
1470
1472
|
};
|
|
1471
1473
|
|
|
1472
|
-
var authenticate = function(self, username, password, options, callback) {
|
|
1473
|
-
// Did the user destroy the topology
|
|
1474
|
-
if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));
|
|
1475
|
-
|
|
1476
|
-
// the default db to authenticate against is 'self'
|
|
1477
|
-
// if authententicate is called from a retry context, it may be another one, like admin
|
|
1478
|
-
var authdb = options.dbName ? options.dbName : self.databaseName;
|
|
1479
|
-
authdb = self.authSource ? self.authSource : authdb;
|
|
1480
|
-
authdb = options.authdb ? options.authdb : authdb;
|
|
1481
|
-
authdb = options.authSource ? options.authSource : authdb;
|
|
1482
|
-
|
|
1483
|
-
// Callback
|
|
1484
|
-
var _callback = function(err, result) {
|
|
1485
|
-
if(self.listeners('authenticated').length > 0) {
|
|
1486
|
-
self.emit('authenticated', err, result);
|
|
1487
|
-
}
|
|
1488
|
-
|
|
1489
|
-
// Return to caller
|
|
1490
|
-
handleCallback(callback, err, result);
|
|
1491
|
-
}
|
|
1492
|
-
|
|
1493
|
-
// authMechanism
|
|
1494
|
-
var authMechanism = options.authMechanism || '';
|
|
1495
|
-
authMechanism = authMechanism.toUpperCase();
|
|
1496
|
-
|
|
1497
|
-
// If classic auth delegate to auth command
|
|
1498
|
-
if(authMechanism == 'MONGODB-CR') {
|
|
1499
|
-
self.s.topology.auth('mongocr', authdb, username, password, function(err) {
|
|
1500
|
-
if(err) return handleCallback(callback, err, false);
|
|
1501
|
-
_callback(null, true);
|
|
1502
|
-
});
|
|
1503
|
-
} else if(authMechanism == 'PLAIN') {
|
|
1504
|
-
self.s.topology.auth('plain', authdb, username, password, function(err) {
|
|
1505
|
-
if(err) return handleCallback(callback, err, false);
|
|
1506
|
-
_callback(null, true);
|
|
1507
|
-
});
|
|
1508
|
-
} else if(authMechanism == 'MONGODB-X509') {
|
|
1509
|
-
self.s.topology.auth('x509', authdb, username, password, function(err) {
|
|
1510
|
-
if(err) return handleCallback(callback, err, false);
|
|
1511
|
-
_callback(null, true);
|
|
1512
|
-
});
|
|
1513
|
-
} else if(authMechanism == 'SCRAM-SHA-1') {
|
|
1514
|
-
self.s.topology.auth('scram-sha-1', authdb, username, password, function(err) {
|
|
1515
|
-
if(err) return handleCallback(callback, err, false);
|
|
1516
|
-
_callback(null, true);
|
|
1517
|
-
});
|
|
1518
|
-
} else if(authMechanism == 'GSSAPI') {
|
|
1519
|
-
if(process.platform == 'win32') {
|
|
1520
|
-
self.s.topology.auth('sspi', authdb, username, password, options, function(err) {
|
|
1521
|
-
if(err) return handleCallback(callback, err, false);
|
|
1522
|
-
_callback(null, true);
|
|
1523
|
-
});
|
|
1524
|
-
} else {
|
|
1525
|
-
self.s.topology.auth('gssapi', authdb, username, password, options, function(err) {
|
|
1526
|
-
if(err) return handleCallback(callback, err, false);
|
|
1527
|
-
_callback(null, true);
|
|
1528
|
-
});
|
|
1529
|
-
}
|
|
1530
|
-
} else if(authMechanism == 'DEFAULT') {
|
|
1531
|
-
self.s.topology.auth('default', authdb, username, password, function(err) {
|
|
1532
|
-
if(err) return handleCallback(callback, err, false);
|
|
1533
|
-
_callback(null, true);
|
|
1534
|
-
});
|
|
1535
|
-
} else {
|
|
1536
|
-
handleCallback(callback, MongoError.create({message: f("authentication mechanism %s not supported", options.authMechanism), driver:true}));
|
|
1537
|
-
}
|
|
1538
|
-
}
|
|
1539
|
-
|
|
1540
1474
|
/**
|
|
1541
1475
|
* Authenticate a user against the server.
|
|
1542
1476
|
* @method
|
|
@@ -1546,44 +1480,11 @@ var authenticate = function(self, username, password, options, callback) {
|
|
|
1546
1480
|
* @param {string} [options.authMechanism=MONGODB-CR] The authentication mechanism to use, GSSAPI, MONGODB-CR, MONGODB-X509, PLAIN
|
|
1547
1481
|
* @param {Db~resultCallback} [callback] The command result callback
|
|
1548
1482
|
* @return {Promise} returns Promise if no callback passed
|
|
1483
|
+
* @deprecated This method will no longer be available in the next major release 3.x as MongoDB 3.6 will only allow auth against users in the admin db and will no longer allow multiple credentials on a socket. Please authenticate using MongoClient.connect with auth credentials.
|
|
1549
1484
|
*/
|
|
1550
1485
|
Db.prototype.authenticate = function(username, password, options, callback) {
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
// Shallow copy the options
|
|
1554
|
-
options = shallowClone(options);
|
|
1555
|
-
|
|
1556
|
-
// Set default mechanism
|
|
1557
|
-
if(!options.authMechanism) {
|
|
1558
|
-
options.authMechanism = 'DEFAULT';
|
|
1559
|
-
} else if(options.authMechanism != 'GSSAPI'
|
|
1560
|
-
&& options.authMechanism != 'DEFAULT'
|
|
1561
|
-
&& options.authMechanism != 'MONGODB-CR'
|
|
1562
|
-
&& options.authMechanism != 'MONGODB-X509'
|
|
1563
|
-
&& options.authMechanism != 'SCRAM-SHA-1'
|
|
1564
|
-
&& options.authMechanism != 'PLAIN') {
|
|
1565
|
-
return handleCallback(callback, MongoError.create({message: "only DEFAULT, GSSAPI, PLAIN, MONGODB-X509, SCRAM-SHA-1 or MONGODB-CR is supported by authMechanism", driver:true}));
|
|
1566
|
-
}
|
|
1567
|
-
|
|
1568
|
-
// If we have a callback fallback
|
|
1569
|
-
if(typeof callback == 'function') return authenticate(self, username, password, options, function(err, r) {
|
|
1570
|
-
// Support failed auth method
|
|
1571
|
-
if(err && err.message && err.message.indexOf('saslStart') != -1) err.code = 59;
|
|
1572
|
-
// Reject error
|
|
1573
|
-
if(err) return callback(err, r);
|
|
1574
|
-
callback(null, r);
|
|
1575
|
-
});
|
|
1576
|
-
|
|
1577
|
-
// Return a promise
|
|
1578
|
-
return new this.s.promiseLibrary(function(resolve, reject) {
|
|
1579
|
-
authenticate(self, username, password, options, function(err, r) {
|
|
1580
|
-
// Support failed auth method
|
|
1581
|
-
if(err && err.message && err.message.indexOf('saslStart') != -1) err.code = 59;
|
|
1582
|
-
// Reject error
|
|
1583
|
-
if(err) return reject(err);
|
|
1584
|
-
resolve(r);
|
|
1585
|
-
});
|
|
1586
|
-
});
|
|
1486
|
+
console.warn("Db.prototype.authenticate method will no longer be available in the next major release 3.x as MongoDB 3.6 will only allow auth against users in the admin db and will no longer allow multiple credentials on a socket. Please authenticate using MongoClient.connect with auth credentials.");
|
|
1487
|
+
return authenticate.apply(this, [this].concat(Array.prototype.slice.call(arguments)));
|
|
1587
1488
|
};
|
|
1588
1489
|
|
|
1589
1490
|
define.classMethod('authenticate', {callback: true, promise:true});
|
package/lib/gridfs/grid_store.js
CHANGED
|
@@ -427,20 +427,23 @@ var writeFile = function(self, file, callback) {
|
|
|
427
427
|
|
|
428
428
|
// Write a chunk
|
|
429
429
|
var writeChunk = function() {
|
|
430
|
-
|
|
430
|
+
// Allocate the buffer
|
|
431
|
+
var _buffer = new Buffer(self.chunkSize);
|
|
432
|
+
// Read the file
|
|
433
|
+
fs.read(file, _buffer, 0, _buffer.length, offset, function(err, bytesRead, data) {
|
|
431
434
|
if(err) return callback(err, self);
|
|
432
435
|
|
|
433
436
|
offset = offset + bytesRead;
|
|
434
437
|
|
|
435
438
|
// Create a new chunk for the data
|
|
436
439
|
var chunk = new Chunk(self, {n:index++}, self.writeConcern);
|
|
437
|
-
chunk.write(data, function(err, chunk) {
|
|
440
|
+
chunk.write(data.slice(0, bytesRead), function(err, chunk) {
|
|
438
441
|
if(err) return callback(err, self);
|
|
439
442
|
|
|
440
443
|
chunk.save({}, function(err) {
|
|
441
444
|
if(err) return callback(err, self);
|
|
442
445
|
|
|
443
|
-
self.position = self.position +
|
|
446
|
+
self.position = self.position + bytesRead;
|
|
444
447
|
|
|
445
448
|
// Point to current chunk
|
|
446
449
|
self.currentChunk = chunk;
|
|
@@ -298,15 +298,27 @@ function init(self) {
|
|
|
298
298
|
return;
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
-
self.s.
|
|
301
|
+
self.s.bytesToSkip = handleStartOption(self, doc, self.s.options);
|
|
302
|
+
|
|
303
|
+
var filter = { files_id: doc._id };
|
|
304
|
+
|
|
305
|
+
// Currently (MongoDB 3.4.4) skip function does not support the index,
|
|
306
|
+
// it needs to retrieve all the documents first and then skip them. (CS-25811)
|
|
307
|
+
// As work around we use $gte on the "n" field.
|
|
308
|
+
if (self.s.options && self.s.options.start != null){
|
|
309
|
+
var skip = Math.floor(self.s.options.start / doc.chunkSize);
|
|
310
|
+
if (skip > 0){
|
|
311
|
+
filter["n"] = {"$gte": skip};
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
self.s.cursor = self.s.chunks.find(filter).sort({ n: 1 });
|
|
315
|
+
|
|
302
316
|
if (self.s.readPreference) {
|
|
303
317
|
self.s.cursor.setReadPreference(self.s.readPreference);
|
|
304
318
|
}
|
|
305
319
|
|
|
306
320
|
self.s.expectedEnd = Math.ceil(doc.length / doc.chunkSize);
|
|
307
321
|
self.s.file = doc;
|
|
308
|
-
self.s.bytesToSkip = handleStartOption(self, doc, self.s.cursor,
|
|
309
|
-
self.s.options);
|
|
310
322
|
self.s.bytesToTrim = handleEndOption(self, doc, self.s.cursor,
|
|
311
323
|
self.s.options);
|
|
312
324
|
self.emit('file', doc);
|
|
@@ -336,11 +348,11 @@ function waitForFile(_this, callback) {
|
|
|
336
348
|
* @ignore
|
|
337
349
|
*/
|
|
338
350
|
|
|
339
|
-
function handleStartOption(stream, doc,
|
|
351
|
+
function handleStartOption(stream, doc, options) {
|
|
340
352
|
if (options && options.start != null) {
|
|
341
353
|
if (options.start > doc.length) {
|
|
342
354
|
throw new Error('Stream start (' + options.start + ') must not be ' +
|
|
343
|
-
'more than the length of the file (' + doc.length +')')
|
|
355
|
+
'more than the length of the file (' + doc.length +')');
|
|
344
356
|
}
|
|
345
357
|
if (options.start < 0) {
|
|
346
358
|
throw new Error('Stream start (' + options.start + ') must not be ' +
|
|
@@ -351,8 +363,6 @@ function handleStartOption(stream, doc, cursor, options) {
|
|
|
351
363
|
'greater than stream end (' + options.end + ')');
|
|
352
364
|
}
|
|
353
365
|
|
|
354
|
-
cursor.skip(Math.floor(options.start / doc.chunkSize));
|
|
355
|
-
|
|
356
366
|
stream.s.bytesRead = Math.floor(options.start / doc.chunkSize) *
|
|
357
367
|
doc.chunkSize;
|
|
358
368
|
stream.s.expected = Math.floor(options.start / doc.chunkSize);
|
|
@@ -33,6 +33,8 @@ function GridFSBucketWriteStream(bucket, filename, options) {
|
|
|
33
33
|
this.filename = filename;
|
|
34
34
|
this.files = bucket.s._filesCollection;
|
|
35
35
|
this.options = options;
|
|
36
|
+
// Signals the write is all done
|
|
37
|
+
this.done = false;
|
|
36
38
|
|
|
37
39
|
this.id = options.id ? options.id : core.BSON.ObjectId();
|
|
38
40
|
this.chunkSizeBytes = this.options.chunkSizeBytes;
|
|
@@ -252,9 +254,13 @@ function checkChunksIndex(_this, callback) {
|
|
|
252
254
|
*/
|
|
253
255
|
|
|
254
256
|
function checkDone(_this, callback) {
|
|
257
|
+
if(_this.done) return true;
|
|
255
258
|
if (_this.state.streamEnd &&
|
|
256
259
|
_this.state.outstandingRequests === 0 &&
|
|
257
260
|
!_this.state.errored) {
|
|
261
|
+
// Set done so we dont' trigger duplicate createFilesDoc
|
|
262
|
+
_this.done = true;
|
|
263
|
+
// Create a new files doc
|
|
258
264
|
var filesDoc = createFilesDoc(_this.id, _this.length, _this.chunkSizeBytes,
|
|
259
265
|
_this.md5.digest('hex'), _this.filename, _this.options.contentType,
|
|
260
266
|
_this.options.aliases, _this.options.metadata);
|
|
@@ -421,6 +427,7 @@ function doWrite(_this, chunk, encoding, callback) {
|
|
|
421
427
|
}
|
|
422
428
|
--_this.state.outstandingRequests;
|
|
423
429
|
--outstandingRequests;
|
|
430
|
+
|
|
424
431
|
if (!outstandingRequests) {
|
|
425
432
|
_this.emit('drain', doc);
|
|
426
433
|
callback && callback();
|