4

I am able to migrate all the datas of users account including the password but it doesn’t work due to encryption and hash in drupal 8.

My password are not MD5. They are not encrypted, in csv file they are like normal plain text.

I’ve seen here : https://www.drupal.org/docs/8/api/migrate-api/migrate-destination-entityuser

If the incoming passwords are not plain or are not MD5 hashed you'll have to deal with this in your migration

My password are plain so i guess it should work.

Here is what i’ve tried but the password are imported but not encrypted :

destination:
  plugin: 'entity:user'
  plaintext_passwords: true

In the documentation, it is explained how to import MD5 password but not plain password.

What should i use for the configuration ?


EDIT :

I’ve tried this :

pass:
    -
      plugin: callback
      callable: 'Drupal\Core\Password\PhpassHashedPassword::hash'
      source: passwebservice

And

pass:
    -
      plugin: callback
      callable:
        - 'Drupal\Core\Password\PhpassHashedPassword'
        - hash
      source: passwebservice

Error :

Error: Using $this when not in object context in Drupal\Core\Password\PhpassHashedPassword::hash() [error] (line 215 of Core/Password/PhpassHashedPassword.php) 0 [internal function]: Drupal\Core\Password\PhpassHashedPassword::hash('9BQmM1') 1 core/modules/migrate/src/Plugin/migrate/process/Callback.php(54): call_user_func('Drupal\Core\Pas...', '9BQmM1')

When i check hash()

public function hash($password) {
    return $this->crypt('sha512', $password, $this->generateSalt());
  }

I can't invoke method this way ($this does not exist in class context) so how can I do ? Is it possible in configuration file ?

  • \Drupal::service('password')->hash($password) – user21641 Oct 3 '17 at 11:55
  • @IvanJaros I need a little bit more explanation. I guess it is a 2 step process : i import plain text password in database (i can do this) and then i hash the password with your code ? – Sébastien Gicquel Oct 3 '17 at 12:00
  • The function you are calling is not a static function. The docs say only static function. There is also a known bug for plain passwords. drupal.org/node/2816921 – CG Monroe Oct 3 '17 at 22:09
4

You can use Ivan Jaros' code in two ways:

As you said, preprocess your passwords to convert them to hashes. This can be done via a Drush script that can be run from the command line. Drush scripts are just snippets of PhP code that run in the Drupal context. Run by the command:

drush @site-alias scr [path to php snippet]

The alternative is to override you CVS Source class and use the preparerow method to hash the password.

  /**
   * {@inheritdoc}
   */
  public function prepareRow(Row $row) {
    $password = $row->getSourceProperty('password');
    $hash = \Drupal::service('password')->hash($password);
    $row->setSourceProperty('password', $hash);
  }

As pointed out in the comments, you can also use a process plug-in to do this. The callback plugin only uses static classes and AFIAK the hash method requires access to the context information that is not available via static methods.

Here's some quick untested code to create your own process plug-in to hash a plain text password.

<?php

namespace Drupal\my_mode\Plugin\migrate\process;

use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;

/**
 * Converts a plain password to an hash.
 *
 * Example:
 *
 * @code
 * process:
 *   password:
 *     plugin: my_module_hash_password
 *     source: field_password
 * @endcode
 *
 * @see \Drupal\migrate\Plugin\MigrateProcessInterface
 *
 * @MigrateProcessPlugin(
 *   id = "my_module_hash_password"
 * )
 */
class HashPassword extends ProcessPluginBase {

  /**
   * {@inheritdoc}
   */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    $hash = \Drupal::service('password')->hash($value);
    return $hash;
  }

}
  • Thanx for this explanation. I will try. Do you know if it is possible to do it with Process plugin: callback like this : drupal.org/docs/8/api/migrate-api/migrate-process/… This way, the hash could be done with the migrate configuration file – Sébastien Gicquel Oct 3 '17 at 15:59
  • Since it's a simple value transformation, that should work. FWIW - I have mostly done custom source plugins that override prepareRow and some other methods because of the need for more detailed processing. E.g. validating terms and other info from the source and skipping rows (return False). Doing it this ways a bit more complicated to set up but more flexible. – CG Monroe Oct 3 '17 at 18:19
  • I’ve updated my question. If you can have a look and tell me what you think ? I would like to know if it's possible to use configuration file because i’ve spent a few hours on migrate module and i want to pursue it to the end – Sébastien Gicquel Oct 3 '17 at 20:23
0

I have written custom migration to migrate users from CSV file. I have successfully migrated the user but when i tried to login its give me login error so I have checked my migration code found md5_passwords: true in it. md5_passwords convert any string to hashed string with md5() encryption. so i have written my custom plugin and added to my migration code without md5_passwords: true.

Here is the step by step solution:

  1. Create custom module and define your plugins file in it:

    custom_module->src->Plugins->plugins_name->process->plugin_file.php
    

    in my case:

    custom_module->src->Plugins->migrate->process->HashPasswords.php
    
  2. Write this example code in your plugin_file.php

    <?php
    
    namespace Drupal\custom_module\Plugin\migrate\process;
    use Drupal\Core\Password\PhpassHashedPassword;
    use Drupal\migrate\MigrateExecutableInterface;
    use Drupal\migrate\ProcessPluginBase;
    use Drupal\migrate\Row;
    
    /**
    * Converts a plain password to an hash.
    *
    * Example:
    *
    * @code
    * process:
    *   password:
    *     plugin: hashpasswords
    *     source: password
    * @endcode
    *
    * @see \Drupal\migrate\Plugin\MigrateProcessInterface
    *
    * @MigrateProcessPlugin(
    *   id = "hashpasswords"
    * )
    */
    class HashPasswords extends ProcessPluginBase {
    
    /**
    * {@inheritdoc}
    */
      public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
       $passwordHasher = new PhpassHashedPassword(1);
       $hashedPassword = $passwordHasher->hash($value);
       return $hashedPassword;
      }
    } ?>`
    
  3. Now write your migration code and add this custom plugin.

    id: ROF_user
    label: 'Migrate ROF User from CSV'
    source:
      plugin: csv
      path: modules/custom/custom_module/csv/user.csv
      header_row_count: 1
      keys:
        - ID
    process:
      uid: ID
      name: name
      field_first_name: firstname
      field_last_name: lastname
      mail: email
      pass:
        plugin: hashpasswords
        source: password
      roles:
        plugin: explode
        delimiter: ','
        source: roles
      status: status
    destination:
      plugin: 'entity:user'
    migration_dependencies:
      required: {  }
      optional: {  }
    

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.