I have a site where users/customers were being uploaded from an external source every five minutes. We found that if one of these users was logged in, they were unexpectedly logged out whenever the migration ran.

It looks like the problem is as described here: http://drupal.stackexchange.com/questions/40438/users-are-getting-sponta...

Comments

fonant created an issue.

fonant’s picture

As per the linked description, the code in user_save() that is logging the user out is as follows:

      // If the password changed, delete all open sessions and recreate
      // the current one.
      if ($account->pass != $account->original->pass) {
        drupal_session_destroy_uid($account->uid);
        if ($account->uid == $GLOBALS['user']->uid) {
          drupal_session_regenerate();
        }
      }

Hmmm... are we changing the password every import, perhaps?

fonant’s picture

Findings so far:

  • MigrateDestinationUser allows a plain-text password or an MD5 password hash. It does not have an option to use an existing password hash if the migration is called with --update. Could this be a useful option, perhaps?
  • MigrateDestinationUser::import() copies the account data to $old_account before calling Migration::prepare(), so this method cannot be used to copy the original password hash into the $old_account. Perhaps the call to prepare() could usefully be moved earlier in the import() method code?
  • The new account data comes from the fields mapped in the migration: and we cannot map the existing password hash.
  • The original account data is loaded using entity_load_unchanged() within user_save().
  • If the migration does not supply a password, the new and original passwords don't match, so the user is logged out in user_save().

It doesn't seem possible to use Migrate methods to set the existing password hash before MigrateDestinationUser::import() calls user_save. This means the user_save() function call will log out the user referred to by $old_account.

I _think_ I have a workaround using hook_user_presave() in a custom module:

/**
 * Implements hook_user_presave().
 */
function mymodule_user_presave(&$edit, $account, $category) {
  // If we're not changing password, copy existing password hash as needed.
  if (!isset($edit['pass']) and isset($account->original) and !isset($account->pass)) {
    $account->pass = $account->original->pass;
  }
}