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());
}
Exemple #6
0
 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();
 }
Exemple #7
0
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()};
}
Exemple #8
0
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();
}
Exemple #9
0
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());
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}
Exemple #12
0
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();
 }
Exemple #14
0
    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();
    }
Exemple #17
0
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();
        }
Exemple #20
0
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, &timestamp);

    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();
}
Exemple #23
0
        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);
}
Exemple #26
0
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)});
}
Exemple #27
0
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();
    }