mirror of https://github.com/mongodb/mongo
SERVER-102870: Make $mergeCursors internal (#34112)
GitOrigin-RevId: ee527360b84c6798535ee0895de3c7186b3522f9
This commit is contained in:
parent
f4184f18fe
commit
fc15786481
|
|
@ -32,7 +32,7 @@ const testInternalClient = (function createInternalClient() {
|
|||
|
||||
const curDB = testInternalClient.getDB(dbName);
|
||||
|
||||
// Tests that the internal stage '$mergeCursors' does not throw 'ApiStrictError' with an internal
|
||||
// Tests that the internal stage '$mergeCursors' is allowed in requests with an internal
|
||||
// client and 'apiStrict' set to true.
|
||||
let result = curDB.runCommand({
|
||||
aggregate: collName,
|
||||
|
|
@ -52,8 +52,8 @@ let result = curDB.runCommand({
|
|||
});
|
||||
assert.commandWorked(result);
|
||||
|
||||
// Tests that the internal stage '$mergeCursors' throws 'ApiStrictError' with default external
|
||||
// client when 'apiStrict' is set to true.
|
||||
// Tests that the internal stage '$mergeCursors' is not allowed in user requests with default
|
||||
// external client when 'apiStrict' is set to true.
|
||||
result = testDB.runCommand({
|
||||
aggregate: collName,
|
||||
pipeline: [{
|
||||
|
|
@ -70,9 +70,9 @@ result = testDB.runCommand({
|
|||
apiVersion: "1",
|
||||
apiStrict: true
|
||||
});
|
||||
assert.commandFailedWithCode(result, ErrorCodes.APIStrictError);
|
||||
assert.commandFailedWithCode(result, 5491300);
|
||||
|
||||
// Tests that the internal stage '$mergeCursors' should not fail with 'ApiStrictError' with default
|
||||
// Tests that the internal stage '$mergeCursors' is not allowed with default
|
||||
// external client without specifying 'apiStrict' flag.
|
||||
result = testDB.runCommand({
|
||||
aggregate: collName,
|
||||
|
|
@ -89,7 +89,7 @@ result = testDB.runCommand({
|
|||
writeConcern: {w: "majority"},
|
||||
apiVersion: "1"
|
||||
});
|
||||
assert.commandWorked(result);
|
||||
assert.commandFailedWithCode(result, 5491300);
|
||||
|
||||
// Tests that the 'exchange' option cannot be specified by external client with 'apiStrict' set to
|
||||
// true.
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
/**
|
||||
* SERVER-95350: Fix jstests/aggregation/api_version_stage_allowance_checks.js.
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
load("jstests/libs/collection_drop_recreate.js"); // For assertDropAndRecreateCollection.
|
||||
|
||||
const collName = 'test';
|
||||
assertDropAndRecreateCollection(db, collName);
|
||||
|
||||
let docs = [];
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
docs.push({x: i, y: i, z: i});
|
||||
}
|
||||
db[collName].insertMany(docs);
|
||||
|
||||
assert.commandWorked(db.runCommand({
|
||||
explain: {
|
||||
aggregate: collName,
|
||||
pipeline: [{
|
||||
$mergeCursors: {
|
||||
sort: {y: 1, z: 1},
|
||||
compareWholeSortKey: false,
|
||||
remotes: [],
|
||||
nss: "test.mergeCursors",
|
||||
allowPartialResults: false,
|
||||
}
|
||||
}],
|
||||
cursor: {},
|
||||
readConcern: {},
|
||||
},
|
||||
}));
|
||||
})();
|
||||
|
|
@ -6637,6 +6637,42 @@ var authCommandsLib = {
|
|||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
testname: "aggregate_$mergeCursors",
|
||||
command: {
|
||||
aggregate: "foo",
|
||||
pipeline: [{
|
||||
$mergeCursors: {
|
||||
sort: {y: 1, z: 1},
|
||||
compareWholeSortKey: false,
|
||||
remotes: [],
|
||||
nss: "test.mergeCursors",
|
||||
allowPartialResults: false,
|
||||
}
|
||||
}],
|
||||
cursor: {},
|
||||
},
|
||||
testcases: [
|
||||
{
|
||||
runOnDb: firstDbName,
|
||||
roles: {__system: 1},
|
||||
// $mergeCursors requires __system role OR a user with internal and find action types as privileges.
|
||||
expectFail: true,
|
||||
privileges: [
|
||||
{resource: {cluster: true}, actions: ["internal"]},
|
||||
{resource: {db: firstDbName, collection: "foo"}, actions: ["find"]},
|
||||
],
|
||||
},
|
||||
{
|
||||
runOnDb: firstDbName,
|
||||
// Find action type as a privilege alone is not sufficient for $mergeCursors.
|
||||
expectAuthzFailure: true,
|
||||
privileges: [
|
||||
{resource: {db: firstDbName, collection: "foo"}, actions: ["find"]},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
testname: "validate_db_metadata_command_specific_db",
|
||||
command: {
|
||||
|
|
|
|||
|
|
@ -295,6 +295,32 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class LiteParsedDocumentSourceInternal final : public LiteParsedDocumentSource {
|
||||
public:
|
||||
/**
|
||||
* Creates the default LiteParsedDocumentSource for internal document sources. This requires
|
||||
* the privilege on 'internal' action. This should still be used with caution. Make sure your
|
||||
* stage doesn't need to communicate any special behavior before registering a DocumentSource
|
||||
* using this parser.
|
||||
*/
|
||||
static std::unique_ptr<LiteParsedDocumentSourceInternal> parse(const NamespaceString& nss,
|
||||
const BSONElement& spec) {
|
||||
return std::make_unique<LiteParsedDocumentSourceInternal>(spec.fieldName());
|
||||
}
|
||||
|
||||
LiteParsedDocumentSourceInternal(std::string parseTimeName)
|
||||
: LiteParsedDocumentSource(std::move(parseTimeName)) {}
|
||||
|
||||
stdx::unordered_set<NamespaceString> getInvolvedNamespaces() const final {
|
||||
return stdx::unordered_set<NamespaceString>();
|
||||
}
|
||||
|
||||
PrivilegeVector requiredPrivileges(bool isMongos, bool bypassDocumentValidation) const final {
|
||||
return {Privilege(ResourcePattern::forClusterResource(), ActionSet{ActionType::internal})};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper class for DocumentSources which reference a foreign collection.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -38,10 +38,10 @@
|
|||
|
||||
namespace mongo {
|
||||
|
||||
REGISTER_DOCUMENT_SOURCE(mergeCursors,
|
||||
LiteParsedDocumentSourceDefault::parse,
|
||||
REGISTER_INTERNAL_DOCUMENT_SOURCE(mergeCursors,
|
||||
LiteParsedDocumentSourceInternal::parse,
|
||||
DocumentSourceMergeCursors::createFromBson,
|
||||
AllowedWithApiStrict::kInternal);
|
||||
true);
|
||||
|
||||
constexpr StringData DocumentSourceMergeCursors::kStageName;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue