/** * Updates roleGraph for a delete-type oplog operation on admin.system.roles. */ Status handleOplogDelete(RoleGraph* roleGraph, const BSONObj& deletePattern) { RoleName roleToDelete; Status status = getRoleNameFromIdField(deletePattern["_id"], &roleToDelete); if (!status.isOK()) return status; status = roleGraph->deleteRole(roleToDelete); if (ErrorCodes::RoleNotFound == status) { // Double-delete can happen in oplog application. status = Status::OK(); } return status; }
/** * Updates roleGraph for an update-type oplog operation on admin.system.roles. * * Treats all updates as upserts. */ Status handleOplogUpdate(OperationContext* opCtx, RoleGraph* roleGraph, const BSONObj& updatePattern, const BSONObj& queryPattern) { RoleName roleToUpdate; Status status = getRoleNameFromIdField(queryPattern["_id"], &roleToUpdate); if (!status.isOK()) return status; boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContext(opCtx, nullptr)); UpdateDriver driver(std::move(expCtx)); driver.setFromOplogApplication(true); // Oplog updates do not have array filters. std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; driver.parse(updatePattern, arrayFilters); mutablebson::Document roleDocument; status = RoleGraph::getBSONForRole(roleGraph, roleToUpdate, roleDocument.root()); if (status == ErrorCodes::RoleNotFound) { // The query pattern will only contain _id, no other immutable fields are present const FieldRef idFieldRef("_id"); FieldRefSet immutablePaths; invariant(immutablePaths.insert(&idFieldRef)); status = driver.populateDocumentWithQueryFields( opCtx, queryPattern, immutablePaths, roleDocument); } if (!status.isOK()) return status; const bool validateForStorage = false; const FieldRefSet emptyImmutablePaths; status = driver.update(StringData(), &roleDocument, validateForStorage, emptyImmutablePaths); if (!status.isOK()) return status; // Now use the updated document to totally replace the role in the graph! RoleInfo role; status = parseRoleFromDocument(roleDocument.getObject(), &role); if (!status.isOK()) return status; status = roleGraph->replaceRole(role.name, role.roles, role.privileges, role.restrictions); return status; }
/** * Updates roleGraph for an update-type oplog operation on admin.system.roles. * * Treats all updates as upserts. */ Status handleOplogUpdate(RoleGraph* roleGraph, const BSONObj& updatePattern, const BSONObj& queryPattern) { RoleName roleToUpdate; Status status = getRoleNameFromIdField(queryPattern["_id"], &roleToUpdate); if (!status.isOK()) return status; UpdateDriver::Options updateOptions; updateOptions.upsert = true; UpdateDriver driver(updateOptions); status = driver.parse(updatePattern); if (!status.isOK()) return status; mutablebson::Document roleDocument; status = AuthorizationManager::getBSONForRole( roleGraph, roleToUpdate, roleDocument.root()); if (status == ErrorCodes::RoleNotFound) { status = driver.populateDocumentWithQueryFields(queryPattern, roleDocument); } if (!status.isOK()) return status; status = driver.update(StringData(), &roleDocument); if (!status.isOK()) return status; // Now use the updated document to totally replace the role in the graph! RoleInfo role; status = parseRoleFromDocument(roleDocument.getObject(), &role); if (!status.isOK()) return status; status = roleGraph->replaceRole(role.name, role.roles, role.privileges); return status; }