bool run(OperationContext* opCtx,
             const string& dbname,
             const BSONObj& cmdObj,
             BSONObjBuilder& result) {
        RoleName roleName;
        Status status = auth::parseDropRoleCommand(cmdObj, dbname, &roleName);
        uassertStatusOK(status);

        ServiceContext* serviceContext = opCtx->getClient()->getServiceContext();
        AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);

        auto lk = uassertStatusOK(requireWritableAuthSchema28SCRAM(opCtx, authzManager));

        if (RoleGraph::isBuiltinRole(roleName)) {
            uasserted(ErrorCodes::InvalidRoleModification,
                      str::stream() << roleName.getFullName()
                                    << " is a built-in role and cannot be modified.");
        }

        BSONObj roleDoc;
        status = authzManager->getRoleDescription(opCtx, roleName, &roleDoc);
        uassertStatusOK(status);

        // From here on, we always want to invalidate the user cache before returning.
        auto invalidateGuard = makeGuard([&] {
            try {
                authzManager->invalidateUserCache(opCtx);
            } catch (const DBException& e) {
                // Since this may be called after a uassert, we want to catch any uasserts
                // that come out of invalidating the user cache and explicitly append it to
                // the command response.
                CommandHelpers::appendCommandStatusNoThrow(result, e.toStatus());
            }
        });

        // Remove this role from all users
        long long nMatched;
        status = updateAuthzDocuments(
            opCtx,
            AuthorizationManager::usersCollectionNamespace,
            BSON("roles" << BSON("$elemMatch" << BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME
                                                      << roleName.getRole()
                                                      << AuthorizationManager::ROLE_DB_FIELD_NAME
                                                      << roleName.getDB()))),
            BSON("$pull" << BSON("roles" << BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME
                                                 << roleName.getRole()
                                                 << AuthorizationManager::ROLE_DB_FIELD_NAME
                                                 << roleName.getDB()))),
            false,
            true,
            &nMatched);
        if (!status.isOK()) {
            uassertStatusOK(useDefaultCode(status, ErrorCodes::UserModificationFailed)
                                .withContext(str::stream() << "Failed to remove role "
                                                           << roleName.getFullName()
                                                           << " from all users"));
        }

        // Remove this role from all other roles
        status = updateAuthzDocuments(
            opCtx,
            AuthorizationManager::rolesCollectionNamespace,
            BSON("roles" << BSON("$elemMatch" << BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME
                                                      << roleName.getRole()
                                                      << AuthorizationManager::ROLE_DB_FIELD_NAME
                                                      << roleName.getDB()))),
            BSON("$pull" << BSON("roles" << BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME
                                                 << roleName.getRole()
                                                 << AuthorizationManager::ROLE_DB_FIELD_NAME
                                                 << roleName.getDB()))),
            false,
            true,
            &nMatched);
        if (!status.isOK()) {
            uassertStatusOK(
                useDefaultCode(status, ErrorCodes::RoleModificationFailed)
                    .withContext(
                        str::stream() << "Removed role " << roleName.getFullName()
                                      << " from all users but failed to remove from all roles"));
        }

        audit::logDropRole(Client::getCurrent(), roleName);
        // Finally, remove the actual role document
        status = removeRoleDocuments(opCtx,
                                     BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME
                                          << roleName.getRole()
                                          << AuthorizationManager::ROLE_DB_FIELD_NAME
                                          << roleName.getDB()),
                                     &nMatched);
        if (!status.isOK()) {
            uassertStatusOK(status.withContext(
                str::stream() << "Removed role " << roleName.getFullName()
                              << " from all users and roles but failed to actually delete"
                                 " the role itself"));
        }

        dassert(nMatched == 0 || nMatched == 1);
        if (nMatched == 0) {
            uasserted(ErrorCodes::RoleNotFound,
                      str::stream() << "Role '" << roleName.getFullName() << "' not found");
        }

        return true;
    }