Status parseCreateOrUpdateRoleCommands(const BSONObj& cmdObj,
                                           const StringData& cmdName,
                                           const std::string& dbname,
                                           CreateOrUpdateRoleArgs* parsedArgs) {
        unordered_set<std::string> validFieldNames;
        validFieldNames.insert(cmdName.toString());
        validFieldNames.insert("privileges");
        validFieldNames.insert("roles");
        validFieldNames.insert("writeConcern");

        Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames);
        if (!status.isOK()) {
            return status;
        }

        status = _extractWriteConcern(cmdObj, &parsedArgs->writeConcern);
        if (!status.isOK()) {
            return status;
        }

        std::string roleName;
        status = bsonExtractStringField(cmdObj, "createRole", &roleName);
        if (!status.isOK()) {
            return status;
        }
        parsedArgs->roleName = RoleName(roleName, dbname);

        // Parse privileges
        if (cmdObj.hasField("privileges")) {
            BSONElement privilegesElement;
            status = bsonExtractTypedField(cmdObj, "privileges", Array, &privilegesElement);
            if (!status.isOK()) {
                return status;
            }
            status = parseAndValidatePrivilegeArray(BSONArray(privilegesElement.Obj()),
                                                    &parsedArgs->privileges);
            if (!status.isOK()) {
                return status;
            }
            parsedArgs->hasPrivileges = true;
        }

        // Parse roles
        if (cmdObj.hasField("roles")) {
            BSONElement rolesElement;
            status = bsonExtractTypedField(cmdObj, "roles", Array, &rolesElement);
            if (!status.isOK()) {
                return status;
            }
            status = parseRoleNamesFromBSONArray(BSONArray(rolesElement.Obj()),
                                                 dbname,
                                                 "roles",
                                                 &parsedArgs->roles);
            if (!status.isOK()) {
                return status;
            }
            parsedArgs->hasRoles = true;
        }
        return Status::OK();
    }
Example #2
0
    TEST( Shard, EqualityRs ) {
        Shard a("foo", "bar/a,b", 0, false, BSONArray());
        Shard b("foo", "bar/a,b", 0, false, BSONArray());
        ASSERT_EQUALS( a, b );

        b = Shard("foo", "bar/b,a", 0, false, BSONArray());
        ASSERT_EQUALS( a, b );
    }
TEST_F(DocumentSourceFacetTest, ShouldRejectEmptyPipelines) {
    auto ctx = getExpCtx();
    auto spec = BSON("$facet" << BSON("a" << BSONArray()));
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);

    spec = BSON("$facet" << BSON("a" << BSON_ARRAY(BSON("$skip" << 4)) << "b" << BSONArray()));
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);
}
Status V2UserDocumentParser::initializeAuthenticationRestrictionsFromUserDocument(
    const BSONObj& privDoc, User* user) const {
    RestrictionDocuments::sequence_type restrictionVector;

    // Restrictions on the user
    const auto authenticationRestrictions = privDoc[AUTHENTICATION_RESTRICTIONS_FIELD_NAME];
    if (!authenticationRestrictions.eoo()) {
        if (authenticationRestrictions.type() != Array) {
            return Status(ErrorCodes::UnsupportedFormat,
                          "'authenticationRestrictions' field must be an array");
        }

        auto restrictions =
            parseAuthenticationRestriction(BSONArray(authenticationRestrictions.Obj()));
        if (!restrictions.isOK()) {
            return restrictions.getStatus();
        }

        restrictionVector.push_back(restrictions.getValue());
    }

    // Restrictions from roles
    const auto inherited = privDoc[INHERITED_AUTHENTICATION_RESTRICTIONS_FIELD_NAME];
    if (!inherited.eoo()) {
        if (inherited.type() != Array) {
            return Status(ErrorCodes::UnsupportedFormat,
                          "'inheritedAuthenticationRestrictions' field must be an array");
        }

        for (const auto& roleRestriction : BSONArray(inherited.Obj())) {
            if (roleRestriction.type() != Array) {
                return Status(ErrorCodes::UnsupportedFormat,
                              "'inheritedAuthenticationRestrictions' sub-fields must be arrays");
            }

            auto roleRestrictionDoc =
                parseAuthenticationRestriction(BSONArray(roleRestriction.Obj()));
            if (!roleRestrictionDoc.isOK()) {
                return roleRestrictionDoc.getStatus();
            }

            restrictionVector.push_back(roleRestrictionDoc.getValue());
        }
    }

    if (user) {
        user->setRestrictions(RestrictionDocuments(restrictionVector));
    }

    return Status::OK();
}
Example #5
0
mongo::BSONArray MockRemoteDBServer::query(MockRemoteDBServer::InstanceID id,
                                           const string& ns,
                                           mongo::Query query,
                                           int nToReturn,
                                           int nToSkip,
                                           const BSONObj* fieldsToReturn,
                                           int queryOptions,
                                           int batchSize) {
    checkIfUp(id);

    if (_delayMilliSec > 0) {
        mongo::sleepmillis(_delayMilliSec);
    }

    checkIfUp(id);

    scoped_spinlock sLock(_lock);
    _queryCount++;

    const vector<BSONObj>& coll = _dataMgr[ns];
    BSONArrayBuilder result;
    for (vector<BSONObj>::const_iterator iter = coll.begin(); iter != coll.end(); ++iter) {
        result.append(iter->copy());
    }

    return BSONArray(result.obj());
}
Example #6
0
    Value DocumentSourceGeoNear::serialize(bool explain) const {
        MutableDocument result;

        if (coordsIsArray) {
            result.setField("near", Value(BSONArray(coords)));
        }
        else {
            result.setField("near", Value(coords));
        }

        // not in buildGeoNearCmd
        result.setField("distanceField", Value(distanceField->getPath(false)));

        result.setField("limit", Value(limit));

        if (maxDistance > 0)
            result.setField("maxDistance", Value(maxDistance));

        result.setField("query", Value(query));
        result.setField("spherical", Value(spherical));
        result.setField("distanceMultiplier", Value(distanceMultiplier));

        if (includeLocs)
            result.setField("includeLocs", Value(includeLocs->getPath(false)));

        result.setField("uniqueDocs", Value(uniqueDocs));

        return Value(DOC(getSourceName() << result.freeze()));
    }
    Status parseRolesInfoCommand(const BSONObj& cmdObj,
                                 const StringData& dbname,
                                 std::vector<RoleName>* parsedRoleNames) {
        unordered_set<std::string> validFieldNames;
        validFieldNames.insert("rolesInfo");

        Status status = _checkNoExtraFields(cmdObj, "rolesInfo", validFieldNames);
        if (!status.isOK()) {
            return status;
        }

        if (cmdObj["rolesInfo"].type() == Array) {
            status = parseRoleNamesFromBSONArray(BSONArray(cmdObj["rolesInfo"].Obj()),
                                                 dbname,
                                                 parsedRoleNames);
            if (!status.isOK()) {
                return status;
            }
        } else {
            RoleName name;
            status = _parseNameFromBSONElement(cmdObj["rolesInfo"],
                                               dbname,
                                               AuthorizationManager::ROLE_NAME_FIELD_NAME,
                                               AuthorizationManager::ROLE_SOURCE_FIELD_NAME,
                                               &name);
            if (!status.isOK()) {
                return status;
            }
            parsedRoleNames->push_back(name);
        }

        return Status::OK();
    }
Example #8
0
        virtual bool run(OperationContext* txn, const string& , BSONObj& cmdObj, int, string& errmsg,
                         BSONObjBuilder& result, bool fromRepl) {
            if (!check(errmsg, result))
                return false;

            if (cmdObj.hasField("handshake")) {
                // we have received a handshake, not an update message
                // handshakes are done here to ensure the receiving end supports the update command

                return appendCommandStatus(
                        result,
                        getGlobalReplicationCoordinator()->processReplSetUpdatePositionHandshake(
                                cmdObj["handshake"].embeddedObject(),
                                &result));
            }

            uassert(16888, "optimes field should be an array with an object for each secondary",
                    cmdObj["optimes"].type() == Array);

            return appendCommandStatus(
                    result,
                    getGlobalReplicationCoordinator()->processReplSetUpdatePosition(
                            BSONArray(cmdObj["optimes"].Obj()),
                            &result));
        }
Example #9
0
StatusWith<Shard::QueryResponse> ShardLocal::_exhaustiveFindOnConfig(
    OperationContext* txn,
    const ReadPreferenceSetting& readPref,
    const repl::ReadConcernLevel& readConcernLevel,
    const NamespaceString& nss,
    const BSONObj& query,
    const BSONObj& sort,
    boost::optional<long long> limit) {
    auto replCoord = repl::ReplicationCoordinator::get(txn);

    if (readConcernLevel == repl::ReadConcernLevel::kMajorityReadConcern) {
        // Set up operation context with majority read snapshot so correct optime can be retrieved.
        Status status = txn->recoveryUnit()->setReadFromMajorityCommittedSnapshot();

        // Wait for any writes performed by this ShardLocal instance to be committed and visible.
        Status readConcernStatus = replCoord->waitUntilOpTimeForRead(
            txn, repl::ReadConcernArgs{_getLastOpTime(), readConcernLevel});
        if (!readConcernStatus.isOK()) {
            return readConcernStatus;
        }

        // Inform the storage engine to read from the committed snapshot for the rest of this
        // operation.
        status = txn->recoveryUnit()->setReadFromMajorityCommittedSnapshot();
        if (!status.isOK()) {
            return status;
        }
    } else {
        invariant(readConcernLevel == repl::ReadConcernLevel::kLocalReadConcern);
    }

    DBDirectClient client(txn);
    Query fullQuery(query);
    if (!sort.isEmpty()) {
        fullQuery.sort(sort);
    }
    fullQuery.readPref(readPref.pref, BSONArray());

    try {
        std::unique_ptr<DBClientCursor> cursor =
            client.query(nss.ns().c_str(), fullQuery, limit.get_value_or(0));

        if (!cursor) {
            return {ErrorCodes::OperationFailed,
                    str::stream() << "Failed to establish a cursor for reading " << nss.ns()
                                  << " from local storage"};
        }

        std::vector<BSONObj> documentVector;
        while (cursor->more()) {
            BSONObj document = cursor->nextSafe().getOwned();
            documentVector.push_back(std::move(document));
        }

        return Shard::QueryResponse{std::move(documentVector),
                                    replCoord->getCurrentCommittedSnapshotOpTime()};
    } catch (const DBException& ex) {
        return ex.toStatus();
    }
}
Example #10
0
 TEST( Shard, EqualitySingle ) {
     ASSERT_EQUALS(Shard("foo", "b.foo.com:123", 0, false, BSONArray()),
                   Shard("foo", "b.foo.com:123", 0, false, BSONArray()));
     ASSERT_NOT_EQUALS(Shard("foo", "b.foo.com:123", 0, false, BSONArray()),
                       Shard("foo", "a.foo.com:123", 0, false, BSONArray()));
     ASSERT_NOT_EQUALS(Shard("foo", "b.foo.com:123", 0, false, BSONArray()),
                       Shard("foo", "b.foo.com:124", 0, false, BSONArray()));
     ASSERT_NOT_EQUALS(Shard("foo", "b.foo.com:123", 0, false, BSONArray()),
                       Shard("foa", "b.foo.com:123", 0, false, BSONArray()));
 }
Example #11
0
TEST( AllElemMatchOp, MatchesElement ) {


    BSONObj baseOperanda1 = BSON( "a" << 1 );
    auto_ptr<ComparisonMatchExpression> eqa1( new ComparisonMatchExpression() );
    ASSERT( eqa1->init( "a", ComparisonMatchExpression::EQ, baseOperanda1[ "a" ] ).isOK() );

    BSONObj baseOperandb1 = BSON( "b" << 1 );
    auto_ptr<ComparisonMatchExpression> eqb1( new ComparisonMatchExpression() );
    ASSERT( eqb1->init( "b", ComparisonMatchExpression::EQ, baseOperandb1[ "b" ] ).isOK() );

    auto_ptr<AndMatchExpression> and1( new AndMatchExpression() );
    and1->add( eqa1.release() );
    and1->add( eqb1.release() );
    // and1 = { a : 1, b : 1 }

    auto_ptr<ElemMatchObjectMatchExpression> elemMatch1( new ElemMatchObjectMatchExpression() );
    elemMatch1->init( "x", and1.release() );
    // elemMatch1 = { x : { $elemMatch : { a : 1, b : 1 } } }

    BSONObj baseOperanda2 = BSON( "a" << 2 );
    auto_ptr<ComparisonMatchExpression> eqa2( new ComparisonMatchExpression() );
    ASSERT( eqa2->init( "a", ComparisonMatchExpression::EQ, baseOperanda2[ "a" ] ).isOK() );

    BSONObj baseOperandb2 = BSON( "b" << 2 );
    auto_ptr<ComparisonMatchExpression> eqb2( new ComparisonMatchExpression() );
    ASSERT( eqb2->init( "b", ComparisonMatchExpression::EQ, baseOperandb2[ "b" ] ).isOK() );

    auto_ptr<AndMatchExpression> and2( new AndMatchExpression() );
    and2->add( eqa2.release() );
    and2->add( eqb2.release() );

    auto_ptr<ElemMatchObjectMatchExpression> elemMatch2( new ElemMatchObjectMatchExpression() );
    elemMatch2->init( "x", and2.release() );
    // elemMatch2 = { x : { $elemMatch : { a : 2, b : 2 } } }

    AllElemMatchOp op;
    op.init( "" );
    op.add( elemMatch1.release() );
    op.add( elemMatch2.release() );

    BSONObj nonArray = BSON( "x" << 4 );
    ASSERT( !op.matchesSingleElement( nonArray[ "x" ] ) );
    BSONObj emptyArray = BSON( "x" << BSONArray() );
    ASSERT( !op.matchesSingleElement( emptyArray[ "x" ] ) );
    BSONObj nonObjArray = BSON( "x" << BSON_ARRAY( 4 ) );
    ASSERT( !op.matchesSingleElement( nonObjArray[ "x" ] ) );
    BSONObj singleObjMatch = BSON( "x" << BSON_ARRAY( BSON( "a" << 1 << "b" << 1 ) ) );
    ASSERT( !op.matchesSingleElement( singleObjMatch[ "x" ] ) );
    BSONObj otherObjMatch = BSON( "x" << BSON_ARRAY( BSON( "a" << 2 << "b" << 2 ) ) );
    ASSERT( !op.matchesSingleElement( otherObjMatch[ "x" ] ) );
    BSONObj bothObjMatch = BSON( "x" << BSON_ARRAY( BSON( "a" << 1 << "b" << 1 ) <<
                                 BSON( "a" << 2 << "b" << 2 ) ) );
    ASSERT( op.matchesSingleElement( bothObjMatch[ "x" ] ) );
    BSONObj noObjMatch = BSON( "x" << BSON_ARRAY( BSON( "a" << 1 << "b" << 2 ) <<
                               BSON( "a" << 2 << "b" << 1 ) ) );
    ASSERT( !op.matchesSingleElement( noObjMatch[ "x" ] ) );
}
Example #12
0
BSONArray storageEngineList() {
    if (!hasGlobalServiceContext())
        return BSONArray();

    std::unique_ptr<StorageFactoriesIterator> sfi(
        getGlobalServiceContext()->makeStorageFactoriesIterator());

    if (!sfi)
        return BSONArray();

    BSONArrayBuilder engineArrayBuilder;

    while (sfi->more()) {
        engineArrayBuilder.append(sfi->next()->getCanonicalName());
    }

    return engineArrayBuilder.arr();
}
    TEST( ExpressionParserArrayTest, SizeAsString ) {
        BSONObj query = BSON( "x" << BSON( "$size" << "a" ) );
        StatusWithExpression result = ExpressionParser::parse( query );
        ASSERT_TRUE( result.isOK() );

        ASSERT( !result.getValue()->matches( BSON( "x" << 1 ) ) );
        ASSERT( !result.getValue()->matches( BSON( "x" << BSON_ARRAY( 1 << 2 ) ) ) );
        ASSERT( result.getValue()->matches( BSON( "x" << BSONArray() ) ) );
        ASSERT( !result.getValue()->matches( BSON( "x" << BSON_ARRAY( 1 ) ) ) );
    }
Example #14
0
StatusWith<Shard::QueryResponse> ShardLocal::_exhaustiveFindOnConfig(
    OperationContext* txn,
    const ReadPreferenceSetting& readPref,
    const NamespaceString& nss,
    const BSONObj& query,
    const BSONObj& sort,
    boost::optional<long long> limit) {
    // Set up operation context with majority read snapshot so correct optime can be retrieved.
    Status status = txn->recoveryUnit()->setReadFromMajorityCommittedSnapshot();
    auto replCoord = repl::ReplicationCoordinator::get(txn);

    // Ensure timeout is set on the txn so we don't wait forever for the snapshot.
    // TODO (SERVER-18277): Remove this
    CurOp::get(txn)->ensureStarted();

    // Wait until a snapshot is available.
    while (status == ErrorCodes::ReadConcernMajorityNotAvailableYet) {
        LOG(1) << "Waiting for ReadFromMajorityCommittedSnapshot to become available";
        replCoord->waitUntilSnapshotCommitted(txn, SnapshotName::min());
        status = txn->recoveryUnit()->setReadFromMajorityCommittedSnapshot();
    }

    if (!status.isOK()) {
        return status;
    }

    DBDirectClient client(txn);
    Query fullQuery(query);
    if (!sort.isEmpty()) {
        fullQuery.sort(sort);
    }
    fullQuery.readPref(readPref.pref, BSONArray());

    try {
        std::unique_ptr<DBClientCursor> cursor =
            client.query(nss.ns().c_str(), fullQuery, limit.get_value_or(0));

        if (!cursor) {
            return {ErrorCodes::OperationFailed,
                    str::stream() << "Failed to establish a cursor for reading " << nss.ns()
                                  << " from local storage"};
        }

        std::vector<BSONObj> documentVector;
        while (cursor->more()) {
            BSONObj document = cursor->nextSafe().getOwned();
            documentVector.push_back(std::move(document));
        }

        return Shard::QueryResponse{std::move(documentVector),
                                    replCoord->getCurrentCommittedSnapshotOpTime()};
    } catch (const DBException& ex) {
        return ex.toStatus();
    }
}
Example #15
0
TEST( SizeMatchExpression, MatchesNonArray ) {
    // Non arrays do not match.
    BSONObj stringValue = BSON( "a" << "z" );
    BSONObj numberValue = BSON( "a" << 0 );
    BSONObj arrayValue = BSON( "a" << BSONArray() );
    SizeMatchExpression size;
    ASSERT( size.init( "", 0 ).isOK() );
    ASSERT( !size.matchesSingleElement( stringValue.firstElement() ) );
    ASSERT( !size.matchesSingleElement( numberValue.firstElement() ) );
    ASSERT( size.matchesSingleElement( arrayValue.firstElement() ) );
}
    Status parseRolesInfoCommand(const BSONObj& cmdObj,
                                 const StringData& dbname,
                                 RolesInfoArgs* parsedArgs) {
        unordered_set<std::string> validFieldNames;
        validFieldNames.insert("rolesInfo");
        validFieldNames.insert("showPrivileges");
        validFieldNames.insert("showBuiltinRoles");

        Status status = _checkNoExtraFields(cmdObj, "rolesInfo", validFieldNames);
        if (!status.isOK()) {
            return status;
        }

        if (cmdObj["rolesInfo"].numberInt() == 1) {
            parsedArgs->allForDB = true;
        } else if (cmdObj["rolesInfo"].type() == Array) {
            status = parseRoleNamesFromBSONArray(BSONArray(cmdObj["rolesInfo"].Obj()),
                                                 dbname,
                                                 &parsedArgs->roleNames);
            if (!status.isOK()) {
                return status;
            }
        } else {
            RoleName name;
            status = _parseNameFromBSONElement(cmdObj["rolesInfo"],
                                               dbname,
                                               AuthorizationManager::ROLE_NAME_FIELD_NAME,
                                               AuthorizationManager::ROLE_SOURCE_FIELD_NAME,
                                               &name);
            if (!status.isOK()) {
                return status;
            }
            parsedArgs->roleNames.push_back(name);
        }

        status = bsonExtractBooleanFieldWithDefault(cmdObj,
                                                    "showPrivileges",
                                                    false,
                                                    &parsedArgs->showPrivileges);
        if (!status.isOK()) {
            return status;
        }

        status = bsonExtractBooleanFieldWithDefault(cmdObj,
                                                    "showBuiltinRoles",
                                                    false,
                                                    &parsedArgs->showBuiltinRoles);
        if (!status.isOK()) {
            return status;
        }

        return Status::OK();
    }
bool appendEmptyResultSet(OperationContext* opCtx,
                          BSONObjBuilder& result,
                          Status status,
                          const std::string& ns) {
    invariant(!status.isOK());

    CurOp::get(opCtx)->debug().nreturned = 0;
    CurOp::get(opCtx)->debug().nShards = 0;

    if (status == ErrorCodes::NamespaceNotFound) {
        // Old style reply
        result << "result" << BSONArray();

        // New (command) style reply
        appendCursorResponseObject(0LL, ns, BSONArray(), &result);

        return true;
    }

    uassertStatusOK(status);
    return true;
}
    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();
    }
 Status AuthzManagerExternalStateMongos::query(
         const NamespaceString& collectionName,
         const BSONObj& queryDoc,
         const BSONObj& projection,
         const stdx::function<void(const BSONObj&)>& resultProcessor) {
     try {
         scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(collectionName));
         Query query(queryDoc);
         query.readPref(ReadPreference_PrimaryPreferred, BSONArray());
         conn->get()->query(resultProcessor, collectionName.ns(), query, &projection);
         return Status::OK();
     } catch (const DBException& e) {
         return e.toStatus();
     }
 }
Example #21
0
TEST( AllMatchExpression, MatchesArrayAndNonArrayMultiValues ) {
    BSONObj operand = BSON_ARRAY( 1 << 2 << 3 << 4 );
    AllMatchExpression all;
    all.init( "a.b" );
    all.getArrayFilterEntries()->addEquality( operand[0] );
    all.getArrayFilterEntries()->addEquality( operand[1] );
    all.getArrayFilterEntries()->addEquality( operand[2] );
    all.getArrayFilterEntries()->addEquality( operand[3] );

    ASSERT( all.matches( BSON( "a" << BSON_ARRAY( BSON( "b" << BSON_ARRAY( 4 << 5 << 2 ) ) <<
                               BSON( "b" << 3 ) <<
                               BSON( "b" << BSONArray() ) <<
                               BSON( "b" << BSON_ARRAY( 1 ) ) ) ),
                         NULL ) );
}
Example #22
0
TEST( AllElemMatchOp, Matches ) {
    BSONObj baseOperandgt1 = BSON( "$gt" << 1 );
    auto_ptr<ComparisonMatchExpression> gt1( new ComparisonMatchExpression() );
    ASSERT( gt1->init( "", ComparisonMatchExpression::GT, baseOperandgt1[ "$gt" ] ).isOK() );

    BSONObj baseOperandlt1 = BSON( "$lt" << 10 );
    auto_ptr<ComparisonMatchExpression> lt1( new ComparisonMatchExpression() );
    ASSERT( lt1->init( "", ComparisonMatchExpression::LT, baseOperandlt1[ "$lt" ] ).isOK() );

    auto_ptr<ElemMatchValueMatchExpression> elemMatch1( new ElemMatchValueMatchExpression() );
    elemMatch1->init( "x" );
    elemMatch1->add( gt1.release() );
    elemMatch1->add( lt1.release() );

    BSONObj baseOperandgt2 = BSON( "$gt" << 101 );
    auto_ptr<ComparisonMatchExpression> gt2( new ComparisonMatchExpression() );
    ASSERT( gt2->init( "", ComparisonMatchExpression::GT, baseOperandgt2[ "$gt" ] ).isOK() );

    BSONObj baseOperandlt2 = BSON( "$lt" << 110 );
    auto_ptr<ComparisonMatchExpression> lt2( new ComparisonMatchExpression() );
    ASSERT( lt2->init( "", ComparisonMatchExpression::LT, baseOperandlt2[ "$lt" ] ).isOK() );

    auto_ptr<ElemMatchValueMatchExpression> elemMatch2( new ElemMatchValueMatchExpression() );
    elemMatch2->init( "x" );
    elemMatch2->add( gt2.release() );
    elemMatch2->add( lt2.release() );

    AllElemMatchOp op;
    op.init( "x" );
    op.add( elemMatch1.release() );
    op.add( elemMatch2.release() );


    BSONObj nonArray = BSON( "x" << 4 );
    ASSERT( !op.matches( nonArray, NULL ) );
    BSONObj emptyArray = BSON( "x" << BSONArray() );
    ASSERT( !op.matches( emptyArray, NULL ) );
    BSONObj nonNumberArray = BSON( "x" << BSON_ARRAY( "q" ) );
    ASSERT( !op.matches( nonNumberArray, NULL ) );
    BSONObj singleMatch = BSON( "x" << BSON_ARRAY( 5 ) );
    ASSERT( !op.matches( singleMatch, NULL ) );
    BSONObj otherMatch = BSON( "x" << BSON_ARRAY( 105 ) );
    ASSERT( !op.matches( otherMatch, NULL ) );
    BSONObj bothMatch = BSON( "x" << BSON_ARRAY( 5 << 105 ) );
    ASSERT( op.matches( bothMatch, NULL ) );
    BSONObj neitherMatch = BSON( "x" << BSON_ARRAY( 0 << 200 ) );
    ASSERT( !op.matches( neitherMatch, NULL ) );
}
    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();
    }
Example #24
0
Status Database::createView(OperationContext* txn,
                            StringData ns,
                            const CollectionOptions& options) {
    invariant(txn->lockState()->isDbLockedForMode(name(), MODE_X));
    invariant(options.isView());

    NamespaceString nss(ns);
    NamespaceString viewOnNss(nss.db(), options.viewOn);
    _checkCanCreateCollection(nss, options);
    audit::logCreateCollection(&cc(), ns);

    if (nss.isOplog())
        return Status(ErrorCodes::InvalidNamespace,
                      str::stream() << "invalid namespace name for a view: " + nss.toString());

    return _views.createView(txn, nss, viewOnNss, BSONArray(options.pipeline), options.collation);
}
Example #25
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 AuthzManagerExternalStateMongos::findOne(
         const NamespaceString& collectionName,
         const BSONObj& queryDoc,
         BSONObj* result) {
     try {
         scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(collectionName));
         Query query(queryDoc);
         query.readPref(ReadPreference_PrimaryPreferred, BSONArray());
         *result = conn->get()->findOne(collectionName, query).getOwned();
         conn->done();
         if (result->isEmpty()) {
             return Status(ErrorCodes::NoMatchingDocument, mongoutils::str::stream() <<
                           "No document in " << collectionName.ns() << " matches " << queryDoc);
         }
         return Status::OK();
     } catch (const DBException& e) {
         return e.toStatus();
     }
 }
    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();
    }
Example #28
0
 virtual BSONArray splitPoints() const { return BSONArray(); }
        Status _parseAndValidateInput(BSONObj cmdObj, CreateUserArgs* parsedArgs) const {
            unordered_set<std::string> validFieldNames;
            validFieldNames.insert("createUser");
            validFieldNames.insert("user");
            validFieldNames.insert("pwd");
            validFieldNames.insert("userSource");
            validFieldNames.insert("roles");
            validFieldNames.insert("readOnly");
            validFieldNames.insert("otherDBRoles");


            // 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 createUser");
                }
            }

            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("userSource")) {
                parsedArgs->hasUserSource = true;
                status = bsonExtractStringField(cmdObj, "userSource", &parsedArgs->userSource);
                if (!status.isOK()) {
                    return status;
                }
            }

            if (cmdObj.hasField("readOnly")) {
                parsedArgs->hasReadOnly = true;
                status = bsonExtractBooleanField(cmdObj, "readOnly", &parsedArgs->readOnly);
                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 (cmdObj.hasField("roles")) {
                parsedArgs->hasRoles = true;
                BSONElement element;
                status = bsonExtractTypedField(cmdObj, "roles", Array, &element);
                if (!status.isOK()) {
                    return status;
                }
                parsedArgs->roles = BSONArray(element.Obj());
            }

            if (cmdObj.hasField("otherDBRoles")) {
                parsedArgs->hasOtherDBRoles = true;
                BSONElement element;
                status = bsonExtractTypedField(cmdObj, "otherDBRoles", Object, &element);
                if (!status.isOK()) {
                    return status;
                }
                parsedArgs->otherDBRoles = element.Obj();
            }

            if (parsedArgs->hasPassword && parsedArgs->hasUserSource) {
                return Status(ErrorCodes::BadValue,
                              "User objects can't have both 'pwd' and 'userSource'");
            }
            if (!parsedArgs->hasPassword && !parsedArgs->hasUserSource) {
                return Status(ErrorCodes::BadValue,
                              "User objects must have one of 'pwd' and 'userSource'");
            }
            if (parsedArgs->hasRoles && parsedArgs->hasReadOnly) {
                return Status(ErrorCodes::BadValue,
                              "User objects can't have both 'roles' and 'readOnly'");
            }

            return Status::OK();
        }
Example #30
0
TagSet TagSet::primaryOnly() {
    return TagSet{BSONArray()};
}