summaryrefslogtreecommitdiff
path: root/src/mongo/shell
diff options
context:
space:
mode:
authorSara Golemon <sara.golemon@mongodb.com>2018-10-11 16:29:07 +0000
committerSara Golemon <sara.golemon@mongodb.com>2018-10-15 21:00:06 +0000
commitce7d8e88d3ffa8a1415a5f0c915ffe65b718e637 (patch)
tree050bf6d25c33d3b6ccbf0824adce6d35380ee3ed /src/mongo/shell
parent1edcd827fb96c39f7011d88d4b0a0b7e261dc353 (diff)
downloadmongo-ce7d8e88d3ffa8a1415a5f0c915ffe65b718e637.tar.gz
SERVER-36262 Support inferring database names from privileges in mongo shell when speaking to pre-4.0 mongod
Diffstat (limited to 'src/mongo/shell')
-rw-r--r--src/mongo/shell/mongo.js73
1 files changed, 69 insertions, 4 deletions
diff --git a/src/mongo/shell/mongo.js b/src/mongo/shell/mongo.js
index 4db8924a8ec..9a2f21544ef 100644
--- a/src/mongo/shell/mongo.js
+++ b/src/mongo/shell/mongo.js
@@ -56,15 +56,80 @@ Mongo.prototype.getDB = function(name) {
return new DB(this, name);
};
-Mongo.prototype.getDBs = function(driverSession = this._getDefaultSession()) {
- var cmdObj = {listDatabases: 1};
+Mongo.prototype._getDatabaseNamesFromPrivileges = function() {
+ 'use strict';
+
+ const ret = this.adminCommand({connectionStatus: 1, showPrivileges: 1});
+ if (!ret.ok) {
+ throw _getErrorWithCode(res, "Failed to acquire database information from privileges");
+ }
+
+ const privileges = (ret.authInfo || {}).authenticatedUserPrivileges;
+ if (privileges === undefined) {
+ return [];
+ }
+
+ return privileges
+ .filter(function(priv) {
+ // Find all named databases in priv list.
+ return ((priv.resource || {}).db || '').length > 0;
+ })
+ .map(function(priv) {
+ // Return just the names.
+ return priv.resource.db;
+ })
+ .filter(function(db, idx, arr) {
+ // Make sure the list is unique
+ return arr.indexOf(db) === idx;
+ })
+ .sort();
+};
+
+Mongo.prototype.getDBs = function(driverSession = this._getDefaultSession(),
+ filter = {},
+ nameOnly = undefined,
+ authorizedDatabases = undefined) {
+ 'use strict';
+
+ let cmdObj = {listDatabases: 1};
+ if (filter) {
+ cmdObj.filter = filter;
+ }
+ if (nameOnly !== undefined) {
+ cmdObj.nameOnly = nameOnly;
+ }
+ if (authorizedDatabases !== undefined) {
+ cmdObj.authorizedDatabases = authorizedDatabases;
+ }
+
if (driverSession._isExplicit || !jsTest.options().disableImplicitSessions) {
cmdObj = driverSession._serverSession.injectSessionId(cmdObj);
}
- var res = this.adminCommand(cmdObj);
- if (!res.ok)
+ const res = this.adminCommand(cmdObj);
+ if (!res.ok) {
+ // If "Unauthorized" was returned by the back end and we haven't explicitly
+ // asked for anything difficult to provide from userspace, then we can
+ // fallback on inspecting the user's permissions.
+ // This means that:
+ // * filter should be empty, as reimplementing that logic is out of scope.
+ // * nameOnly should not be false as we can't infer size information.
+ // * authorizedDatabases should not be false as those are the only DBs we can infer.
+ // Note that if the above are true and we get Unauthorized, that also means
+ // that we MUST be talking to a pre-4.0 mongod.
+ if ((res.code === ErrorCodes.Unauthorized) && !filter && (nameOnly !== false) &&
+ (authorizedDatabases !== false)) {
+ return this._getDatabaseNamesFromPrivileges();
+ }
throw _getErrorWithCode(res, "listDatabases failed:" + tojson(res));
+ }
+
+ if (nameOnly) {
+ return res.databases.map(function(db) {
+ return db.name;
+ });
+ }
+
return res;
};