bool run(OperationContext* txn,
             const string& dbname,
             BSONObj& cmdObj,
             int options,
             string& errmsg,
             BSONObjBuilder& result) {
        auth::CreateOrUpdateUserArgs args;
        Status status = auth::parseCreateOrUpdateUserCommands(cmdObj, "createUser", dbname, &args);
        if (!status.isOK()) {
            return appendCommandStatus(result, status);
        }

        if (args.userName.getDB() == "local") {
            return appendCommandStatus(
                result, Status(ErrorCodes::BadValue, "Cannot create users in the local database"));
        }

        if (!args.hasHashedPassword && args.userName.getDB() != "$external") {
            return appendCommandStatus(
                result,
                Status(ErrorCodes::BadValue,
                       "Must provide a 'pwd' field for all user documents, except those"
                       " with '$external' as the user's source db"));
        }

        if ((args.hasHashedPassword) && args.userName.getDB() == "$external") {
            return appendCommandStatus(
                result,
                Status(ErrorCodes::BadValue,
                       "Cannot set the password for users defined on the '$external' "
                       "database"));
        }

        if (!args.hasRoles) {
            return appendCommandStatus(
                result,
                Status(ErrorCodes::BadValue, "\"createUser\" command requires a \"roles\" array"));
        }

#ifdef MONGO_CONFIG_SSL
        if (args.userName.getDB() == "$external" && getSSLManager() &&
            getSSLManager()->getSSLConfiguration().isClusterMember(args.userName.getUser())) {
            return appendCommandStatus(result,
                                       Status(ErrorCodes::BadValue,
                                              "Cannot create an x.509 user with a subjectname "
                                              "that would be recognized as an internal "
                                              "cluster member."));
        }
#endif

        BSONObjBuilder userObjBuilder;
        userObjBuilder.append(
            "_id", str::stream() << args.userName.getDB() << "." << args.userName.getUser());
        userObjBuilder.append(AuthorizationManager::USER_NAME_FIELD_NAME, args.userName.getUser());
        userObjBuilder.append(AuthorizationManager::USER_DB_FIELD_NAME, args.userName.getDB());

        ServiceContext* serviceContext = txn->getClient()->getServiceContext();
        AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
        int authzVersion;
        status = authzManager->getAuthorizationVersion(txn, &authzVersion);
        if (!status.isOK()) {
            return appendCommandStatus(result, status);
        }

        BSONObjBuilder credentialsBuilder(userObjBuilder.subobjStart("credentials"));
        if (!args.hasHashedPassword) {
            // Must be an external user
            credentialsBuilder.append("external", true);
        } else {
            // Add SCRAM credentials for appropriate authSchemaVersions.
            if (authzVersion > AuthorizationManager::schemaVersion26Final) {
                BSONObj scramCred = scram::generateCredentials(
                    args.hashedPassword, saslGlobalParams.scramIterationCount);
                credentialsBuilder.append("SCRAM-SHA-1", scramCred);
            } else {  // Otherwise default to MONGODB-CR.
                credentialsBuilder.append("MONGODB-CR", args.hashedPassword);
            }
        }
        credentialsBuilder.done();

        if (args.hasCustomData) {
            userObjBuilder.append("customData", args.customData);
        }
        userObjBuilder.append("roles", rolesVectorToBSONArray(args.roles));

        BSONObj userObj = userObjBuilder.obj();
        V2UserDocumentParser parser;
        status = parser.checkValidUserDocument(userObj);
        if (!status.isOK()) {
            return appendCommandStatus(result, status);
        }

        stdx::lock_guard<stdx::mutex> lk(getAuthzDataMutex(serviceContext));

        status = requireAuthSchemaVersion26Final(txn, authzManager);
        if (!status.isOK()) {
            return appendCommandStatus(result, status);
        }

        // Role existence has to be checked after acquiring the update lock
        for (size_t i = 0; i < args.roles.size(); ++i) {
            BSONObj ignored;
            status = authzManager->getRoleDescription(
                txn, args.roles[i], PrivilegeFormat::kOmit, &ignored);
            if (!status.isOK()) {
                return appendCommandStatus(result, status);
            }
        }

        audit::logCreateUser(Client::getCurrent(),
                             args.userName,
                             args.hasHashedPassword,
                             args.hasCustomData ? &args.customData : NULL,
                             args.roles);
        status = insertPrivilegeDocument(txn, userObj);
        return appendCommandStatus(result, status);
    }