При работе с распределенными информационными базами (РИБ) администраторы и программисты часто сталкиваются с ситуацией, когда один и тот же сотрудник не может войти в периферийную базу, хотя в центральной базе всё настроено корректно. Одной из самых коварных причин является разрыв связи между пользователем информационной базы (платформенным) и элементом справочника Пользователи. Проблема заключается в несовпадении их уникальных идентификаторов (UUID).
В этой статье мы подробно разберем, почему возникает такая проблема, можно ли изменить UUID пользователя платформы и как программно восстановить синхронизацию данных в узлах РИБ.
В системе 1С:Предприятие 8 существует два уровня сущностей для работы с пользователями:
ИдентификаторПользователяИБ.Когда вы создаете пользователя вручную через Конфигуратор в каждой базе отдельно, платформа генерирует для них разные уникальные идентификаторы. Даже если имя (логин) одинаковое, внутренний UUID будет отличаться. При обмене данными справочник Пользователи мигрирует из центра в дочернюю базу, принося с собой UUID из центра. В итоге в периферийной базе справочник ссылается на идентификатор, которого не существует в локальном списке пользователей платформы, и авторизация под прикладным профилем не срабатывает.
Рассмотрим возможности встроенного языка. Проанализировав объект ПользовательИнформационнойБазы, мы увидим свойство УникальныйИдентификатор. Однако, согласно синтаксис-помощнику, оно доступно только для чтения.
Важный вывод: Платформа 1С не позволяет вручную устанавливать или изменять UUID пользователя информационной базы. Он генерируется автоматически один раз при создании записи. Сделать идентификаторы идентичными во всех базах РИБ путем простого присвоения значения невозможно.
Если мы не можем изменить UUID платформы, значит, нам нужно научить систему обновлять UUID в справочнике Пользователи при первом входе человека в базу. Разберем алгоритм, который позволяет автоматически «подтягивать» актуальный идентификатор, если поиск по точному соответствию не дал результатов.
Для реализации этого механизма необходимо модифицировать процедуру поиска пользователя (обычно она находится в модуле Пользователи или ПользователиСлужебный в конфигурациях на базе БСП). Проанализируем пример кода, который решает эту задачу:
Функция ПользовательПоИдентификаторуСуществует(УникальныйИдентификатор,
СсылкаНаТекущего = Неопределено,
НайденныйПользователь = Неопределено) Экспорт
УстановитьПривилегированныйРежим(Истина);
// Сначала пытаемся найти пользователя в справочнике по UUID
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("СсылкаНаТекущего", СсылкаНаТекущего);
Запрос.УстановитьПараметр("УникальныйИдентификатор", УникальныйИдентификатор);
Запрос.Текст =
"ВЫБРАТЬ
| Пользователи.Ссылка КАК Пользователь
|ИЗ
| Справочник.Пользователи КАК Пользователи
|ГДЕ
| Пользователи.ИдентификаторПользователяИБ = &УникальныйИдентификатор
| И Пользователи.Ссылка <> &СсылкаНаТекущего";
Результат = Ложь;
НайденныйПользователь = Неопределено;
НачатьТранзакцию();
Попытка
РезультатЗапроса = Запрос.Выполнить();
// Если по UUID не нашли, применяем альтернативный поиск по Имени (Коду)
Если РезультатЗапроса.Пустой() Тогда
// Ищем пользователя платформы по переданному идентификатору
НайденПользовательИБ = ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(УникальныйИдентификатор);
Если НайденПользовательИБ <> Неопределено Тогда
// Пытаемся найти элемент в справочнике, где Код (или Имя) совпадает с логином пользователя ИБ
ЗапросАльтернативный = Новый Запрос;
ЗапросАльтернативный.Текст =
"ВЫБРАТЬ
| Пользователи.Ссылка КАК Пользователь
|ИЗ
| Справочник.Пользователи КАК Пользователи
|ГДЕ
| Пользователи.Ссылка <> &СсылкаНаТекущего
| И Пользователи.Код = &Код"; // Предполагаем, что Код справочника = логин
ЗапросАльтернативный.УстановитьПараметр("Код", НайденПользовательИБ.Имя);
ЗапросАльтернативный.УстановитьПараметр("СсылкаНаТекущего", СсылкаНаТекущего);
РезультатЗапроса2 = ЗапросАльтернативный.Выполнить();
Если НЕ РезультатЗапроса2.Пустой() Тогда
Выборка = РезультатЗапроса2.Выбрать();
Выборка.Следующий();
НайденныйПользователь = Выборка.Пользователь;
// Ключевой момент: перезаписываем идентификатор в справочнике актуальным значением из текущей базы
ТекОбъектПользователь = НайденныйПользователь.ПолучитьОбъект();
ТекОбъектПользователь.ИдентификаторПользователяИБ = УникальныйИдентификатор;
ТекОбъектПользователь.Записать();
Результат = Истина;
КонецЕсли;
КонецЕсли;
КонецЕсли;
// Обработка стандартного случая (если нашли сразу по UUID)
Если НЕ РезультатЗапроса.Пустой() И Результат = Ложь Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
НайденныйПользователь = Выборка.Пользователь;
Результат = Истина;
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
Возврат Результат;
КонецФункции
Рассмотрим подробнее, что происходит внутри этой функции:
Пользователи, пытаясь найти запись, у которой реквизит ИдентификаторПользователяИБ совпадает с тем, под которым вошел пользователь. В РИБ этот поиск часто выдает пустое значение, так как идентификатор пришел из другой базы.ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору() мы получаем объект текущего пользователя, который авторизовался в системе.Имя полученного объекта. Это и есть логин (например, "ИвановИИ"). Мы ищем в справочнике Пользователи элемент, у которого поле Код или Наименование совпадает с этим логином.ИдентификаторПользователяИБ, записывая туда текущий UUID из этой базы.UUID уже пройдет успешно.Посмотрим на ситуацию шире. Чтобы не прибегать к правке типовых модулей, можно рассмотреть следующие варианты:
1. Использование типовой обработки «Перенос пользователей»
На портале ИТС доступна специальная обработка, которая позволяет выгружать данные пользователей платформы. Однако стоит помнить, что даже она при загрузке в новую базу создаст новые записи с новыми идентификаторами. Она полезна скорее для массового создания пользователей, чем для решения проблемы UUID в РИБ.
2. Администрирование через справочник в Центральной Базе
Правильный подход при работе с современными конфигурациями (БСП 3.х) заключается в том, чтобы никогда не создавать пользователей через Конфигуратор в дочерних базах.
Выясним правильный порядок действий:
3. Исключение реквизита из обмена
Иногда практикуется настройка правил обмена (в КД 2.0 или КД 3.0), при которой реквизит ИдентификаторПользователяИБ не замещается при загрузке в периферийную базу, если он уже заполнен. Это позволяет сохранить локальную «привязку» пользователя к платформенному UUID, несмотря на обновления других данных (ФИО, телефон и т.д.) из центра.
Таким образом, мы выяснили, что прямой возможности изменить уникальный идентификатор пользователя 1С не существует. Однако, используя программное сопоставление по имени пользователя и актуализацию реквизитов справочника, можно добиться бесшовной работы сотрудников во всех узлах распределенной системы.