summaryrefslogtreecommitdiff
path: root/jstests
diff options
context:
space:
mode:
authorSpencer Jackson <spencer.jackson@mongodb.com>2016-09-26 12:54:12 -0400
committerSpencer Jackson <spencer.jackson@mongodb.com>2016-09-30 13:43:42 -0400
commit1ac511f1673d9663454651c2763aec32387c077f (patch)
treed8b367422ab62a89f928e585b8c4ba4ba9e906a1 /jstests
parent67c441cf094920674fc76668d5b0d225503a9c8a (diff)
downloadmongo-1ac511f1673d9663454651c2763aec32387c077f.tar.gz
SERVER-25994: Make applyOps work without universal privileges
Diffstat (limited to 'jstests')
-rw-r--r--jstests/auth/lib/commands_lib.js239
-rw-r--r--jstests/core/apply_ops1.js145
2 files changed, 374 insertions, 10 deletions
diff --git a/jstests/auth/lib/commands_lib.js b/jstests/auth/lib/commands_lib.js
index ae08ff755cc..daea8325abb 100644
--- a/jstests/auth/lib/commands_lib.js
+++ b/jstests/auth/lib/commands_lib.js
@@ -198,25 +198,250 @@ var authCommandsLib = {
roles: Object.extend({readWriteAnyDatabase: 1}, roles_clusterManager)
}]
},
+
{
- testname: "applyOps",
- command: {applyOps: "x"},
+ testname: "applyOps_empty",
+ command: {applyOps: []},
+ skipSharded: true,
testcases: [
{
+ roles: {__system: 1},
runOnDb: adminDbName,
+ },
+ {
roles: {__system: 1},
- privileges: [{resource: {anyResource: true}, actions: ["anyAction"]}],
- expectFail: true
+ runOnDb: firstDbName,
+ }
+ ]
+ },
+ {
+ testname: "applyOps_precondition",
+ command: {
+ applyOps: [{
+ "ts": Timestamp(1473353037, 1),
+ "h": NumberLong(0),
+ "v": 2,
+ "op": "n",
+ "ns": "",
+ "o": {}
+ }],
+ preCondition: [{ns: firstDbName + ".x", q: {x: 5}, res: []}]
+ },
+ skipSharded: true,
+ setup: function(db) {
+ db.getSisterDB(firstDbName).x.save({});
+ },
+ teardown: function(db) {
+ db.getSisterDB(firstDbName).x.drop();
+ },
+ testcases: [
+ {
+ runOnDb: adminDbName,
+ privileges: [
+ {resource: {db: firstDbName, collection: "x"}, actions: ["find"]},
+ {
+ resource: {cluster: true},
+ actions: ["appendOplogNote"],
+ removeWhenTestingAuthzFailure: false
+ },
+ ],
+ },
+ ]
+ },
+ {
+ testname: "applyOps_noop",
+ command: {
+ applyOps: [{
+ "ts": Timestamp(1473353037, 1),
+ "h": NumberLong(0),
+ "v": 2,
+ "op": "n",
+ "ns": "",
+ "o": {}
+ }]
+ },
+ skipSharded: true,
+ testcases: [
+ {
+ runOnDb: adminDbName,
+ privileges: [
+ {resource: {cluster: true}, actions: ["appendOplogNote"]},
+ ],
},
{
runOnDb: firstDbName,
- roles: {__system: 1},
- privileges: [{resource: {anyResource: true}, actions: ["anyAction"]}],
- expectFail: true
+ privileges: [
+ {resource: {cluster: true}, actions: ["appendOplogNote"]},
+ ],
+ expectFailure: true
}
]
},
{
+ testname: "applyOps_c_renameCollection_twoDbs",
+ command: {
+ applyOps: [{
+ "ts": Timestamp(1474051004, 1),
+ "h": NumberLong(0),
+ "v": 2,
+ "op": "c",
+ "ns": "test.$cmd",
+ "o": {
+ "renameCollection": firstDbName + ".x",
+ "to": secondDbName + ".y",
+ "stayTemp": false,
+ "dropTarget": false
+ }
+ }]
+ },
+ skipSharded: true,
+ setup: function(db) {
+ db.getSisterDB(firstDbName).x.save({});
+ db.getSisterDB(adminDbName).runCommand({movePrimary: firstDbName, to: shard0name});
+ db.getSisterDB(adminDbName).runCommand({movePrimary: secondDbName, to: shard0name});
+ },
+ teardown: function(db) {
+ db.getSisterDB(firstDbName).x.drop();
+ db.getSisterDB(secondDbName).y.drop();
+ },
+ testcases: [
+ {
+ runOnDb: adminDbName,
+ roles: {readWriteAnyDatabase: 1, root: 1, __system: 1},
+ privileges: [
+ {
+ resource: {db: firstDbName, collection: "x"},
+ actions: ["find", "dropCollection"]
+ },
+ {
+ resource: {db: secondDbName, collection: "y"},
+ actions: ["insert", "createIndex"]
+ }
+ ]
+ },
+ ]
+ },
+ {
+ testname: "applyOps_insert",
+ command: {
+ applyOps: [{
+ "ts": Timestamp(1474051453, 1),
+ "h": NumberLong(0),
+ "v": 2,
+ "op": "i",
+ "ns": firstDbName + ".x",
+ "o": {"_id": ObjectId("57dc3d7da4fce4358afa85b8"), "data": 5}
+ }]
+ },
+ skipSharded: true,
+ setup: function(db) {
+ db.getSisterDB(firstDbName).x.save({});
+ },
+ teardown: function(db) {
+ db.getSisterDB(firstDbName).x.drop();
+ },
+ testcases: [
+ {
+ runOnDb: adminDbName,
+ roles: roles_write,
+ privileges: [
+ {resource: {db: firstDbName, collection: "x"}, actions: ["insert"]},
+ ],
+ },
+ ]
+ },
+ {
+ testname: "applyOps_upsert",
+ command: {
+ applyOps: [{
+ "ts": Timestamp(1474053682, 1),
+ "h": NumberLong(0),
+ "v": 2,
+ "op": "u",
+ "ns": firstDbName + ".x",
+ "o2": {"_id": 1},
+ "o": {"_id": 1, "data": 8}
+ }]
+ },
+ skipSharded: true,
+ setup: function(db) {
+ db.getSisterDB(firstDbName).x.save({_id: 1, data: 1});
+ },
+ teardown: function(db) {
+ db.getSisterDB(firstDbName).x.drop();
+ },
+ testcases: [
+ {
+ runOnDb: adminDbName,
+ roles: Object.merge(roles_write, {restore: 0}, true),
+ privileges: [
+ {resource: {db: firstDbName, collection: "x"}, actions: ["update", "insert"]},
+ ],
+ },
+ ]
+ },
+ {
+ testname: "applyOps_update",
+ command: {
+ applyOps: [{
+ "ts": Timestamp(1474053682, 1),
+ "h": NumberLong(0),
+ "v": 2,
+ "op": "u",
+ "ns": firstDbName + ".x",
+ "o2": {"_id": 1},
+ "o": {"_id": 1, "data": 8}
+ }],
+ alwaysUpsert: false
+ },
+ skipSharded: true,
+ setup: function(db) {
+ db.getSisterDB(firstDbName).x.save({_id: 1, data: 1});
+ },
+ teardown: function(db) {
+ db.getSisterDB(firstDbName).x.drop();
+ },
+ testcases: [
+ {
+ runOnDb: adminDbName,
+ roles: Object.merge(roles_write, {restore: 0}, true),
+ privileges: [
+ {resource: {db: firstDbName, collection: "x"}, actions: ["update"]},
+ ],
+ },
+ ]
+ },
+ {
+ testname: "applyOps_delete",
+ command: {
+ applyOps: [{
+ "ts": Timestamp(1474056194, 1),
+ "h": NumberLong(0),
+ "v": 2,
+ "op": "d",
+ "ns": firstDbName + ".x",
+ "o": {"_id": 1}
+ }]
+ },
+ skipSharded: true,
+ setup: function(db) {
+ db.getSisterDB(firstDbName).x.save({_id: 1, data: 1});
+ },
+ teardown: function(db) {
+ db.getSisterDB(firstDbName).x.drop();
+ },
+ testcases: [
+ {
+ runOnDb: adminDbName,
+ roles: Object.merge(roles_write, {restore: 0}, true),
+ privileges: [
+ {resource: {db: firstDbName, collection: "x"}, actions: ["remove"]},
+ ],
+ },
+ ]
+ },
+
+ {
testname: "aggregate_readonly",
command: {aggregate: "foo", pipeline: []},
testcases: [
diff --git a/jstests/core/apply_ops1.js b/jstests/core/apply_ops1.js
index 1e6b545a210..8ce15b1df22 100644
--- a/jstests/core/apply_ops1.js
+++ b/jstests/core/apply_ops1.js
@@ -66,6 +66,144 @@
db.adminCommand({applyOps: [{op: 'c', ns: ''}]}),
'applyOps should fail on non-"n" operation type with empty "ns" field value');
+ // Excessively nested applyOps commands gracefully fail.
+ assert.commandFailed(db.adminCommand({
+ "applyOps": [{
+ "ts": {"$timestamp": {"t": 1, "i": 100}},
+ "h": 0,
+ "v": 2,
+ "op": "c",
+ "ns": "test.$cmd",
+ "o": {
+ "applyOps": [{
+ "ts": {"$timestamp": {"t": 1, "i": 100}},
+ "h": 0,
+ "v": 2,
+ "op": "c",
+ "ns": "test.$cmd",
+ "o": {
+ "applyOps": [{
+ "ts": {"$timestamp": {"t": 1, "i": 100}},
+ "h": 0,
+ "v": 2,
+ "op": "c",
+ "ns": "test.$cmd",
+ "o": {
+ "applyOps": [{
+ "ts": {"$timestamp": {"t": 1, "i": 100}},
+ "h": 0,
+ "v": 2,
+ "op": "c",
+ "ns": "test.$cmd",
+ "o": {
+ "applyOps": [{
+ "ts": {"$timestamp": {"t": 1, "i": 100}},
+ "h": 0,
+ "v": 2,
+ "op": "c",
+ "ns": "test.$cmd",
+ "o": {
+ "applyOps": [{
+ "ts": {"$timestamp": {"t": 1, "i": 100}},
+ "h": 0,
+ "v": 2,
+ "op": "c",
+ "ns": "test.$cmd",
+ "o": {
+ "applyOps": [{
+ "ts":
+ {"$timestamp": {"t": 1, "i": 100}},
+ "h": 0,
+ "v": 2,
+ "op": "c",
+ "ns": "test.$cmd",
+ "o": {
+ "applyOps": [{
+ "ts": {
+ "$timestamp":
+ {"t": 1, "i": 100}
+ },
+ "h": 0,
+ "v": 2,
+ "op": "c",
+ "ns": "test.$cmd",
+ "o": {
+ "applyOps": [{
+ "ts": {
+ "$timestamp": {
+ "t": 1,
+ "i": 100
+ }
+ },
+ "h": 0,
+ "v": 2,
+ "op": "c",
+ "ns": "test.$cmd",
+ "o": {
+ "applyOps": [{
+ "ts": {
+ "$timestamp":
+ {
+ "t":
+ 1,
+ "i":
+ 100
+ }
+ },
+ "h": 0,
+ "v": 2,
+ "op": "c",
+ "ns":
+ "test.$cmd",
+ "o": {
+ "applyOps": [
+ {
+ "ts": {
+ "$timestamp": {
+ "t":
+ 1,
+ "i":
+ 100
+ }
+ },
+ "h":
+ 0,
+ "v":
+ 2,
+ "op":
+ "c",
+ "ns":
+ "test.$cmd",
+ "o": {
+ "applyOps":
+ [
+ ]
+ }
+ }
+ ]
+ }
+ }]
+ }
+ }]
+ }
+ }]
+ }
+ }]
+ }
+ }]
+ }
+ }]
+ }
+ }]
+ }
+ }]
+ }
+ }]
+ }
+ }]
+ }),
+ "Excessively nested applyOps should be rejected");
+
// Missing 'o' field value in an operation of type 'i' on 'system.indexes' collection.
assert.commandFailedWithCode(
db.adminCommand({applyOps: [{op: 'i', ns: db.getName() + '.system.indexes'}]}),
@@ -153,7 +291,8 @@
"Applying an insert operation on a non-existent collection should fail");
assert.commandWorked(db.createCollection(t.getName()));
- var a = db.adminCommand({applyOps: [{"op": "i", "ns": t.getFullName(), "o": {_id: 5, x: 17}}]});
+ var a = assert.commandWorked(
+ db.adminCommand({applyOps: [{"op": "i", "ns": t.getFullName(), "o": {_id: 5, x: 17}}]}));
assert.eq(1, t.find().count(), "Valid insert failed");
assert.eq(true, a.results[0], "Bad result value for valid insert");
@@ -169,12 +308,12 @@
assert.commandFailed(db.adminCommand({applyOps: [{op: 'i', ns: t.getFullName(), o: []}]}),
'applyOps should fail on insert of object with empty array element');
- var res = db.runCommand({
+ var res = assert.commandWorked(db.runCommand({
applyOps: [
{op: "u", ns: t.getFullName(), o2: {_id: 5}, o: {$inc: {x: 1}}},
{op: "u", ns: t.getFullName(), o2: {_id: 5}, o: {$inc: {x: 1}}}
]
- });
+ }));
o.x++;
o.x++;