summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/auth/role_management_commands_lib.js (renamed from jstests/auth/role_management_commands.js)126
-rw-r--r--jstests/auth/role_management_commands_sharded_wc_1.js10
-rw-r--r--jstests/auth/role_management_commands_sharded_wc_majority.js10
-rw-r--r--jstests/auth/role_management_commands_standalone.js9
-rw-r--r--jstests/auth/user_management_commands_lib.js (renamed from jstests/auth/user_management_commands.js)87
-rw-r--r--jstests/auth/user_management_commands_sharded_wc_1.js9
-rw-r--r--jstests/auth/user_management_commands_sharded_wc_majority.js9
-rw-r--r--jstests/auth/user_management_commands_standalone.js9
-rw-r--r--src/mongo/db/write_concern_options.cpp4
-rw-r--r--src/mongo/db/write_concern_options.h1
-rw-r--r--src/mongo/s/catalog/replset/sharding_catalog_client_impl.cpp49
-rw-r--r--src/mongo/s/catalog/replset/sharding_catalog_test.cpp78
12 files changed, 253 insertions, 148 deletions
diff --git a/jstests/auth/role_management_commands.js b/jstests/auth/role_management_commands_lib.js
index af2f7709bf1..e1ff7860950 100644
--- a/jstests/auth/role_management_commands.js
+++ b/jstests/auth/role_management_commands_lib.js
@@ -2,20 +2,21 @@
* This tests that all the different commands for role manipulation all work properly for all valid
* forms of input.
*/
+function runAllRoleManagementCommandsTests(conn, writeConcern) {
+ 'use strict';
-function runTest(conn) {
- var authzErrorCode = 13;
var hasAuthzError = function(result) {
assert(result.hasWriteError());
- assert.eq(authzErrorCode, result.getWriteError().code);
+ assert.eq(ErrorCodes.Unauthorized, result.getWriteError().code);
};
var userAdminConn = new Mongo(conn.host);
var testUserAdmin = userAdminConn.getDB('test');
var adminUserAdmin = userAdminConn.getDB('admin');
- adminUserAdmin.createUser({user: 'userAdmin', pwd: 'pwd', roles: ['userAdminAnyDatabase']});
+ adminUserAdmin.createUser({user: 'userAdmin', pwd: 'pwd', roles: ['userAdminAnyDatabase']},
+ writeConcern);
adminUserAdmin.auth('userAdmin', 'pwd');
- testUserAdmin.createUser({user: 'testUser', pwd: 'pwd', roles: []});
+ testUserAdmin.createUser({user: 'testUser', pwd: 'pwd', roles: []}, writeConcern);
var db = conn.getDB('test');
assert(db.auth('testUser', 'pwd'));
@@ -30,25 +31,30 @@ function runTest(conn) {
(function testCreateRole() {
jsTestLog("Testing createRole");
- testUserAdmin.createRole({role: "testRole1", roles: ['read'], privileges: []});
+ testUserAdmin.createRole({role: "testRole1", roles: ['read'], privileges: []},
+ writeConcern);
testUserAdmin.createRole({
role: "testRole2",
roles: [],
privileges: [{resource: {db: 'test', collection: 'foo'}, actions: ['insert']}]
- });
+ },
+ writeConcern);
testUserAdmin.createRole({
role: "testRole3",
roles: ['testRole1', {role: 'testRole2', db: 'test'}],
privileges: []
- });
- testUserAdmin.createRole({role: "testRole4", roles: [], privileges: []});
+ },
+ writeConcern);
+ testUserAdmin.createRole({role: "testRole4", roles: [], privileges: []}, writeConcern);
adminUserAdmin.createRole({
role: "adminRole",
roles: [],
privileges: [{resource: {cluster: true}, actions: ['connPoolSync']}]
- });
+ },
+ writeConcern);
- testUserAdmin.updateUser('testUser', {roles: [{role: 'adminRole', db: 'admin'}]});
+ testUserAdmin.updateUser(
+ 'testUser', {roles: [{role: 'adminRole', db: 'admin'}]}, writeConcern);
assert.throws(function() {
db.foo.findOne();
});
@@ -56,24 +62,24 @@ function runTest(conn) {
hasAuthzError(db.foo.update({}, {$inc: {a: 1}}, false, true));
assert.commandWorked(db.adminCommand('connPoolSync'));
- testUserAdmin.updateUser('testUser', {roles: ['testRole1']});
+ testUserAdmin.updateUser('testUser', {roles: ['testRole1']}, writeConcern);
assert.doesNotThrow(function() {
db.foo.findOne();
});
assert.eq(0, db.foo.count());
hasAuthzError(db.foo.insert({a: 1}));
hasAuthzError(db.foo.update({}, {$inc: {a: 1}}, false, true));
- assert.commandFailedWithCode(db.adminCommand('connPoolSync'), authzErrorCode);
+ assert.commandFailedWithCode(db.adminCommand('connPoolSync'), ErrorCodes.Unauthorized);
- testUserAdmin.updateUser('testUser', {roles: ['testRole2']});
+ testUserAdmin.updateUser('testUser', {roles: ['testRole2']}, writeConcern);
assert.throws(function() {
db.foo.findOne();
});
assert.writeOK(db.foo.insert({a: 1}));
hasAuthzError(db.foo.update({}, {$inc: {a: 1}}, false, true));
- assert.commandFailedWithCode(db.adminCommand('connPoolSync'), authzErrorCode);
+ assert.commandFailedWithCode(db.adminCommand('connPoolSync'), ErrorCodes.Unauthorized);
- testUserAdmin.updateUser('testUser', {roles: ['testRole3']});
+ testUserAdmin.updateUser('testUser', {roles: ['testRole3']}, writeConcern);
assert.doesNotThrow(function() {
db.foo.findOne();
});
@@ -82,32 +88,34 @@ function runTest(conn) {
assert.eq(2, db.foo.count());
hasAuthzError(db.foo.update({}, {$inc: {a: 1}}, false, true));
assert.eq(1, db.foo.findOne().a);
- assert.commandFailedWithCode(db.adminCommand('connPoolSync'), authzErrorCode);
+ assert.commandFailedWithCode(db.adminCommand('connPoolSync'), ErrorCodes.Unauthorized);
- testUserAdmin.updateUser('testUser', {roles: [{role: 'testRole4', db: 'test'}]});
+ testUserAdmin.updateUser(
+ 'testUser', {roles: [{role: 'testRole4', db: 'test'}]}, writeConcern);
assert.throws(function() {
db.foo.findOne();
});
hasAuthzError(db.foo.insert({a: 1}));
hasAuthzError(db.foo.update({}, {$inc: {a: 1}}, false, true));
- assert.commandFailedWithCode(db.adminCommand('connPoolSync'), authzErrorCode);
+ assert.commandFailedWithCode(db.adminCommand('connPoolSync'), ErrorCodes.Unauthorized);
})();
(function testUpdateRole() {
jsTestLog("Testing updateRole");
- testUserAdmin.updateRole('testRole4',
- {roles: [{role: 'testRole2', db: 'test'}, "testRole2"]});
+ testUserAdmin.updateRole(
+ 'testRole4', {roles: [{role: 'testRole2', db: 'test'}, "testRole2"]}, writeConcern);
assert.throws(function() {
db.foo.findOne();
});
assert.writeOK(db.foo.insert({a: 1}));
hasAuthzError(db.foo.update({}, {$inc: {a: 1}}, false, true));
- assert.commandFailedWithCode(db.adminCommand('connPoolSync'), authzErrorCode);
+ assert.commandFailedWithCode(db.adminCommand('connPoolSync'), ErrorCodes.Unauthorized);
testUserAdmin.updateRole(
'testRole4',
- {privileges: [{resource: {db: 'test', collection: ''}, actions: ['find']}]});
+ {privileges: [{resource: {db: 'test', collection: ''}, actions: ['find']}]},
+ writeConcern);
assert.doesNotThrow(function() {
db.foo.findOne();
});
@@ -116,9 +124,9 @@ function runTest(conn) {
assert.eq(4, db.foo.count());
hasAuthzError(db.foo.update({}, {$inc: {a: 1}}, false, true));
assert.eq(1, db.foo.findOne().a);
- assert.commandFailedWithCode(db.adminCommand('connPoolSync'), authzErrorCode);
+ assert.commandFailedWithCode(db.adminCommand('connPoolSync'), ErrorCodes.Unauthorized);
- testUserAdmin.updateRole('testRole4', {roles: []});
+ testUserAdmin.updateRole('testRole4', {roles: []}, writeConcern);
assert.doesNotThrow(function() {
db.foo.findOne();
});
@@ -127,10 +135,11 @@ function runTest(conn) {
assert.eq(4, db.foo.count());
hasAuthzError(db.foo.update({}, {$inc: {a: 1}}, false, true));
assert.eq(1, db.foo.findOne().a);
- assert.commandFailedWithCode(db.adminCommand('connPoolSync'), authzErrorCode);
+ assert.commandFailedWithCode(db.adminCommand('connPoolSync'), ErrorCodes.Unauthorized);
- testUserAdmin.updateUser('testUser', {roles: [{role: 'adminRole', db: 'admin'}]});
- adminUserAdmin.updateRole('adminRole', {roles: [{role: 'read', db: 'test'}]});
+ testUserAdmin.updateUser(
+ 'testUser', {roles: [{role: 'adminRole', db: 'admin'}]}, writeConcern);
+ adminUserAdmin.updateRole('adminRole', {roles: [{role: 'read', db: 'test'}]}, writeConcern);
assert.doesNotThrow(function() {
db.foo.findOne();
});
@@ -145,11 +154,12 @@ function runTest(conn) {
(function testGrantRolesToRole() {
jsTestLog("Testing grantRolesToRole");
- assert.commandFailedWithCode(db.adminCommand('serverStatus'), authzErrorCode);
+ assert.commandFailedWithCode(db.adminCommand('serverStatus'), ErrorCodes.Unauthorized);
adminUserAdmin.grantRolesToRole(
"adminRole",
- ['clusterMonitor', {role: 'read', db: 'test'}, {role: 'testRole2', db: 'test'}]);
+ ['clusterMonitor', {role: 'read', db: 'test'}, {role: 'testRole2', db: 'test'}],
+ writeConcern);
assert.doesNotThrow(function() {
db.foo.findOne();
});
@@ -167,23 +177,27 @@ function runTest(conn) {
adminUserAdmin.revokeRolesFromRole(
"adminRole",
- ['clusterMonitor', {role: 'read', db: 'test'}, {role: 'testRole2', db: 'test'}]);
+ ['clusterMonitor', {role: 'read', db: 'test'}, {role: 'testRole2', db: 'test'}],
+ writeConcern);
assert.throws(function() {
db.foo.findOne();
});
hasAuthzError(db.foo.insert({a: 1}));
hasAuthzError(db.foo.update({}, {$inc: {a: 1}}, false, true));
assert.commandWorked(db.adminCommand('connPoolSync'));
- assert.commandFailedWithCode(db.adminCommand('serverStatus'), authzErrorCode);
+ assert.commandFailedWithCode(db.adminCommand('serverStatus'), ErrorCodes.Unauthorized);
})();
(function testGrantPrivilegesToRole() {
jsTestLog("Testing grantPrivilegesToRole");
- adminUserAdmin.grantPrivilegesToRole('adminRole', [
- {resource: {cluster: true}, actions: ['serverStatus']},
- {resource: {db: "", collection: ""}, actions: ['find']}
- ]);
+ adminUserAdmin.grantPrivilegesToRole(
+ 'adminRole',
+ [
+ {resource: {cluster: true}, actions: ['serverStatus']},
+ {resource: {db: "", collection: ""}, actions: ['find']}
+ ],
+ writeConcern);
assert.doesNotThrow(function() {
db.foo.findOne();
});
@@ -194,11 +208,14 @@ function runTest(conn) {
assert.commandWorked(db.adminCommand('connPoolSync'));
assert.commandWorked(db.adminCommand('serverStatus'));
- testUserAdmin.updateUser('testUser', {roles: ['testRole2']});
- testUserAdmin.grantPrivilegesToRole('testRole2', [
- {resource: {db: 'test', collection: ''}, actions: ['insert', 'update']},
- {resource: {db: 'test', collection: 'foo'}, actions: ['find']}
- ]);
+ testUserAdmin.updateUser('testUser', {roles: ['testRole2']}, writeConcern);
+ testUserAdmin.grantPrivilegesToRole(
+ 'testRole2',
+ [
+ {resource: {db: 'test', collection: ''}, actions: ['insert', 'update']},
+ {resource: {db: 'test', collection: 'foo'}, actions: ['find']}
+ ],
+ writeConcern);
assert.doesNotThrow(function() {
db.foo.findOne();
});
@@ -206,8 +223,8 @@ function runTest(conn) {
assert.eq(6, db.foo.count());
assert.writeOK(db.foo.update({}, {$inc: {a: 1}}, false, true));
assert.eq(2, db.foo.findOne().a);
- assert.commandFailedWithCode(db.adminCommand('connPoolSync'), authzErrorCode);
- assert.commandFailedWithCode(db.adminCommand('serverStatus'), authzErrorCode);
+ assert.commandFailedWithCode(db.adminCommand('connPoolSync'), ErrorCodes.Unauthorized);
+ assert.commandFailedWithCode(db.adminCommand('serverStatus'), ErrorCodes.Unauthorized);
})();
(function testRevokePrivilegesFromRole() {
@@ -215,7 +232,8 @@ function runTest(conn) {
testUserAdmin.revokePrivilegesFromRole(
'testRole2',
- [{resource: {db: 'test', collection: ''}, actions: ['insert', 'update', 'find']}]);
+ [{resource: {db: 'test', collection: ''}, actions: ['insert', 'update', 'find']}],
+ writeConcern);
assert.doesNotThrow(function() {
db.foo.findOne();
});
@@ -223,8 +241,8 @@ function runTest(conn) {
assert.eq(7, db.foo.count());
hasAuthzError(db.foo.update({}, {$inc: {a: 1}}, false, true));
assert.eq(2, db.foo.findOne().a);
- assert.commandFailedWithCode(db.adminCommand('connPoolSync'), authzErrorCode);
- assert.commandFailedWithCode(db.adminCommand('serverStatus'), authzErrorCode);
+ assert.commandFailedWithCode(db.adminCommand('connPoolSync'), ErrorCodes.Unauthorized);
+ assert.commandFailedWithCode(db.adminCommand('serverStatus'), ErrorCodes.Unauthorized);
})();
(function testRolesInfo() {
@@ -265,7 +283,7 @@ function runTest(conn) {
(function testDropRole() {
jsTestLog("Testing dropRole");
- testUserAdmin.grantRolesToUser('testUser', ['testRole4']);
+ testUserAdmin.grantRolesToUser('testUser', ['testRole4'], writeConcern);
assert.doesNotThrow(function() {
db.foo.findOne();
@@ -273,7 +291,7 @@ function runTest(conn) {
assert.writeOK(db.foo.insert({a: 1}));
assert.eq(8, db.foo.count());
- assert.commandWorked(testUserAdmin.runCommand({dropRole: 'testRole2'}));
+ testUserAdmin.dropRole('testRole2', writeConcern);
assert.doesNotThrow(function() {
db.foo.findOne();
@@ -292,7 +310,7 @@ function runTest(conn) {
});
assert.eq(3, testUserAdmin.getRoles().length);
- assert.commandWorked(testUserAdmin.runCommand({dropAllRolesFromDatabase: 1}));
+ testUserAdmin.dropAllRoles(writeConcern);
assert.throws(function() {
db.foo.findOne();
@@ -300,13 +318,3 @@ function runTest(conn) {
assert.eq(0, testUserAdmin.getRoles().length);
})();
}
-
-jsTest.log('Test standalone');
-var conn = MongoRunner.runMongod({auth: '', useHostname: false});
-runTest(conn);
-MongoRunner.stopMongod(conn.port);
-
-jsTest.log('Test sharding');
-var st = new ShardingTest({shards: 2, config: 3, keyFile: 'jstests/libs/key1', useHostname: false});
-runTest(st.s);
-st.stop();
diff --git a/jstests/auth/role_management_commands_sharded_wc_1.js b/jstests/auth/role_management_commands_sharded_wc_1.js
new file mode 100644
index 00000000000..78ce948802b
--- /dev/null
+++ b/jstests/auth/role_management_commands_sharded_wc_1.js
@@ -0,0 +1,10 @@
+(function() {
+ 'use strict';
+
+ load('jstests/auth/role_management_commands_lib.js');
+
+ var st =
+ new ShardingTest({shards: 2, config: 3, keyFile: 'jstests/libs/key1', useHostname: false});
+ runAllRoleManagementCommandsTests(st.s, {w: 1});
+ st.stop();
+})();
diff --git a/jstests/auth/role_management_commands_sharded_wc_majority.js b/jstests/auth/role_management_commands_sharded_wc_majority.js
new file mode 100644
index 00000000000..19aa8e2c37e
--- /dev/null
+++ b/jstests/auth/role_management_commands_sharded_wc_majority.js
@@ -0,0 +1,10 @@
+(function() {
+ 'use strict';
+
+ load('jstests/auth/role_management_commands_lib.js');
+
+ var st =
+ new ShardingTest({shards: 2, config: 3, keyFile: 'jstests/libs/key1', useHostname: false});
+ runAllRoleManagementCommandsTests(st.s, {w: 'majority', wtimeout: 60 * 1000});
+ st.stop();
+})();
diff --git a/jstests/auth/role_management_commands_standalone.js b/jstests/auth/role_management_commands_standalone.js
new file mode 100644
index 00000000000..38f848f9936
--- /dev/null
+++ b/jstests/auth/role_management_commands_standalone.js
@@ -0,0 +1,9 @@
+(function() {
+ 'use strict';
+
+ load('jstests/auth/role_management_commands_lib.js');
+
+ var conn = MongoRunner.runMongod({auth: '', useHostname: false});
+ runAllRoleManagementCommandsTests(conn);
+ MongoRunner.stopMongod(conn.port);
+})();
diff --git a/jstests/auth/user_management_commands.js b/jstests/auth/user_management_commands_lib.js
index a5cca448576..424fe5ef4ee 100644
--- a/jstests/auth/user_management_commands.js
+++ b/jstests/auth/user_management_commands_lib.js
@@ -2,22 +2,23 @@
* This tests that all the different commands for user manipulation all work properly for all valid
* forms of input.
*/
+function runAllUserManagementCommandsTests(conn, writeConcern) {
+ 'use strict';
-function runTest(conn) {
- var authzErrorCode = 13;
var hasAuthzError = function(result) {
assert(result.hasWriteError());
- assert.eq(authzErrorCode, result.getWriteError().code);
+ assert.eq(ErrorCodes.Unauthorized, result.getWriteError().code);
};
- conn.getDB('admin').createUser({user: 'admin', pwd: 'pwd', roles: ['root']});
+ conn.getDB('admin').createUser({user: 'admin', pwd: 'pwd', roles: ['root']}, writeConcern);
conn.getDB('admin').auth('admin', 'pwd');
conn.getDB('admin').createUser({
user: 'userAdmin',
pwd: 'pwd',
roles: ['userAdminAnyDatabase'],
customData: {userAdmin: true}
- });
+ },
+ writeConcern);
conn.getDB('admin').logout();
var userAdminConn = new Mongo(conn.host);
@@ -27,12 +28,14 @@ function runTest(conn) {
role: 'testRole',
roles: [],
privileges: [{resource: {db: 'test', collection: ''}, actions: ['viewRole']}],
- });
+ },
+ writeConcern);
userAdminConn.getDB('admin').createRole({
role: 'adminRole',
roles: [],
privileges: [{resource: {cluster: true}, actions: ['connPoolSync']}]
- });
+ },
+ writeConcern);
var db = conn.getDB('test');
@@ -51,8 +54,9 @@ function runTest(conn) {
pwd: "pwd",
customData: {zipCode: 10028},
roles: ['readWrite', 'testRole', {role: 'adminRole', db: 'admin'}]
- });
- testUserAdmin.createUser({user: "andy", pwd: "pwd", roles: []});
+ },
+ writeConcern);
+ testUserAdmin.createUser({user: "andy", pwd: "pwd", roles: []}, writeConcern);
var user = testUserAdmin.getUser('spencer');
assert.eq(10028, user.customData.zipCode);
@@ -78,14 +82,14 @@ function runTest(conn) {
(function testUpdateUser() {
jsTestLog("Testing updateUser");
- testUserAdmin.updateUser('spencer', {pwd: 'password', customData: {}});
+ testUserAdmin.updateUser('spencer', {pwd: 'password', customData: {}}, writeConcern);
var user = testUserAdmin.getUser('spencer');
assert.eq(null, user.customData.zipCode);
assert(!db.auth('spencer', 'pwd'));
assert(db.auth('spencer', 'password'));
- testUserAdmin.updateUser('spencer',
- {customData: {zipCode: 10036}, roles: ["read", "testRole"]});
+ testUserAdmin.updateUser(
+ 'spencer', {customData: {zipCode: 10036}, roles: ["read", "testRole"]}, writeConcern);
var user = testUserAdmin.getUser('spencer');
assert.eq(10036, user.customData.zipCode);
hasAuthzError(db.foo.insert({a: 1}));
@@ -94,10 +98,10 @@ function runTest(conn) {
assert.doesNotThrow(function() {
db.getRole('testRole');
});
- assert.commandFailedWithCode(db.adminCommand('connPoolSync'), authzErrorCode);
+ assert.commandFailedWithCode(db.adminCommand('connPoolSync'), ErrorCodes.Unauthorized);
- testUserAdmin.updateUser('spencer',
- {roles: ["readWrite", {role: 'adminRole', db: 'admin'}]});
+ testUserAdmin.updateUser(
+ 'spencer', {roles: ["readWrite", {role: 'adminRole', db: 'admin'}]}, writeConcern);
assert.writeOK(db.foo.update({}, {$inc: {a: 1}}));
assert.eq(2, db.foo.findOne().a);
assert.eq(1, db.foo.count());
@@ -111,15 +115,17 @@ function runTest(conn) {
jsTestLog("Testing grantRolesToUser");
assert.commandFailedWithCode(db.runCommand({collMod: 'foo', usePowerOf2Sizes: true}),
- authzErrorCode);
-
- testUserAdmin.grantRolesToUser('spencer', [
- 'readWrite',
- 'dbAdmin',
- {role: 'readWrite', db: 'test'},
- {role: 'testRole', db: 'test'},
- 'readWrite'
- ]);
+ ErrorCodes.Unauthorized);
+
+ testUserAdmin.grantRolesToUser('spencer',
+ [
+ 'readWrite',
+ 'dbAdmin',
+ {role: 'readWrite', db: 'test'},
+ {role: 'testRole', db: 'test'},
+ 'readWrite'
+ ],
+ writeConcern);
assert.commandWorked(db.runCommand({collMod: 'foo', usePowerOf2Sizes: true}));
assert.writeOK(db.foo.update({}, {$inc: {a: 1}}));
@@ -134,11 +140,14 @@ function runTest(conn) {
(function testRevokeRolesFromUser() {
jsTestLog("Testing revokeRolesFromUser");
- testUserAdmin.revokeRolesFromUser('spencer', [
- 'readWrite',
- {role: 'dbAdmin', db: 'test2'}, // role user doesnt have
- "testRole"
- ]);
+ testUserAdmin.revokeRolesFromUser(
+ 'spencer',
+ [
+ 'readWrite',
+ {role: 'dbAdmin', db: 'test2'}, // role user doesnt have
+ "testRole"
+ ],
+ writeConcern);
assert.commandWorked(db.runCommand({collMod: 'foo', usePowerOf2Sizes: true}));
hasAuthzError(db.foo.update({}, {$inc: {a: 1}}));
@@ -150,7 +159,8 @@ function runTest(conn) {
});
assert.commandWorked(db.adminCommand('connPoolSync'));
- testUserAdmin.revokeRolesFromUser('spencer', [{role: 'adminRole', db: 'admin'}]);
+ testUserAdmin.revokeRolesFromUser(
+ 'spencer', [{role: 'adminRole', db: 'admin'}], writeConcern);
hasAuthzError(db.foo.update({}, {$inc: {a: 1}}));
assert.throws(function() {
@@ -159,7 +169,7 @@ function runTest(conn) {
assert.throws(function() {
db.getRole('testRole');
});
- assert.commandFailedWithCode(db.adminCommand('connPoolSync'), authzErrorCode);
+ assert.commandFailedWithCode(db.adminCommand('connPoolSync'), ErrorCodes.Unauthorized);
})();
@@ -214,7 +224,7 @@ function runTest(conn) {
assert(db.auth('spencer', 'password'));
assert(db.auth('andy', 'pwd'));
- assert.commandWorked(testUserAdmin.runCommand({dropUser: 'spencer'}));
+ testUserAdmin.dropUser('spencer', writeConcern);
assert(!db.auth('spencer', 'password'));
assert(db.auth('andy', 'pwd'));
@@ -228,20 +238,9 @@ function runTest(conn) {
assert.eq(1, testUserAdmin.getUsers().length);
assert(db.auth('andy', 'pwd'));
- assert.commandWorked(testUserAdmin.runCommand({dropAllUsersFromDatabase: 1}));
+ testUserAdmin.dropAllUsers(writeConcern);
assert(!db.auth('andy', 'pwd'));
assert.eq(0, testUserAdmin.getUsers().length);
})();
}
-
-jsTest.log('Test standalone');
-var conn = MongoRunner.runMongod({auth: ''});
-conn.getDB('admin').runCommand({setParameter: 1, newCollectionsUsePowerOf2Sizes: false});
-runTest(conn);
-MongoRunner.stopMongod(conn.port);
-
-jsTest.log('Test sharding');
-var st = new ShardingTest({shards: 2, config: 3, keyFile: 'jstests/libs/key1'});
-runTest(st.s);
-st.stop();
diff --git a/jstests/auth/user_management_commands_sharded_wc_1.js b/jstests/auth/user_management_commands_sharded_wc_1.js
new file mode 100644
index 00000000000..ff5bc0cfc43
--- /dev/null
+++ b/jstests/auth/user_management_commands_sharded_wc_1.js
@@ -0,0 +1,9 @@
+(function() {
+ 'use strict';
+
+ load('jstests/auth/user_management_commands_lib.js');
+
+ var st = new ShardingTest({shards: 2, config: 3, keyFile: 'jstests/libs/key1'});
+ runAllUserManagementCommandsTests(st.s, {w: 1});
+ st.stop();
+})();
diff --git a/jstests/auth/user_management_commands_sharded_wc_majority.js b/jstests/auth/user_management_commands_sharded_wc_majority.js
new file mode 100644
index 00000000000..a18bc70e96a
--- /dev/null
+++ b/jstests/auth/user_management_commands_sharded_wc_majority.js
@@ -0,0 +1,9 @@
+(function() {
+ 'use strict';
+
+ load('jstests/auth/user_management_commands_lib.js');
+
+ var st = new ShardingTest({shards: 2, config: 3, keyFile: 'jstests/libs/key1'});
+ runAllUserManagementCommandsTests(st.s, {w: 'majority', wtimeout: 60 * 1000});
+ st.stop();
+})();
diff --git a/jstests/auth/user_management_commands_standalone.js b/jstests/auth/user_management_commands_standalone.js
new file mode 100644
index 00000000000..951ee1e9801
--- /dev/null
+++ b/jstests/auth/user_management_commands_standalone.js
@@ -0,0 +1,9 @@
+(function() {
+ 'use strict';
+
+ load('jstests/auth/user_management_commands_lib.js');
+
+ var conn = MongoRunner.runMongod({auth: '', useHostname: false});
+ runAllUserManagementCommandsTests(conn);
+ MongoRunner.stopMongod(conn.port);
+})();
diff --git a/src/mongo/db/write_concern_options.cpp b/src/mongo/db/write_concern_options.cpp
index 028d03d4635..dd9694dcc61 100644
--- a/src/mongo/db/write_concern_options.cpp
+++ b/src/mongo/db/write_concern_options.cpp
@@ -62,6 +62,7 @@ constexpr StringData kWElectionIdFieldName = "wElectionId"_sd;
const int WriteConcernOptions::kNoTimeout(0);
const int WriteConcernOptions::kNoWaiting(-1);
+const StringData WriteConcernOptions::kWriteConcernField = "writeConcern"_sd;
const char WriteConcernOptions::kMajority[] = "majority";
const BSONObj WriteConcernOptions::Default = BSONObj();
@@ -159,7 +160,8 @@ StatusWith<WriteConcernOptions> WriteConcernOptions::extractWCFromCommand(
}
BSONElement writeConcernElement;
- Status wcStatus = bsonExtractTypedField(cmdObj, "writeConcern", Object, &writeConcernElement);
+ Status wcStatus =
+ bsonExtractTypedField(cmdObj, kWriteConcernField, Object, &writeConcernElement);
if (!wcStatus.isOK()) {
if (wcStatus == ErrorCodes::NoSuchKey) {
// Return default write concern if no write concern is given.
diff --git a/src/mongo/db/write_concern_options.h b/src/mongo/db/write_concern_options.h
index 06ddfbc56a0..85f9e0e0390 100644
--- a/src/mongo/db/write_concern_options.h
+++ b/src/mongo/db/write_concern_options.h
@@ -47,6 +47,7 @@ public:
static const BSONObj Unacknowledged;
static const BSONObj Majority;
+ static const StringData kWriteConcernField;
static const char kMajority[]; // = "majority"
WriteConcernOptions() {
diff --git a/src/mongo/s/catalog/replset/sharding_catalog_client_impl.cpp b/src/mongo/s/catalog/replset/sharding_catalog_client_impl.cpp
index 0c9e47d976e..57d701a82a6 100644
--- a/src/mongo/s/catalog/replset/sharding_catalog_client_impl.cpp
+++ b/src/mongo/s/catalog/replset/sharding_catalog_client_impl.cpp
@@ -96,8 +96,6 @@ using str::stream;
namespace {
-const char kWriteConcernField[] = "writeConcern";
-
const ReadPreferenceSetting kConfigReadSelector(ReadPreference::Nearest, TagSet{});
const ReadPreferenceSetting kConfigPrimaryPreferredSelector(ReadPreference::PrimaryPreferred,
TagSet{});
@@ -767,12 +765,13 @@ Status ShardingCatalogClientImpl::dropCollection(OperationContext* txn, const Na
return {ErrorCodes::ShardNotFound,
str::stream() << "shard " << shardEntry.getName() << " not found"};
}
- auto dropResult = shard->runCommand(
- txn,
- ReadPreferenceSetting{ReadPreference::PrimaryOnly},
- ns.db().toString(),
- BSON("drop" << ns.coll() << "writeConcern" << txn->getWriteConcern().toBSON()),
- Shard::RetryPolicy::kIdempotent);
+ auto dropResult =
+ shard->runCommand(txn,
+ ReadPreferenceSetting{ReadPreference::PrimaryOnly},
+ ns.db().toString(),
+ BSON("drop" << ns.coll() << WriteConcernOptions::kWriteConcernField
+ << txn->getWriteConcern().toBSON()),
+ Shard::RetryPolicy::kIdempotent);
if (!dropResult.isOK()) {
return Status(dropResult.getStatus().code(),
@@ -1134,24 +1133,26 @@ bool ShardingCatalogClientImpl::runUserManagementWriteCommand(OperationContext*
// convert w:1 or no write concern to w:majority before sending.
WriteConcernOptions writeConcern;
writeConcern.reset();
- const char* writeConcernFieldName = "writeConcern";
- BSONElement writeConcernElement = cmdObj[writeConcernFieldName];
+
+ BSONElement writeConcernElement = cmdObj[WriteConcernOptions::kWriteConcernField];
bool initialCmdHadWriteConcern = !writeConcernElement.eoo();
if (initialCmdHadWriteConcern) {
Status status = writeConcern.parse(writeConcernElement.Obj());
if (!status.isOK()) {
return Command::appendCommandStatus(*result, status);
}
- if (!writeConcern.validForConfigServers()) {
+
+ if (!(writeConcern.wNumNodes == 1 ||
+ writeConcern.wMode == WriteConcernOptions::kMajority)) {
return Command::appendCommandStatus(
*result,
- Status(ErrorCodes::InvalidOptions,
- str::stream()
- << "Invalid replication write concern. Writes to config server "
- "replica sets must use w:'majority', got: "
- << writeConcern.toBSON()));
+ {ErrorCodes::InvalidOptions,
+ str::stream() << "Invalid replication write concern. User management write "
+ "commands may only use w:1 or w:'majority', got: "
+ << writeConcern.toBSON()});
}
}
+
writeConcern.wMode = WriteConcernOptions::kMajority;
writeConcern.wNumNodes = 0;
@@ -1162,13 +1163,13 @@ bool ShardingCatalogClientImpl::runUserManagementWriteCommand(OperationContext*
BSONObjIterator cmdObjIter(cmdObj);
while (cmdObjIter.more()) {
BSONElement e = cmdObjIter.next();
- if (str::equals(e.fieldName(), writeConcernFieldName)) {
+ if (WriteConcernOptions::kWriteConcernField == e.fieldName()) {
continue;
}
modifiedCmd.append(e);
}
}
- modifiedCmd.append(writeConcernFieldName, writeConcern.toBSON());
+ modifiedCmd.append(WriteConcernOptions::kWriteConcernField, writeConcern.toBSON());
cmdToRun = modifiedCmd.obj();
}
@@ -1230,9 +1231,9 @@ Status ShardingCatalogClientImpl::applyChunkOpsDeprecated(OperationContext* txn,
const BSONArray& preCondition,
const std::string& nss,
const ChunkVersion& lastChunkVersion) {
- BSONObj cmd =
- BSON("applyOps" << updateOps << "preCondition" << preCondition << kWriteConcernField
- << ShardingCatalogClient::kMajorityWriteConcern.toBSON());
+ BSONObj cmd = BSON("applyOps" << updateOps << "preCondition" << preCondition
+ << WriteConcernOptions::kWriteConcernField
+ << ShardingCatalogClient::kMajorityWriteConcern.toBSON());
auto response = Grid::get(txn)->shardRegistry()->getConfigShard()->runCommand(
txn,
@@ -1511,9 +1512,9 @@ Status ShardingCatalogClientImpl::_checkDbDoesNotExist(OperationContext* txn,
Status ShardingCatalogClientImpl::_createCappedConfigCollection(OperationContext* txn,
StringData collName,
int cappedSize) {
- BSONObj createCmd =
- BSON("create" << collName << "capped" << true << "size" << cappedSize << "writeConcern"
- << ShardingCatalogClient::kMajorityWriteConcern.toBSON());
+ BSONObj createCmd = BSON("create" << collName << "capped" << true << "size" << cappedSize
+ << WriteConcernOptions::kWriteConcernField
+ << ShardingCatalogClient::kMajorityWriteConcern.toBSON());
auto result = Grid::get(txn)->shardRegistry()->getConfigShard()->runCommand(
txn,
diff --git a/src/mongo/s/catalog/replset/sharding_catalog_test.cpp b/src/mongo/s/catalog/replset/sharding_catalog_test.cpp
index 5ecf1899c60..e4d06494d1b 100644
--- a/src/mongo/s/catalog/replset/sharding_catalog_test.cpp
+++ b/src/mongo/s/catalog/replset/sharding_catalog_test.cpp
@@ -679,27 +679,9 @@ TEST_F(ShardingCatalogClientTest, RunUserManagementWriteCommandSuccess) {
future.timed_get(kFutureTimeout);
}
-TEST_F(ShardingCatalogClientTest, RunUserManagementWriteCommandWithInvalidWriteConcernSingleNode) {
- // Tests that if you send a non-majority write concern it will not be accepted
- BSONObjBuilder responseBuilder;
- bool ok =
- catalogClient()->runUserManagementWriteCommand(operationContext(),
- "dropUser",
- "test",
- BSON("dropUser"
- << "test"
- << "writeConcern"
- << BSON("w" << 1 << "wtimeout" << 30)),
- &responseBuilder);
- ASSERT_FALSE(ok);
-
- Status commandStatus = getStatusFromCommandResult(responseBuilder.obj());
- ASSERT_EQUALS(ErrorCodes::InvalidOptions, commandStatus);
- ASSERT_STRING_CONTAINS(commandStatus.reason(), "Invalid replication write concern");
-}
+TEST_F(ShardingCatalogClientTest, RunUserManagementWriteCommandInvalidWriteConcern) {
+ configTargeter()->setFindHostReturnValue(HostAndPort("TestHost1"));
-TEST_F(ShardingCatalogClientTest, RunUserManagementWriteCommandInvalidWriteConcernTwoNodes) {
- // Tests that if you send a non-majority write concern it will not be accepted
BSONObjBuilder responseBuilder;
bool ok = catalogClient()->runUserManagementWriteCommand(operationContext(),
"dropUser",
@@ -716,6 +698,62 @@ TEST_F(ShardingCatalogClientTest, RunUserManagementWriteCommandInvalidWriteConce
ASSERT_STRING_CONTAINS(commandStatus.reason(), "Invalid replication write concern");
}
+TEST_F(ShardingCatalogClientTest, RunUserManagementWriteCommandRewriteWriteConcern) {
+ // Tests that if you send a w:1 write concern it gets replaced with w:majority
+ configTargeter()->setFindHostReturnValue(HostAndPort("TestHost1"));
+
+ distLock()->expectLock(
+ [](StringData name,
+ StringData whyMessage,
+ Milliseconds waitFor,
+ Milliseconds lockTryInterval) {
+ ASSERT_EQUALS("authorizationData", name);
+ ASSERT_EQUALS("dropUser", whyMessage);
+ },
+ Status::OK());
+
+ auto future = launchAsync([this] {
+ BSONObjBuilder responseBuilder;
+ bool ok = catalogClient()->runUserManagementWriteCommand(operationContext(),
+ "dropUser",
+ "test",
+ BSON("dropUser"
+ << "test"
+ << "writeConcern"
+ << BSON("w" << 1 << "wtimeout"
+ << 30)),
+ &responseBuilder);
+ ASSERT_FALSE(ok);
+
+ Status commandStatus = getStatusFromCommandResult(responseBuilder.obj());
+ ASSERT_EQUALS(ErrorCodes::UserNotFound, commandStatus);
+ });
+
+ onCommand([](const RemoteCommandRequest& request) {
+ ASSERT_EQUALS("test", request.dbname);
+ ASSERT_EQUALS(BSON("dropUser"
+ << "test"
+ << "writeConcern"
+ << BSON("w"
+ << "majority"
+ << "wtimeout"
+ << 30)
+ << "maxTimeMS"
+ << 30000),
+ request.cmdObj);
+
+ ASSERT_EQUALS(BSON(rpc::kReplSetMetadataFieldName << 1), request.metadata);
+
+ BSONObjBuilder responseBuilder;
+ Command::appendCommandStatus(responseBuilder,
+ Status(ErrorCodes::UserNotFound, "User test@test not found"));
+ return responseBuilder.obj();
+ });
+
+ // Now wait for the runUserManagementWriteCommand call to return
+ future.timed_get(kFutureTimeout);
+}
+
TEST_F(ShardingCatalogClientTest, RunUserManagementWriteCommandNotMaster) {
configTargeter()->setFindHostReturnValue(HostAndPort("TestHost1"));