# User Migration

* If user passwords in the old system are encrypted using MD5, SHA1, or SHA256, you can migrate users using these algorithms.
* Otherwise, after users are migrated, they must create a new password using the **Forgot Password** option during their first login. In this case, get in touch with the Akinon team to receive assistance regarding the password\_algorithm value to be used in the upcoming steps.
* Migrated users can be checked in the omnitron panel under **Sales Channel > Users** section.
* Unencrypted credentials of the test user undergoing migration will be needed for future checks.
* The user being imported must not have a record in Omnitron. The email field must be unique.

## <mark style="color:red;">Commerce ENV Settings</mark>

If the encryption algorithm is "md5," then the PASSWORD\_HASHERS list in the ENV should be updated as follows:

```

PASSWORD_HASHERS='django.contrib.auth.hashers.PBKDF2PasswordHasher','django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher','django.contrib.auth.hashers.Argon2PasswordHasher','django.contrib.auth.hashers.BCryptSHA256PasswordHasher','django.contrib.auth.hashers.BCryptPasswordHasher','django.contrib.auth.hashers.MD5PasswordHasher','django.contrib.auth.hashers.UnsaltedMD5PasswordHasher'

```

If the encryption algorithm is "sha1," then the PASSWORD\_HASHERS list in the ENV should be updated as follows:

```

PASSWORD_HASHERS='django.contrib.auth.hashers.PBKDF2PasswordHasher','django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher','django.contrib.auth.hashers.Argon2PasswordHasher','django.contrib.auth.hashers.BCryptSHA256PasswordHasher','django.contrib.auth.hashers.BCryptPasswordHasher','omnishop.users.helpers.SHA1MD5PasswordHasher','django.contrib.auth.hashers.SHA1PasswordHasher', ‘django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher'

```

If the encryption algorithm is "sha256," then the PASSWORD\_HASHERS list in the ENV should be updated as follows:

```

PASSWORD_HASHERS='django.contrib.auth.hashers.PBKDF2PasswordHasher','django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher','django.contrib.auth.hashers.Argon2PasswordHasher','django.contrib.auth.hashers.BCryptSHA256PasswordHasher','django.contrib.auth.hashers.BCryptPasswordHasher','omnishop.users.helpers.SHA256PasswordHasher', ‘omnishop.users.helpers.SHA256UnsaltedPasswordHasher'

```

### Example Request

```
curl --location --request POST 'https://{{omnitron_url}}/api/v1/remote/{{channel_id}}/migrations/start/user/' \
--header 'Authorization: Token {{token}}' \
--form 'file=@"/path/to/test_user.json"'

```

#### **Test User File Format (test\_user.json)**

```json
[
    {
        "first_name": "Lorem",
        "last_name": "Ipsum",
        "email": "lorem.ipsum@mail.com",
        "gender": "male",
        "sms_allowed": false,
        "email_allowed": false,
        "phone": "999999999",
        "date_of_birth": "1990-01-13",
        "date_joined": "2022-01-13 09:26:00",
        "password": "sha1$salt$7c4a8d09ca3762af61e59520943ddc26494f8941b",
        "password_algorithm": "sha1",
        "customer_code": "1",
        "verified": true,
        "facebook_uuid": null,
        "attributes": {},
        "call_allowed": false,
        "user_type": "registered"
    }
]
```

**Description:**

The data format requirements for each field are as follows:

* **"first\_name"**: Should be in String format and is mandatory.
* **"last\_name"**: Should be in String format and is mandatory.
* **"email"**: Should be in Email format and is mandatory.
* **"gender"**: Should be in String format, can be null or an empty string. Acceptable values are 'male' or 'female'.
* **"sms\_allowed"**: Should be in Boolean format and is mandatory.
* **"email\_allowed"**: Should be in Boolean format and is mandatory.
* **"phone"**: Should be in the format "5XXXXXXXXX" as a string. Can be null. For foreign numbers, please seek assistance from the Akinon team.
* **"date\_of\_birth"**: Format is detailed in the date\_format section. Can be null.
* **"date\_joined"**: Format is detailed in the datetime\_format section and is mandatory.
* **"password"**: Format is detailed in the password section and is mandatory.
* **"password\_algorithm"**: Should be in String format. Acceptable values are 'sha1', 'md5', or 'sha256'. Mandatory.
* **"customer\_code"**: Should be in String format and is mandatory. After migration, this information will be stored in user.attributes.migration\_customer\_code.
* **"verified"**: Should be in Boolean format and is mandatory.
* **"facebook\_uuid"**: Should be in String format, can be null or an empty string.
* **"attributes"**: Should be in Dictionary format and is mandatory. If empty, it should be provided as {}.
* **"call\_allowed"**: Should be in Boolean format.
* **"user\_type"**: Should be in String format and is mandatory. Acceptable values are 'guest' or 'registered'.

**Date Format:**

The following formats are accepted as date\_format:

* '%Y-%m-%d'
* '%Y/%m/%d'
* '%d.%m.%Y'
* '%d-%m-%Y'
* '%d/%m/%Y'

**Password Format:**

It should be provided in the following format:\
`{algorithm}${salt}${hash_value}`

* **algorithm:** Can be `sha1`, `md5`, or `sha256`.
  * If **no salt** is used, the algorithm value must be set as `unsalted_sha256` instead of `sha256`.
  * Example:

    ```json
    "password": "unsalted_sha256$$02368e229cacd51bdd9c0284744dc049e7f1de06f0fd42529a98c931b5cd59a0",
    "password_algorithm": "sha256"
    ```
* **salt:** If unsalted, should be left empty.
* **hash\_value:** The hash value.

### Example Response

When a request is made using cURL, the response received will be as follows:

```
{"migration_id": "2740e84efe2e4bea91615f46f567aa3c"}
```

#### **Control**

For verification, the following request is sent:

```
curl --location --request GET 'https://{{omnitron_url}}/api/v1/remote/{{channel_id}}/migrations/{{migration_id}}/progress/' \  
--header 'Authorization: Token {{token}}'
```

If the response received is as follows:

```
{
    "total_count": 1,
    "error_count": 0,
    "processed_count": 1
}
```

The response means that the user has been successfully migrated.
