diff options
author | Randolph Tan <randolph@10gen.com> | 2018-09-25 16:52:27 -0400 |
---|---|---|
committer | Randolph Tan <randolph@10gen.com> | 2018-09-27 10:31:35 -0400 |
commit | 5674fa1f3087f65ea326b33f5b81647d4dcfb8d6 (patch) | |
tree | be74b03f086a8a338c5354eaf9b2e5f2d86d8996 /src/mongo/db/commands.cpp | |
parent | f58a039003b982d40de3ce1be56563270f6b78de (diff) | |
download | mongo-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.cpp | 59 |
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; ////////////////////////////////////////////////////////////// |