Перенос пользователей Битрикс (Импорт/Экспорт)

  • Блог
  • Перенос пользователей Битрикс (Импорт/Экспорт)
image
image
image
Перенос пользователей Битрикс (Импорт/Экспорт)

Очень частой задачей является перенести пользователей со старой системы 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 можно удалить, и периодически проверять промежуточную таблицу, как только она опустее можно удалять. Всем спасибо за внимание, если возникнут сложности или понадобится профессиональная помощь мы всегда на связи.

Заказать звонок