Status bsonExtractStringField(const BSONObj& object, StringData fieldName, std::string* out) { BSONElement element; Status status = bsonExtractTypedField(object, fieldName, String, &element); if (!status.isOK()) return status; *out = element.str(); return Status::OK(); }
Status bsonExtractBooleanField(const BSONObj& object, StringData fieldName, bool* out) { BSONElement element; Status status = bsonExtractTypedField(object, fieldName, Bool, &element); if (!status.isOK()) return status; *out = element.boolean(); return Status::OK(); }
Status bsonExtractOIDField(const BSONObj& object, StringData fieldName, OID* out) { BSONElement element; Status status = bsonExtractTypedField(object, fieldName, jstOID, &element); if (!status.isOK()) return status; *out = element.OID(); return Status::OK(); }
Status bsonExtractTimestampField(const BSONObj& object, StringData fieldName, Timestamp* out) { BSONElement element; Status status = bsonExtractTypedField(object, fieldName, bsonTimestamp, &element); if (!status.isOK()) return status; *out = element.timestamp(); return Status::OK(); }
StatusWith<ShardingMetadata> ShardingMetadata::readFromMetadata(const BSONObj& metadataObj) { BSONElement smElem; auto smExtractStatus = bsonExtractTypedField(metadataObj, kGLEStatsFieldName, mongol::Object, &smElem); if (!smExtractStatus.isOK()) { return smExtractStatus; } if (smElem.embeddedObject().nFields() != 2) { return Status(ErrorCodes::InvalidOptions, str::stream() << "The $gleStats object can only have 2 fields, but got " << smElem.embeddedObject().toString()); } repl::OpTime opTime; const BSONElement opTimeElement = smElem.embeddedObject()[kGLEStatsLastOpTimeFieldName]; if (opTimeElement.eoo()) { return Status(ErrorCodes::NoSuchKey, "lastOpTime field missing"); } else if (opTimeElement.type() == bsonTimestamp) { opTime = repl::OpTime(opTimeElement.timestamp(), repl::OpTime::kUninitializedTerm); } else if (opTimeElement.type() == Date) { opTime = repl::OpTime(Timestamp(opTimeElement.date()), repl::OpTime::kUninitializedTerm); } else if (opTimeElement.type() == Object) { Status status = bsonExtractOpTimeField(smElem.embeddedObject(), kGLEStatsLastOpTimeFieldName, &opTime); if (!status.isOK()) { return status; } } else { return Status(ErrorCodes::TypeMismatch, str::stream() << "Expected \"" << kGLEStatsLastOpTimeFieldName << "\" field in response to replSetHeartbeat " "command to have type Date or Timestamp, but found type " << typeName(opTimeElement.type())); } BSONElement lastElectionIdElem; auto lastElectionIdExtractStatus = bsonExtractTypedField( smElem.embeddedObject(), kGLEStatsElectionIdFieldName, mongol::jstOID, &lastElectionIdElem); if (!lastElectionIdExtractStatus.isOK()) { return lastElectionIdExtractStatus; } return ShardingMetadata(opTime, lastElectionIdElem.OID()); }
Status bsonExtractOpTimeField(const BSONObj& object, const StringData& fieldName, OpTime* out) { BSONElement element; Status status = bsonExtractTypedField(object, fieldName, Timestamp, &element); if (!status.isOK()) return status; *out = element._opTime(); return Status::OK(); }
StatusWith<Date_t> getBSONDocumentId(const BSONObj& obj) { BSONElement element; Status status = bsonExtractTypedField(obj, kFTDCIdField, BSONType::Date, &element); if (!status.isOK()) { return {status}; } return {element.Date()}; }
BSONObj Cloner::getIdIndexSpec(const std::list<BSONObj>& indexSpecs) { for (auto&& indexSpec : indexSpecs) { BSONElement indexName; uassertStatusOK(bsonExtractTypedField( indexSpec, IndexDescriptor::kIndexNameFieldName, String, &indexName)); if (indexName.valueStringData() == "_id_"_sd) { return indexSpec; } } return BSONObj(); }
StatusWith<ChunkRange> ChunkRange::fromBSON(const BSONObj& obj) { BSONElement minKey; { Status minKeyStatus = bsonExtractTypedField(obj, kMinKey, Object, &minKey); if (!minKeyStatus.isOK()) { return {minKeyStatus.code(), str::stream() << "Invalid min key due to " << minKeyStatus.reason()}; } } BSONElement maxKey; { Status maxKeyStatus = bsonExtractTypedField(obj, kMaxKey, Object, &maxKey); if (!maxKeyStatus.isOK()) { return {maxKeyStatus.code(), str::stream() << "Invalid max key due to " << maxKeyStatus.reason()}; } } return ChunkRange(minKey.Obj().getOwned(), maxKey.Obj().getOwned()); }
StatusWith<LocksType> LocksType::fromBSON(const BSONObj& source) { LocksType lock; { std::string lockName; Status status = bsonExtractStringField(source, name.name(), &lockName); if (!status.isOK()) return status; lock._name = lockName; } { long long lockStateInt; Status status = bsonExtractIntegerField(source, state.name(), &lockStateInt); if (!status.isOK()) return status; lock._state = static_cast<State>(lockStateInt); } if (source.hasField(process.name())) { std::string lockProcess; Status status = bsonExtractStringField(source, process.name(), &lockProcess); if (!status.isOK()) return status; lock._process = lockProcess; } if (source.hasField(lockID.name())) { BSONElement lockIDElem; Status status = bsonExtractTypedField(source, lockID.name(), BSONType::jstOID, &lockIDElem); if (!status.isOK()) return status; lock._lockID = lockIDElem.OID(); } if (source.hasField(who.name())) { std::string lockWho; Status status = bsonExtractStringField(source, who.name(), &lockWho); if (!status.isOK()) return status; lock._who = lockWho; } if (source.hasField(why.name())) { std::string lockWhy; Status status = bsonExtractStringField(source, why.name(), &lockWhy); if (!status.isOK()) return status; lock._why = lockWhy; } return lock; }
StatusWith<MongosType> MongosType::fromBSON(const BSONObj& source) { MongosType mt; { std::string mtName; Status status = bsonExtractStringField(source, name.name(), &mtName); if (!status.isOK()) return status; mt._name = mtName; } { BSONElement mtPingElem; Status status = bsonExtractTypedField(source, ping.name(), BSONType::Date, &mtPingElem); if (!status.isOK()) return status; mt._ping = mtPingElem.date(); } { long long mtUptime; Status status = bsonExtractIntegerField(source, uptime.name(), &mtUptime); if (!status.isOK()) return status; mt._uptime = mtUptime; } { bool mtWaiting; Status status = bsonExtractBooleanField(source, waiting.name(), &mtWaiting); if (!status.isOK()) return status; mt._waiting = mtWaiting; } if (source.hasField(mongoVersion.name())) { std::string mtMongoVersion; Status status = bsonExtractStringField(source, mongoVersion.name(), &mtMongoVersion); if (!status.isOK()) return status; mt._mongoVersion = mtMongoVersion; } if (source.hasField(configVersion.name())) { long long mtConfigVersion; Status status = bsonExtractIntegerField(source, configVersion.name(), &mtConfigVersion); if (!status.isOK()) return status; mt._configVersion = mtConfigVersion; } return mt; }
StatusWith<ParsedDistinct> ParsedDistinct::parse(OperationContext* txn, const NamespaceString& nss, const BSONObj& cmdObj, const ExtensionsCallback& extensionsCallback, bool isExplain) { // Extract the key field. BSONElement keyElt; auto statusKey = bsonExtractTypedField(cmdObj, kKeyField, BSONType::String, &keyElt); if (!statusKey.isOK()) { return {statusKey}; } auto key = keyElt.valuestrsafe(); auto qr = stdx::make_unique<QueryRequest>(nss); // Extract the query field. If the query field is nonexistent, an empty query is used. if (BSONElement queryElt = cmdObj[kQueryField]) { if (queryElt.type() == BSONType::Object) { qr->setFilter(queryElt.embeddedObject()); } else if (queryElt.type() != BSONType::jstNULL) { return Status(ErrorCodes::TypeMismatch, str::stream() << "\"" << kQueryField << "\" had the wrong type. Expected " << typeName(BSONType::Object) << " or " << typeName(BSONType::jstNULL) << ", found " << typeName(queryElt.type())); } } // Extract the collation field, if it exists. if (BSONElement collationElt = cmdObj[kCollationField]) { if (collationElt.type() != BSONType::Object) { return Status(ErrorCodes::TypeMismatch, str::stream() << "\"" << kCollationField << "\" had the wrong type. Expected " << typeName(BSONType::Object) << ", found " << typeName(collationElt.type())); } qr->setCollation(collationElt.embeddedObject()); } qr->setExplain(isExplain); auto cq = CanonicalQuery::canonicalize(txn, std::move(qr), extensionsCallback); if (!cq.isOK()) { return cq.getStatus(); } return ParsedDistinct(std::move(cq.getValue()), std::move(key)); }
/** * Writes into *writeConcern a BSONObj describing the parameters to getLastError to use for * the write confirmation. */ Status _extractWriteConcern(const BSONObj& cmdObj, BSONObj* writeConcern) { BSONElement writeConcernElement; Status status = bsonExtractTypedField(cmdObj, "writeConcern", Object, &writeConcernElement); if (!status.isOK()) { if (status.code() == ErrorCodes::NoSuchKey) { *writeConcern = BSONObj(); return Status::OK(); } return status; } *writeConcern = writeConcernElement.Obj().getOwned();; return Status::OK(); }
Status UpdatePositionArgs::initialize(const BSONObj& argsObj) { Status status = bsonCheckOnlyHasFields("UpdatePositionArgs", argsObj, kLegalUpdatePositionFieldNames); if (!status.isOK()) return status; // grab the array of changes BSONElement updateArray; status = bsonExtractTypedField(argsObj, kUpdateArrayFieldName, Array, &updateArray); if (!status.isOK()) return status; // now parse each array entry into an update BSONObjIterator i(updateArray.Obj()); while(i.more()) { BSONObj entry = i.next().Obj(); status = bsonCheckOnlyHasFields("UpdateInfoArgs", entry, kLegalUpdateInfoFieldNames); if (!status.isOK()) return status; OpTime ts; status = bsonExtractOpTimeField(entry, kOpTimeFieldName, &ts); if (!status.isOK()) return status; // TODO(spencer): The following three fields are optional in 2.8, but should be made // required or ignored in 3.0 long long cfgver; status = bsonExtractIntegerFieldWithDefault(entry, kConfigVersionFieldName, -1, &cfgver); if (!status.isOK()) return status; OID rid; status = bsonExtractOIDFieldWithDefault(entry, kMemberRIDFieldName, OID(), &rid); if (!status.isOK()) return status; long long memberID; status = bsonExtractIntegerFieldWithDefault(entry, kMemberIdFieldName, -1, &memberID); if (!status.isOK()) return status; _updates.push_back(UpdateInfo(rid, ts, cfgver, memberID)); } return Status::OK(); }
Status parseAndValidateRolePrivilegeManipulationCommands(const BSONObj& cmdObj, const StringData& cmdName, const std::string& dbname, RoleName* parsedRoleName, PrivilegeVector* parsedPrivileges, BSONObj* parsedWriteConcern) { unordered_set<std::string> validFieldNames; validFieldNames.insert(cmdName.toString()); validFieldNames.insert("privileges"); validFieldNames.insert("writeConcern"); Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames); if (!status.isOK()) { return status; } status = _extractWriteConcern(cmdObj, parsedWriteConcern); if (!status.isOK()) { return status; } BSONObjBuilder roleObjBuilder; // Parse role name std::string roleName; status = bsonExtractStringField(cmdObj, cmdName, &roleName); if (!status.isOK()) { return status; } *parsedRoleName = RoleName(roleName, dbname); // Parse privileges BSONElement privilegesElement; status = bsonExtractTypedField(cmdObj, "privileges", Array, &privilegesElement); if (!status.isOK()) { return status; } status = parseAndValidatePrivilegeArray(BSONArray(privilegesElement.Obj()), parsedPrivileges); if (!status.isOK()) { return status; } if (!parsedPrivileges->size()) { return Status(ErrorCodes::BadValue, mongoutils::str::stream() << cmdName << " command requires a non-empty " "\"privileges\" array"); } return Status::OK(); }
Status parseUserRoleManipulationCommand(const BSONObj& cmdObj, const StringData& cmdName, const std::string& dbname, AuthorizationManager* authzManager, UserName* parsedUserName, vector<RoleName>* parsedRoleNames, BSONObj* parsedWriteConcern) { unordered_set<std::string> validFieldNames; validFieldNames.insert(cmdName.toString()); validFieldNames.insert("roles"); validFieldNames.insert("writeConcern"); Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames); if (!status.isOK()) { return status; } status = _extractWriteConcern(cmdObj, parsedWriteConcern); if (!status.isOK()) { return status; } std::string userNameStr; status = bsonExtractStringField(cmdObj, cmdName, &userNameStr); if (!status.isOK()) { return status; } *parsedUserName = UserName(userNameStr, dbname); BSONElement rolesElement; status = bsonExtractTypedField(cmdObj, "roles", Array, &rolesElement); if (!status.isOK()) { return status; } status = _extractRoleNamesFromBSONArray(BSONArray(rolesElement.Obj()), dbname, authzManager, parsedRoleNames); if (!status.isOK()) { return status; } if (!parsedRoleNames->size()) { return Status(ErrorCodes::BadValue, mongoutils::str::stream() << cmdName << " command requires a non-empty" << " roles array"); } return Status::OK(); }
StatusWith<BSONObj> getBSONDocumentFromMetadataDoc(const BSONObj& obj) { if (kDebugBuild) { auto swType = getBSONDocumentType(obj); dassert(swType.isOK() && swType.getValue() == FTDCType::kMetadata); } BSONElement element; Status status = bsonExtractTypedField(obj, kFTDCDocField, BSONType::Object, &element); if (!status.isOK()) { return {status}; } return {element.Obj()}; }
Status parseRolePossessionManipulationCommands(const BSONObj& cmdObj, const StringData& cmdName, const StringData& rolesFieldName, const std::string& dbname, std::string* parsedName, vector<RoleName>* parsedRoleNames, BSONObj* parsedWriteConcern) { unordered_set<std::string> validFieldNames; validFieldNames.insert(cmdName.toString()); validFieldNames.insert(rolesFieldName.toString()); validFieldNames.insert("writeConcern"); Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames); if (!status.isOK()) { return status; } status = _extractWriteConcern(cmdObj, parsedWriteConcern); if (!status.isOK()) { return status; } status = bsonExtractStringField(cmdObj, cmdName, parsedName); if (!status.isOK()) { return status; } BSONElement rolesElement; status = bsonExtractTypedField(cmdObj, rolesFieldName, Array, &rolesElement); if (!status.isOK()) { return status; } status = parseRoleNamesFromBSONArray(BSONArray(rolesElement.Obj()), dbname, rolesFieldName, parsedRoleNames); if (!status.isOK()) { return status; } if (!parsedRoleNames->size()) { return Status(ErrorCodes::BadValue, mongoutils::str::stream() << cmdName << " command requires a non-empty \"" << rolesFieldName << "\" array"); } return Status::OK(); }
Status _parseAndValidateInput(BSONObj cmdObj, UpdateUserArgs* parsedArgs) const { unordered_set<std::string> validFieldNames; validFieldNames.insert("updateUser"); validFieldNames.insert("user"); validFieldNames.insert("pwd"); validFieldNames.insert("extraData"); // Iterate through all fields in command object and make sure there are no // unexpected ones. for (BSONObjIterator iter(cmdObj); iter.more(); iter.next()) { StringData fieldName = (*iter).fieldNameStringData(); if (!validFieldNames.count(fieldName.toString())) { return Status(ErrorCodes::BadValue, mongoutils::str::stream() << "\"" << fieldName << "\" is not " "a valid argument to updateUser"); } } Status status = bsonExtractStringField(cmdObj, "user", &parsedArgs->userName); if (!status.isOK()) { return status; } if (cmdObj.hasField("pwd")) { parsedArgs->hasPassword = true; status = bsonExtractStringField(cmdObj, "pwd", &parsedArgs->clearTextPassword); if (!status.isOK()) { return status; } } if (cmdObj.hasField("extraData")) { parsedArgs->hasExtraData = true; BSONElement element; status = bsonExtractTypedField(cmdObj, "extraData", Object, &element); if (!status.isOK()) { return status; } parsedArgs->extraData = element.Obj(); } if (!parsedArgs->hasPassword && !parsedArgs->hasExtraData) { return Status(ErrorCodes::BadValue, "Must specify at least one of 'pwd' and 'extraData'"); } return Status::OK(); }
StatusWith<ReadPreferenceSetting> ReadPreferenceSetting::fromBSON(const BSONObj& readPrefObj) { std::string modeStr; auto modeExtractStatus = bsonExtractStringField(readPrefObj, kModeFieldName, &modeStr); if (!modeExtractStatus.isOK()) { return modeExtractStatus; } ReadPreference mode; auto swReadPrefMode = parseReadPreferenceMode(modeStr); if (!swReadPrefMode.isOK()) { return swReadPrefMode.getStatus(); } mode = std::move(swReadPrefMode.getValue()); TagSet tags; BSONElement tagsElem; auto tagExtractStatus = bsonExtractTypedField(readPrefObj, kTagsFieldName, mongo::Array, &tagsElem); if (tagExtractStatus.isOK()) { tags = TagSet{BSONArray(tagsElem.Obj().getOwned())}; // In accordance with the read preference spec, passing the default wildcard tagset // '[{}]' is the same as not passing a TagSet at all. Furthermore, passing an empty // TagSet with a non-primary ReadPreference is equivalent to passing the wildcard // ReadPreference. if (tags == TagSet() || tags == TagSet::primaryOnly()) { tags = defaultTagSetForMode(mode); } // If we are using a user supplied TagSet, check that it is compatible with // the readPreference mode. else if (ReadPreference::PrimaryOnly == mode && (tags != TagSet::primaryOnly())) { return Status(ErrorCodes::BadValue, "Only empty tags are allowed with primary read preference"); } } else if (ErrorCodes::NoSuchKey == tagExtractStatus) { tags = defaultTagSetForMode(mode); } else { return tagExtractStatus; } return ReadPreferenceSetting(mode, tags); }
Status bsonExtractOpTimeField(const BSONObj& object, StringData fieldName, repl::OpTime* out) { BSONElement element; Status status = bsonExtractTypedField(object, fieldName, Object, &element); if (!status.isOK()) return status; BSONObj opTimeObj = element.Obj(); Timestamp ts; status = bsonExtractTimestampField(opTimeObj, kTimestampFieldName, &ts); if (!status.isOK()) return status; long long term; status = bsonExtractIntegerField(opTimeObj, kTermFieldName, &term); if (!status.isOK()) return status; *out = repl::OpTime(ts, term); return Status::OK(); }
Status ReadAfterOpTimeArgs::initialize(const BSONObj& cmdObj) { auto afterElem = cmdObj[ReadAfterOpTimeArgs::kRootFieldName]; if (afterElem.eoo()) { return Status::OK(); } if (!afterElem.isABSONObj()) { return Status(ErrorCodes::FailedToParse, "'after' field should be an object"); } BSONObj readAfterObj = afterElem.Obj(); BSONElement opTimeElem; auto opTimeStatus = bsonExtractTypedField( readAfterObj, ReadAfterOpTimeArgs::kOpTimeFieldName, Object, &opTimeElem); if (!opTimeStatus.isOK()) { return opTimeStatus; } BSONObj opTimeObj = opTimeElem.Obj(); BSONElement timestampElem; Timestamp timestamp; auto timestampStatus = bsonExtractTimestampField( opTimeObj, ReadAfterOpTimeArgs::kOpTimestampFieldName, ×tamp); if (!timestampStatus.isOK()) { return timestampStatus; } long long termNumber; auto termStatus = bsonExtractIntegerField(opTimeObj, ReadAfterOpTimeArgs::kOpTermFieldName, &termNumber); if (!termStatus.isOK()) { return termStatus; } _opTime = OpTime(timestamp, termNumber); return Status::OK(); }
virtual bool run(OperationContext* txn, const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { if (!replset::replSettings.master) { return appendCommandStatus(result, Status( ErrorCodes::NoReplicationEnabled, "Must have replication set up to run \"appendOplogNote\"")); } BSONElement dataElement; Status status = bsonExtractTypedField(cmdObj, "data", Object, &dataElement); if (!status.isOK()) { return appendCommandStatus(result, status); } replset::logOpComment(dataElement.Obj()); return true; }
void OperationShardVersion::initializeFromCommand(NamespaceString ns, const BSONObj& cmdObj) { if (ns.isSystemDotIndexes()) { setShardVersion(std::move(ns), ChunkVersion::IGNORED()); return; } BSONElement versionElt; Status status = bsonExtractTypedField(cmdObj, kShardVersionField, BSONType::Array, &versionElt); if (!status.isOK()) { return; } const BSONArray versionArr(versionElt.Obj()); bool hasVersion = false; ChunkVersion newVersion = ChunkVersion::fromBSON(versionArr, &hasVersion); if (!hasVersion) { return; } setShardVersion(std::move(ns), std::move(newVersion)); }
void OperationShardVersion::initializeFromCommand(NamespaceString ns, const BSONObj& cmdObj) { BSONElement versionElt; Status status = bsonExtractTypedField(cmdObj, kShardVersionField, BSONType::Array, &versionElt); if (!status.isOK()) { return; } const BSONArray versionArr(versionElt.Obj()); bool hasVersion = false; ChunkVersion newVersion = ChunkVersion::fromBSON(versionArr, &hasVersion); if (!hasVersion) { return; } // This currently supports only setting the shard version for one namespace. invariant(!_hasVersion || _ns == ns); _hasVersion = true; _ns = std::move(ns); _shardVersion = std::move(newVersion); }
StatusWith<std::vector<BSONObj>> getMetricsFromMetricDoc(const BSONObj& obj, FTDCDecompressor* decompressor) { if (kDebugBuild) { auto swType = getBSONDocumentType(obj); dassert(swType.isOK() && swType.getValue() == FTDCType::kMetricChunk); } BSONElement element; Status status = bsonExtractTypedField(obj, kFTDCDataField, BSONType::BinData, &element); if (!status.isOK()) { return {status}; } int length; const char* buffer = element.binData(length); if (length < 0) { return {ErrorCodes::BadValue, str::stream() << "Field " << std::string(kFTDCTypeField) << " is not a BinData."}; } return decompressor->uncompress({buffer, static_cast<std::size_t>(length)}); }
StatusWith<ShardType> ShardType::fromBSON(const BSONObj& source) { ShardType shard; { std::string shardName; Status status = bsonExtractStringField(source, name.name(), &shardName); if (!status.isOK()) return status; shard._name = shardName; } { std::string shardHost; Status status = bsonExtractStringField(source, host.name(), &shardHost); if (!status.isOK()) return status; shard._host = shardHost; } { bool isShardDraining; Status status = bsonExtractBooleanField(source, draining.name(), &isShardDraining); if (status.isOK()) { shard._draining = isShardDraining; } else if (status == ErrorCodes::NoSuchKey) { // draining field can be mssing in which case it is presumed false } else { return status; } } { long long shardMaxSizeMB; // maxSizeMB == 0 means there's no limitation to space usage. Status status = bsonExtractIntegerField(source, maxSizeMB.name(), &shardMaxSizeMB); if (status.isOK()) { shard._maxSizeMB = shardMaxSizeMB; } else if (status == ErrorCodes::NoSuchKey) { // maxSizeMB field can be missing in which case it is presumed false } else { return status; } } if (source.hasField(tags.name())) { shard._tags = std::vector<std::string>(); BSONElement tagsElement; Status status = bsonExtractTypedField(source, tags.name(), Array, &tagsElement); if (!status.isOK()) return status; BSONObjIterator it(tagsElement.Obj()); while (it.more()) { BSONElement tagElement = it.next(); if (tagElement.type() != String) { return Status(ErrorCodes::TypeMismatch, str::stream() << "Elements in \"" << tags.name() << "\" array must be strings but found " << typeName(tagElement.type())); } shard._tags->push_back(tagElement.String()); } } return shard; }
Status parseAndValidateCreateRoleCommand(const BSONObj& cmdObj, const std::string& dbname, AuthorizationManager* authzManager, BSONObj* parsedRoleObj, BSONObj* parsedWriteConcern) { unordered_set<std::string> validFieldNames; validFieldNames.insert("createRole"); validFieldNames.insert("privileges"); validFieldNames.insert("roles"); validFieldNames.insert("writeConcern"); Status status = _checkNoExtraFields(cmdObj, "createRole", validFieldNames); if (!status.isOK()) { return status; } status = _extractWriteConcern(cmdObj, parsedWriteConcern); if (!status.isOK()) { return status; } BSONObjBuilder roleObjBuilder; // Parse role name std::string roleName; status = bsonExtractStringField(cmdObj, "createRole", &roleName); if (!status.isOK()) { return status; } // Prevent creating roles in the local database if (dbname == "local") { return Status(ErrorCodes::BadValue, "Cannot create roles in the local database"); } roleObjBuilder.append("_id", dbname + "." + roleName); roleObjBuilder.append(AuthorizationManager::ROLE_NAME_FIELD_NAME, roleName); roleObjBuilder.append(AuthorizationManager::ROLE_SOURCE_FIELD_NAME, dbname); // Parse privileges BSONElement privilegesElement; status = bsonExtractTypedField(cmdObj, "privileges", Array, &privilegesElement); if (!status.isOK()) { return status; } status = _parseAndValidatePrivilegeArray(BSONArray(privilegesElement.Obj()), NULL); if (!status.isOK()) { return status; } roleObjBuilder.append(privilegesElement); // Parse roles BSONElement rolesElement; status = bsonExtractTypedField(cmdObj, "roles", Array, &rolesElement); if (!status.isOK()) { return status; } BSONArray modifiedRolesArray; status = _validateAndModifyRolesArray(rolesElement, dbname, authzManager, false, &modifiedRolesArray); if (!status.isOK()) { return status; } roleObjBuilder.append("roles", modifiedRolesArray); *parsedRoleObj = roleObjBuilder.obj(); return Status::OK(); }
Status parseAndValidateUpdateUserCommand(const BSONObj& cmdObj, const std::string& dbname, AuthorizationManager* authzManager, BSONObj* parsedUpdateObj, UserName* parsedUserName, BSONObj* parsedWriteConcern) { unordered_set<std::string> validFieldNames; validFieldNames.insert("updateUser"); validFieldNames.insert("customData"); validFieldNames.insert("pwd"); validFieldNames.insert("roles"); validFieldNames.insert("writeConcern"); Status status = _checkNoExtraFields(cmdObj, "updateUser", validFieldNames); if (!status.isOK()) { return status; } status = _extractWriteConcern(cmdObj, parsedWriteConcern); if (!status.isOK()) { return status; } BSONObjBuilder updateSetBuilder; // Parse user name std::string userName; status = bsonExtractStringField(cmdObj, "updateUser", &userName); if (!status.isOK()) { return status; } *parsedUserName = UserName(userName, dbname); // Parse password if (cmdObj.hasField("pwd")) { std::string clearTextPassword; status = bsonExtractStringField(cmdObj, "pwd", &clearTextPassword); if (!status.isOK()) { return status; } std::string password = auth::createPasswordDigest(userName, clearTextPassword); updateSetBuilder.append("credentials.MONGODB-CR", password); } // Parse custom data if (cmdObj.hasField("customData")) { BSONElement element; status = bsonExtractTypedField(cmdObj, "customData", Object, &element); if (!status.isOK()) { return status; } updateSetBuilder.append("customData", element.Obj()); } // Parse roles if (cmdObj.hasField("roles")) { BSONElement rolesElement; Status status = bsonExtractTypedField(cmdObj, "roles", Array, &rolesElement); if (!status.isOK()) { return status; } BSONArray modifiedRolesObj; status = _validateAndModifyRolesArray(rolesElement, dbname, authzManager, true, &modifiedRolesObj); if (!status.isOK()) { return status; } updateSetBuilder.append("roles", modifiedRolesObj); } BSONObj updateSet = updateSetBuilder.obj(); if (updateSet.isEmpty()) { return Status(ErrorCodes::UserModificationFailed, "Must specify at least one field to update in updateUser"); } *parsedUpdateObj = BSON("$set" << updateSet); return Status::OK(); }
Status parseAndValidateCreateUserCommand(const BSONObj& cmdObj, const std::string& dbname, AuthorizationManager* authzManager, BSONObj* parsedUserObj, BSONObj* parsedWriteConcern) { unordered_set<std::string> validFieldNames; validFieldNames.insert("createUser"); validFieldNames.insert("customData"); validFieldNames.insert("pwd"); validFieldNames.insert("roles"); validFieldNames.insert("writeConcern"); Status status = _checkNoExtraFields(cmdObj, "createUser", validFieldNames); if (!status.isOK()) { return status; } status = _extractWriteConcern(cmdObj, parsedWriteConcern); if (!status.isOK()) { return status; } BSONObjBuilder userObjBuilder; // Parse user name std::string userName; status = bsonExtractStringField(cmdObj, "createUser", &userName); if (!status.isOK()) { return status; } // Prevent creating users in the local database if (dbname == "local") { return Status(ErrorCodes::BadValue, "Cannot create users in the local database"); } userObjBuilder.append("_id", dbname + "." + userName); userObjBuilder.append(AuthorizationManager::USER_NAME_FIELD_NAME, userName); userObjBuilder.append(AuthorizationManager::USER_SOURCE_FIELD_NAME, dbname); // Parse password if (cmdObj.hasField("pwd")) { std::string clearTextPassword; status = bsonExtractStringField(cmdObj, "pwd", &clearTextPassword); if (!status.isOK()) { return status; } std::string password = auth::createPasswordDigest(userName, clearTextPassword); userObjBuilder.append("credentials", BSON("MONGODB-CR" << password)); } else { if (dbname != "$external") { return Status(ErrorCodes::BadValue, "Must provide a 'pwd' field for all user documents, except those" " with '$external' as the user's source"); } } // Parse custom data if (cmdObj.hasField("customData")) { BSONElement element; status = bsonExtractTypedField(cmdObj, "customData", Object, &element); if (!status.isOK()) { return status; } userObjBuilder.append("customData", element.Obj()); } // Parse roles if (cmdObj.hasField("roles")) { BSONElement rolesElement; status = bsonExtractTypedField(cmdObj, "roles", Array, &rolesElement); if (!status.isOK()) { return status; } BSONArray modifiedRolesArray; status = _validateAndModifyRolesArray(rolesElement, dbname, authzManager, true, &modifiedRolesArray); if (!status.isOK()) { return status; } userObjBuilder.append("roles", modifiedRolesArray); } *parsedUserObj = userObjBuilder.obj(); // Make sure document to insert is valid V2UserDocumentParser parser; status = parser.checkValidUserDocument(*parsedUserObj); if (!status.isOK()) { return status; } return Status::OK(); }