summaryrefslogtreecommitdiff
path: root/src/mongo/db/commands.cpp
diff options
context:
space:
mode:
authorRandolph Tan <randolph@10gen.com>2018-09-25 16:52:27 -0400
committerRandolph Tan <randolph@10gen.com>2018-09-27 10:31:35 -0400
commit5674fa1f3087f65ea326b33f5b81647d4dcfb8d6 (patch)
treebe74b03f086a8a338c5354eaf9b2e5f2d86d8996 /src/mongo/db/commands.cpp
parentf58a039003b982d40de3ce1be56563270f6b78de (diff)
downloadmongo-5674fa1f3087f65ea326b33f5b81647d4dcfb8d6.tar.gz
SERVER-37239 Router should validate if commands are allowed to run within transactions
Diffstat (limited to 'src/mongo/db/commands.cpp')
-rw-r--r--src/mongo/db/commands.cpp59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp
index 921b9d7a397..82cca3d77e9 100644
--- a/src/mongo/db/commands.cpp
+++ b/src/mongo/db/commands.cpp
@@ -104,6 +104,40 @@ bool checkAuthorizationImplPreParse(OperationContext* opCtx,
return false;
}
+// The command names that are allowed in a multi-document transaction.
+const StringMap<int> txnCmdWhitelist = {{"abortTransaction", 1},
+ {"aggregate", 1},
+ {"commitTransaction", 1},
+ {"coordinateCommitTransaction", 1},
+ {"delete", 1},
+ {"distinct", 1},
+ {"doTxn", 1},
+ {"find", 1},
+ {"findandmodify", 1},
+ {"findAndModify", 1},
+ {"geoSearch", 1},
+ {"getMore", 1},
+ {"insert", 1},
+ {"killCursors", 1},
+ {"prepareTransaction", 1},
+ {"update", 1},
+ {"voteAbortTransaction", 1},
+ {"voteCommitTransaction", 1}};
+
+// The command names that are allowed in a multi-document transaction only when test commands are
+// enabled.
+const StringMap<int> txnCmdForTestingWhitelist = {{"dbHash", 1}};
+
+
+// The commands that can be run on the 'admin' database in multi-document transactions.
+const StringMap<int> txnAdminCommands = {{"abortTransaction", 1},
+ {"commitTransaction", 1},
+ {"coordinateCommitTransaction", 1},
+ {"doTxn", 1},
+ {"prepareTransaction", 1},
+ {"voteAbortTransaction", 1},
+ {"voteCommitTransaction", 1}};
+
} // namespace
@@ -398,6 +432,31 @@ bool CommandHelpers::uassertShouldAttemptParse(OperationContext* opCtx,
}
}
+
+Status CommandHelpers::canUseTransactions(StringData dbName, StringData cmdName) {
+ if (cmdName == "count"_sd) {
+ return {ErrorCodes::OperationNotSupportedInTransaction,
+ "Cannot run 'count' in a multi-document transaction. Please see "
+ "http://dochub.mongodb.org/core/transaction-count for a recommended alternative."};
+ }
+
+ if (txnCmdWhitelist.find(cmdName) == txnCmdWhitelist.cend() &&
+ !(getTestCommandsEnabled() &&
+ txnCmdForTestingWhitelist.find(cmdName) != txnCmdForTestingWhitelist.cend())) {
+ return {ErrorCodes::OperationNotSupportedInTransaction,
+ str::stream() << "Cannot run '" << cmdName << "' in a multi-document transaction."};
+ }
+
+ if (dbName == "config"_sd || dbName == "local"_sd ||
+ (dbName == "admin"_sd && txnAdminCommands.find(cmdName) == txnAdminCommands.cend())) {
+ return {ErrorCodes::OperationNotSupportedInTransaction,
+ str::stream() << "Cannot run command against the '" << dbName
+ << "' database in a transaction"};
+ }
+
+ return Status::OK();
+}
+
constexpr StringData CommandHelpers::kHelpFieldName;
//////////////////////////////////////////////////////////////