Status checkAuthForUpdateRoleCommand(ClientBasic* client,
                                     const std::string& dbname,
                                     const BSONObj& cmdObj) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    auth::CreateOrUpdateRoleArgs args;
    Status status = auth::parseCreateOrUpdateRoleCommands(cmdObj, "updateRole", dbname, &args);
    if (!status.isOK()) {
        return status;
    }

    // You don't know what roles or privileges you might be revoking, so require the ability
    // to revoke any role (or privilege) in the system.
    if (!authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forAnyNormalResource(),
                                                        ActionType::revokeRole)) {
        return Status(ErrorCodes::Unauthorized,
                      "updateRole command required the ability to revoke any role in the "
                      "system");
    }

    status = checkAuthorizedToGrantRoles(authzSession, args.roles);
    if (!status.isOK()) {
        return status;
    }

    return checkAuthorizedToGrantPrivileges(authzSession, args.privileges);
}
Status checkAuthForCreateRoleCommand(Client* client,
                                     const std::string& dbname,
                                     const BSONObj& cmdObj) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    auth::CreateOrUpdateRoleArgs args;
    Status status = auth::parseCreateOrUpdateRoleCommands(cmdObj, "createRole", dbname, &args);
    if (!status.isOK()) {
        return status;
    }

    if (!authzSession->isAuthorizedToCreateRole(args)) {
        return Status(ErrorCodes::Unauthorized,
                      str::stream() << "Not authorized to create roles on db: "
                                    << args.roleName.getDB());
    }

    status = checkAuthorizedToGrantRoles(authzSession, args.roles);
    if (!status.isOK()) {
        return status;
    }

    status = checkAuthorizedToGrantPrivileges(authzSession, args.privileges);
    if (!status.isOK()) {
        return status;
    }

    status = checkAuthorizedToSetRestrictions(
        authzSession, static_cast<bool>(args.authenticationRestrictions), args.roleName.getDB());
    if (!status.isOK()) {
        return status;
    }

    return Status::OK();
}
Status checkAuthForGrantPrivilegesToRoleCommand(Client* client,
                                                const std::string& dbname,
                                                const BSONObj& cmdObj) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    PrivilegeVector privileges;
    RoleName unusedRoleName;
    Status status = auth::parseAndValidateRolePrivilegeManipulationCommands(
        cmdObj, "grantPrivilegesToRole", dbname, &unusedRoleName, &privileges);
    if (!status.isOK()) {
        return status;
    }

    return checkAuthorizedToGrantPrivileges(authzSession, privileges);
}
Status checkAuthForCreateRoleCommand(ClientBasic* client,
                                     const std::string& dbname,
                                     const BSONObj& cmdObj) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    auth::CreateOrUpdateRoleArgs args;
    Status status = auth::parseCreateOrUpdateRoleCommands(cmdObj, "createRole", dbname, &args);
    if (!status.isOK()) {
        return status;
    }

    if (!authzSession->isAuthorizedForActionsOnResource(
            ResourcePattern::forDatabaseName(args.roleName.getDB()), ActionType::createRole)) {
        return Status(ErrorCodes::Unauthorized,
                      str::stream()
                          << "Not authorized to create roles on db: " << args.roleName.getDB());
    }

    status = checkAuthorizedToGrantRoles(authzSession, args.roles);
    if (!status.isOK()) {
        return status;
    }

    return checkAuthorizedToGrantPrivileges(authzSession, args.privileges);
}