Jump to the post that solved this thread.
Solved: 5 Years, 6 Months, 3 Weeks ago Bulk import users by writing directly to users table
#1
Solved: 5 Years, 6 Months, 3 Weeks ago
Hi,

I'm helping out with a new installation of MyBB (1.8) for an established community that presently uses Google Groups.  Before that, it was a mailman mailing list for maybe 15-20 years or so.  

So there are a fair few users and the transition is going to be painful enough for some of them.  I'd like to make this as simple as possible by pre-creating accounts for them, and entering them manually isn't an option.

There is a ModX format mod, but it appears to be for an earlier version of MyBB, and I can't find any equivalent on the new MyBB plugins site.

I'm handy enough with SQL and scripting (I prefer Python, but I can write PHP at a push) and quite comfortable with vim and remote shell, so my question is:

Can I get away with writing a script to generate a username and password, insert rows into directly into the users table (and email the user with their pw)?  Or do I need to mess with other tables?

I figure that a minimum set of fields would be username, password, salt, email and usergroup (registered users).

Should I use an existing row as a template, or will leaving everything else empty provide sane defaults?  Or perhaps I would do better by instantiating whatever is the user class?  (A hint of where to find that and what is required to instantiate it would be welcome!)

How is the salt generated?  Looks like it's a random 8-character alphanumeric string.

How is the password generated?  Is it still:
$stored_pass = md5(md5($salt).md5($plain_pass));
?

Is there a smarter way to go about it than hacking code?

If I can make this work acceptably, I'll make the code available.  Seeing as it'll most likely be in Python, I'll link it from this thread.
Reply
#2
Solved: 5 Years, 6 Months, 3 Weeks ago
I'd recommend using the user datahandler class for this because it makes sure to populate all tables that are needed. Look at /inc/datahandlers/user.php.
Reply
#3
Solved: 5 Years, 6 Months, 3 Weeks ago
(2017-01-11, 03:11 AM)dragonexpert Wrote: I'd recommend using the user datahandler class for this because it makes sure to populate all tables that are needed. Look at /inc/datahandlers/user.php.

That would seem to be the sanest option, thanks for the pointer (and I can see the sanity checks in UserDataHandler).

Is there any web-based documentation on the core functions and classes, similar to WordPress's codex, or is it a case of "the code is the documentation"? Smile

And if I have any trouble on the PHP end of things, should I post here or to the dev's forum?

Thanks,

s.
Reply
#4
Solved: 5 Years, 6 Months, 3 Weeks ago
There is some documentation on the site here under Docs, but most of it is by looking through code. I have some plugin techniques here: https://github.com/dragonexpert/tutorial...pment.html

Any issues with this I'd say should go to Plugin Development.
Reply
#5
Solved: 5 Years, 6 Months, 3 Weeks ago
(2017-01-11, 04:05 PM)dragonexpert Wrote: Any issues with this I'd say should go to Plugin Development.

Thanks for the tips and for the direction.  I'll mark this thread as resolved, and then post my solution once it's completed.

Cheers!

Here's my first attempt at a CSV user importer.  It's command-line only, sorry, because that's all I need.  Plus, as you will see, it is quite simple.  Because it's so short, I'm pasting the code here.  If admins prefer, I can host it on my server and link it.

I assume anybody who knows how to use a shell will know what to do with this.  Perhaps someone who does UI stuff might turn this into a proper MyBB plugin.

CAUTION: 
  • I've put in some protection to prevent the script from being invoked from the web, but I can't promise anything, especially not on a Windows-hosted instance.

  • Just to reiterate: do not put csv files in your docroot or public_html directory or plain-text passwords might be visible to the world if they can guess the filename.

<?php
/*
 * mybb_csv_users.php -- MyBB mass import users from CSV, v1.0
 *
 * (c) 2017 David King
 *
 * Licence: GPL 2.1.  No warranties express or implied.  Use at your own risk.
 *
 * This is a **COMMAND-LINE** tool for mass creation of MyBB users.
 *
 * Instructions for use:
 *      - create a csv file describing the users to create:
 *              - **DO NOT** put this anywhere in your web docroot!
 *              - The first line must be a header labelling each field
 *              - Mandatory fields: username, password, email, usergroup
 *                      - password is plain-text (hence warning about docroot)
 *              - Optional field: regdate, a unix timestamp
 *              - leading and trailing whitespace is stripped which may have
 *                implications for the password.
 *
 *      - put this code in your MyBB root directory
 *
 *      - from the shell:
 *              php mybb_csv_users.php /path/to/user_data.csv
 *
 * Errors will be printed and the script will continue with the next row,
 * so you might want to capture the output so you can rerun with those users
 * fixed.
 *
 * If everything went well, there will be no output.
 */

// Sanity/security checks
array_key_exists( 'SHELL', $_SERVER ) || die( "This tool can only be run from the command line." );
count( $argv ) == 2 || die( "syntax: ${argv[0]} <csv_file>\n" );

$csv_file = $argv[1];

define('IN_MYBB', 1);
require_once './global.php';
require_once MYBB_ROOT.'inc/datahandlers/user.php';

// Open CSV file and get header
$csv = fopen( $csv_file, 'rt' );
$hdr = array_map( 'trim', fgetcsv( $csv ) );

// Check that required fields are present
foreach( Array( 'username', 'password', 'email', 'usergroup' ) as $k ) {
        in_array( $k, $hdr ) || die( "CSV must contain $k field\n" );
}

// Read and add users
$rc = 0;
while( $u = fgetcsv( $csv ) ) {
        $u = array_combine( $hdr, array_map( 'trim', $u ) );

        // Determine group ID (yeah, this should be cached, but KISS)
        $gid = $db->simple_select( "usergroups", "gid", "title = '${u['usergroup']}'", array('order_by' => 'gid') );
        $gid = $db->fetch_field( $gid, 'gid' );
        if( !$gid ) {
                print "${u['username']}: no such group\n";
                $rc = 1;
                continue;
        }
        $u['usergroup'] = $gid;

        // Create user
        $new_user = new UserDataHandler( 'insert' );
        $new_user->set_data( $u );
        if( $new_user->validate_user() ) {
                $user_info = $new_user->insert_user();
        } else {
                foreach( $new_user->get_friendly_errors() as $err ) {
                        print "${u['username']}: $err\n";
                }
                $rc = 1;
        }
}

exit( $rc );
Reply
Jump to the post that solved this thread.


Forum Jump:


Users browsing this thread: 1 Guest(s)