Status AuthorizationSession::checkAuthForAggregate(const NamespaceString& ns,
                                                   const BSONObj& cmdObj) {
    std::string db(ns.db().toString());
    auto inputResource = ResourcePattern::forExactNamespace(ns);
    uassert(
        17138, mongoutils::str::stream() << "Invalid input namespace, " << ns.ns(), ns.isValid());

    PrivilegeVector privileges;

    BSONElement pipelineElem = cmdObj["pipeline"];
    if (pipelineElem.type() != BSONType::Array) {
        return Status(ErrorCodes::TypeMismatch, "'pipeline' must be specified as an array");
    }

    BSONObj pipeline = pipelineElem.embeddedObject();
    if (pipeline.isEmpty()) {
        // The pipeline is empty, so we require only the find action.
        Privilege::addPrivilegeToPrivilegeVector(&privileges,
                                                 Privilege(inputResource, ActionType::find));
    } else {
        if (pipeline.firstElementType() != BSONType::Object) {
            // The pipeline contains something that's not an object.
            return Status(ErrorCodes::TypeMismatch,
                          "'pipeline' cannot contain non-object elements");
        }

        // We treat the first stage in the pipeline specially, as some aggregation stages that are
        // valid initial sources have different auth requirements.
        BSONObj firstPipelineStage = pipeline.firstElement().embeddedObject();
        if (str::equals("$indexStats", firstPipelineStage.firstElementFieldName())) {
            Privilege::addPrivilegeToPrivilegeVector(
                &privileges, Privilege(inputResource, ActionType::indexStats));
        } else if (str::equals("$collStats", firstPipelineStage.firstElementFieldName())) {
            Privilege::addPrivilegeToPrivilegeVector(
                &privileges, Privilege(inputResource, ActionType::collStats));
        } else {
            // If no source requiring an alternative permission scheme is specified then default to
            // requiring find() privileges on the given namespace.
            Privilege::addPrivilegeToPrivilegeVector(&privileges,
                                                     Privilege(inputResource, ActionType::find));
        }

        // Add additional required privileges for each stage in the pipeline.
        for (auto&& stageElem : pipeline) {
            _addPrivilegesForStage(db, cmdObj, &privileges, stageElem.embeddedObjectUserCheck());
        }
    }

    if (isAuthorizedForPrivileges(privileges))
        return Status::OK();
    return Status(ErrorCodes::Unauthorized, "unauthorized");
}
Status AuthorizationSession::checkAuthForAggregate(const NamespaceString& ns,
                                                   const BSONObj& cmdObj) {
    std::string db(ns.db().toString());
    auto inputResource = ResourcePattern::forExactNamespace(ns);
    uassert(
        17138, mongoutils::str::stream() << "Invalid input namespace, " << ns.ns(), ns.isValid());

    PrivilegeVector privileges;

    BSONElement pipelineElem = cmdObj["pipeline"];
    if (pipelineElem.type() != BSONType::Array) {
        return Status(ErrorCodes::TypeMismatch, "'pipeline' must be specified as an array");
    }

    BSONObj pipeline = pipelineElem.embeddedObject();
    if (pipeline.isEmpty()) {
         
        Privilege::addPrivilegeToPrivilegeVector(&privileges,
                                                 Privilege(inputResource, ActionType::find));
    } else {
        if (pipeline.firstElementType() != BSONType::Object) {
             
            return Status(ErrorCodes::TypeMismatch,
                          "'pipeline' cannot contain non-object elements");
        }

         
         
        BSONObj firstPipelineStage = pipeline.firstElement().embeddedObject();
        if (str::equals("$indexStats", firstPipelineStage.firstElementFieldName())) {
            Privilege::addPrivilegeToPrivilegeVector(
                &privileges, Privilege(inputResource, ActionType::indexStats));
        } else if (str::equals("$collStats", firstPipelineStage.firstElementFieldName())) {
            Privilege::addPrivilegeToPrivilegeVector(
                &privileges, Privilege(inputResource, ActionType::collStats));
        } else {
             
             
            Privilege::addPrivilegeToPrivilegeVector(&privileges,
                                                     Privilege(inputResource, ActionType::find));
        }

         
        for (auto&& stageElem : pipeline) {
            _addPrivilegesForStage(db, cmdObj, &privileges, stageElem.embeddedObjectUserCheck());
        }
    }

    if (isAuthorizedForPrivileges(privileges))
        return Status::OK();
    return Status(ErrorCodes::Unauthorized, "unauthorized");
}