Status AuthzManagerExternalStateMock::remove( OperationContext* txn, const NamespaceString& collectionName, const BSONObj& query, const BSONObj&, int* numRemoved) { int n = 0; BSONObjCollection::iterator iter; while (_findOneIter(collectionName, query, &iter).isOK()) { BSONObj idQuery = (*iter)["_id"].wrap(); _documents[collectionName].erase(iter); ++n; if (_authzManager) { _authzManager->logOp( txn, "d", collectionName.ns().c_str(), idQuery, NULL); } } *numRemoved = n; return Status::OK(); }
Status AuthzManagerExternalStateMock::updateOne(OperationContext* opCtx, const NamespaceString& collectionName, const BSONObj& query, const BSONObj& updatePattern, bool upsert, const BSONObj& writeConcern) { namespace mmb = mutablebson; const CollatorInterface* collator = nullptr; boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContext(opCtx, collator)); UpdateDriver driver(std::move(expCtx)); std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; driver.parse(updatePattern, arrayFilters); BSONObjCollection::iterator iter; Status status = _findOneIter(opCtx, collectionName, query, &iter); mmb::Document document; if (status.isOK()) { document.reset(*iter, mmb::Document::kInPlaceDisabled); const bool validateForStorage = false; const FieldRefSet emptyImmutablePaths; const bool isInsert = false; BSONObj logObj; status = driver.update( StringData(), &document, validateForStorage, emptyImmutablePaths, isInsert, &logObj); if (!status.isOK()) return status; BSONObj newObj = document.getObject().copy(); *iter = newObj; BSONObj idQuery = newObj["_id"_sd].Obj(); if (_authzManager) { _authzManager->logOp(opCtx, "u", collectionName, logObj, &idQuery); } return Status::OK(); } else if (status == ErrorCodes::NoMatchingDocument && upsert) { if (query.hasField("_id")) { document.root().appendElement(query["_id"]).transitional_ignore(); } const FieldRef idFieldRef("_id"); FieldRefSet immutablePaths; invariant(immutablePaths.insert(&idFieldRef)); status = driver.populateDocumentWithQueryFields(opCtx, query, immutablePaths, document); if (!status.isOK()) { return status; } const bool validateForStorage = false; const FieldRefSet emptyImmutablePaths; const bool isInsert = false; status = driver.update( StringData(), &document, validateForStorage, emptyImmutablePaths, isInsert); if (!status.isOK()) { return status; } return insert(opCtx, collectionName, document.getObject(), writeConcern); } else { return status; } }
Status AuthzManagerExternalStateMock::updateOne( OperationContext* txn, const NamespaceString& collectionName, const BSONObj& query, const BSONObj& updatePattern, bool upsert, const BSONObj& writeConcern) { namespace mmb = mutablebson; UpdateDriver::Options updateOptions; UpdateDriver driver(updateOptions); Status status = driver.parse(updatePattern); if (!status.isOK()) return status; BSONObjCollection::iterator iter; status = _findOneIter(collectionName, query, &iter); mmb::Document document; if (status.isOK()) { document.reset(*iter, mmb::Document::kInPlaceDisabled); BSONObj logObj; status = driver.update(StringData(), &document, &logObj); if (!status.isOK()) return status; BSONObj newObj = document.getObject().copy(); *iter = newObj; BSONObj idQuery = driver.makeOplogEntryQuery(newObj, false); if (_authzManager) { _authzManager->logOp( txn, "u", collectionName.ns().c_str(), logObj, &idQuery); } return Status::OK(); } else if (status == ErrorCodes::NoMatchingDocument && upsert) { if (query.hasField("_id")) { document.root().appendElement(query["_id"]); } status = driver.populateDocumentWithQueryFields(query, NULL, document); if (!status.isOK()) { return status; } status = driver.update(StringData(), &document); if (!status.isOK()) { return status; } return insert(txn, collectionName, document.getObject(), writeConcern); } else { return status; } }
Status AuthzManagerExternalStateMock::findOne(OperationContext* opCtx, const NamespaceString& collectionName, const BSONObj& query, BSONObj* result) { BSONObjCollection::iterator iter; Status status = _findOneIter(collectionName, query, &iter); if (!status.isOK()) return status; *result = iter->copy(); return Status::OK(); }
Status AuthzManagerExternalStateMock::remove( const NamespaceString& collectionName, const BSONObj& query, const BSONObj&, int* numRemoved) { int n = 0; BSONObjCollection::iterator iter; while (_findOneIter(collectionName, query, &iter).isOK()) { _documents[collectionName].erase(iter); ++n; } *numRemoved = n; return Status::OK(); }
Status AuthzManagerExternalStateMock::updateOne( const NamespaceString& collectionName, const BSONObj& query, const BSONObj& updatePattern, bool upsert, const BSONObj& writeConcern) { namespace mmb = mutablebson; UpdateDriver::Options updateOptions; updateOptions.upsert = upsert; UpdateDriver driver(updateOptions); Status status = driver.parse(updatePattern); if (!status.isOK()) return status; BSONObjCollection::iterator iter; status = _findOneIter(collectionName, query, &iter); mmb::Document document; if (status.isOK()) { document.reset(*iter, mmb::Document::kInPlaceDisabled); status = driver.update(StringData(), &document, NULL); if (!status.isOK()) return status; *iter = document.getObject().copy(); return Status::OK(); } else if (status == ErrorCodes::NoMatchingDocument && upsert) { if (query.hasField("_id")) { document.root().appendElement(query["_id"]); } status = driver.createFromQuery(query, document); if (!status.isOK()) { return status; } status = driver.update(StringData(), &document, NULL); if (!status.isOK()) { return status; } return insert(collectionName, document.getObject(), writeConcern); } else { return status; } }
Status AuthzManagerExternalStateMock::updateOne(OperationContext* opCtx, const NamespaceString& collectionName, const BSONObj& query, const BSONObj& updatePattern, bool upsert, const BSONObj& writeConcern) { namespace mmb = mutablebson; UpdateDriver::Options updateOptions; UpdateDriver driver(updateOptions); std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; Status status = driver.parse(updatePattern, arrayFilters); if (!status.isOK()) return status; BSONObjCollection::iterator iter; status = _findOneIter(collectionName, query, &iter); mmb::Document document; if (status.isOK()) { document.reset(*iter, mmb::Document::kInPlaceDisabled); const BSONObj emptyOriginal; const bool validateForStorage = false; const FieldRefSet emptyImmutablePaths; BSONObj logObj; status = driver.update(StringData(), emptyOriginal, &document, validateForStorage, emptyImmutablePaths, &logObj); if (!status.isOK()) return status; BSONObj newObj = document.getObject().copy(); *iter = newObj; BSONObj idQuery = driver.makeOplogEntryQuery(newObj, false); if (_authzManager) { _authzManager->logOp(opCtx, "u", collectionName, logObj, &idQuery); } return Status::OK(); } else if (status == ErrorCodes::NoMatchingDocument && upsert) { if (query.hasField("_id")) { document.root().appendElement(query["_id"]).transitional_ignore(); } const FieldRef idFieldRef("_id"); FieldRefSet immutablePaths; invariant(immutablePaths.insert(&idFieldRef)); status = driver.populateDocumentWithQueryFields(opCtx, query, immutablePaths, document); if (!status.isOK()) { return status; } // The original document can be empty because it is only needed for validation of immutable // paths. const BSONObj emptyOriginal; const bool validateForStorage = false; const FieldRefSet emptyImmutablePaths; status = driver.update( StringData(), emptyOriginal, &document, validateForStorage, emptyImmutablePaths); if (!status.isOK()) { return status; } return insert(opCtx, collectionName, document.getObject(), writeConcern); } else { return status; } }