Очень частой задачей является перенести пользователей со старой системы 1С-Битрикс на новую. При этом мы конечно же хотим сохранить весь процесс незаметным для клиента что бы не приходилось делать массовую рассылку с временным паролем и так далее.
Экспорт пользователей
Мы можем настроить необходимые столбцы и экспортировать данные в формате Excel с помощью стандартного функционала Битрикс, так же можно сделать экспорт через phpMyAdmin, но мы решили написать этот функционал самостоятельно. На исходном сайте создаем файл, например users.php со следующим содержимым:
// Подключаем пролог Bitrix require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php"); // Проверяем права доступа if (!$USER->IsAdmin()) { die("Access denied"); } // Устанавливаем заголовки для скачивания CSV файла header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename=users.csv'); // Открываем поток для записи в файл $output = fopen('php://output', 'w'); // Записываем заголовки столбцов fputcsv($output, array('ID', 'NAME', 'LAST_NAME' ,'LOGIN','PASSWORD', 'EMAIL')); $rsUsers = CUser::GetList(($by="sort"), ($order="desc"), array()); $users = []; while ($arUser = $rsUsers->Fetch()) { if(empty($arUser['NAME'])) $arUser['NAME'] = 'EMPTY'; if(empty($arUser['LAST_NAME'])) $arUser['LAST_NAME'] = 'EMPTY'; $users[] = $arUser; } foreach($users as $user) { fputcsv($output, array( $user['ID'], $user['NAME'], $user['LAST_NAME'], $user['LOGIN'], $user['PASSWORD'], $user['EMAIL'], )); } // Закрываем поток fclose($output); // Завершаем выполнение скрипта require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_after.php");
После запуска скрипта будет скачан файл .csv со списком пользователей, мы не будем рассматривать в этой статье ситуацию с большим объемом данных, в таких случаях обмен можно выполнять частями.
Промежуточная таблица
Основная задумка в том, что нам необходимо создать промежуточную таблицу для пользователей перед их загрузкой, а после добавления уже внести данные в эту таблицу, в этом случае мы сможем сравнивать хэш паролей перед авторизацией клиентов и в случае совпадения обновлять незаметно пароль и удалять запись из промежуточной таблицы.
Создаем таблицу (Настройки-> Инструменты -> SQL запрос):
CRE ATE TABLE `old_user` ( `LOGIN` varchar(60) NOT NULL, `HASH` varchar(64) NOT NULL, PRIMARY KEY (`LOGIN`) );
Экспорт пользователей
Перед добавлением пользователей в базу регистрируем обработчик события OnBeforeUserAdd
AddEventHandler("main", "OnBeforeUserAdd", "__beforeUserAdd"); function __beforeUserAdd($arParams) { if (defined("USER_IMPORT_EXECUTION_TIME")) { global $DB; $from_old = "FROM old_user where LOGIN='".$arParams["LOGIN"]."';"; $rsOLDUser = $DB->Query("SELECT * $from_old"); if (!($rsOLDUser->GetNext())) { $DB->Insert("old_user", array( "LOGIN" => "'" . $DB->ForSQL($arParams["LOGIN"]) . "'", "HASH" => "'" . $DB->ForSQL($arParams["PASSWORD"]) . "'" )); } } }
Как только обработчик готов можно запускать импорт пользователей из CSV файла.
Сравниваем хэш паролей перед авторизацией с помощью события OnBeforeUserLogin
Пишем обработчик события OnBeforeUserLogin в котором после ввода пароля мы сравниваем его хэш со старым хэшем из промежуточной таблицы и если они совпали обновляем хэш пароля пользователя, авторизуем его в системе и удаляем из промежуточной таблицы.
AddEventHandler("main", "OnBeforeUserLogin", "__beforeUserLogin"); function __beforeUserLogin($arParams) { global $DB; $login = $DB->ForSQL($arParams["LOGIN"]); $password = $arParams["PASSWORD"]; $from_old = "FROM old_user where LOGIN='$login';"; // Ищем пользователя с таким логином в "old_user" $rsOLDUser = $DB->Query("SELECT * $from_old"); if(!($arOLDUser = $rsOLDUser->GetNext())) return true; // Ищем пользователя с таким логином в базе Битрикса $rsBXUser = CUser::GetByLogin($login); if(!($arBXUser = $rsBXUser->GetNext())) return true; // Проверяем правильность присланного пароля // алгоритмом старой системы if(!password_verify($password, $arOLDUser['HASH'])) return true; // Обновляем пароль пользователя в базе Битрикса $USER = new CUser; $bUbdate = $USER->Update($arBXUser["ID"], array("PASSWORD" => $password)); unset($USER); if(!$bUbdate) return true; // А затем удаляем пользователя из "old_user" $DB->Query("DELETE $from_old"); return true; }
После экспорта пользователей обработчик __beforeUserAdd можно удалить, и периодически проверять промежуточную таблицу, как только она опустее можно удалять. Всем спасибо за внимание, если возникнут сложности или понадобится профессиональная помощь мы всегда на связи.