При переносе данных между информационными базами или при написании собственных обработок мы часто сталкиваемся с нестандартными ситуациями. Проанализируем одну из таких проблем: у нас есть элементы в Справочник.Пользователи и есть соответствующие им пользователи информационной базы, которых мы можем получить через ПользователиИнформационнойБазы.ПолучитьПользователей(). Однако связи между ними нет — реквизит ИдентификаторПользователяИБ в элементе справочника пуст.
Давайте разберем, почему возникает сложность при попытке установить эту связь. Если мы попытаемся явно изменить реквизит ИдентификаторПользователяИБ и записать элемент, Библиотека стандартных подсистем (БСП) перехватит это действие в подписках на события (например, в процедуре ПользователиСлужебный.НачатьОбработкуПользователяИБ). В результате значение реквизита вернется к исходному (пустому) состоянию до записи. Выясним причину: БСП строго контролирует синхронизацию пользователей справочника и пользователей ИБ, чтобы исключить рассогласование прав, ролей и настроек.
Рассмотрим метод, к которому разработчики часто прибегают в первую очередь. Это использование свойства ОбменДанными.Загрузка = Истина.
При установке этого флага платформа и большинство обработчиков БСП понимают, что идет системная загрузка данных, и пропускают проверки и синхронизацию. Связь действительно установится, однако проанализируем последствия: это считается грубым «хаком». При таком подходе не отработают важные служебные процедуры, которые отвечают за обновление настроек, профилей групп доступа и ролей. Использовать этот способ стоит только в крайних случаях, если вы точно понимаете, что делаете.
Посмотрим на альтернативный подход. В форме элемента справочника «Пользователи» есть поле «Имя входа». Если туда прописать имя существующего пользователя информационной базы и нажать «Записать», БСП сама всё найдет и свяжет. Мы можем попытаться программно воспроизвести логику, которая происходит в обработчике ПриИзменении этого поля на форме, однако это потребует разбора сложного кода БСП и может зависеть от конкретной версии библиотеки.
Разберем по шагам правильное программное решение, которое работает в рамках логики БСП, не ломая синхронизацию. Для взаимодействия с пользователями ИБ через справочник БСП предоставляет функцию Пользователи.НовоеОписаниеПользователяИБ(). Она возвращает структуру с описанием свойств. Секрет кроется в том, что по умолчанию эта структура не содержит ключа для уникального идентификатора существующего пользователя, но мы можем добавить его туда вручную.
Сформируем корректный алгоритм действий:
Пользователи.НовоеОписаниеПользователяИБ().УникальныйИдентификатор найденного пользователя ИБ.Действие со значением "Записать", чтобы БСП поняла наше намерение.ДополнительныеСвойства нашего объекта справочника. Ключ обязательно должен называться "ОписаниеПользователяИБ".Записать() объекта справочника.При такой последовательности действий платформенные обработчики БСП сами перехватят структуру из дополнительных свойств объекта. Они увидят переданный УникальныйИдентификатор, корректно свяжут учетные данные и автоматически (и безопасно) пропишут защищенный реквизит ИдентификаторПользователяИБ.
Рассмотрим пример кода, который объединяет все описанные выше шаги. В этом примере мы считаем, что переменная ИмяДляВхода содержит строку с именем пользователя ИБ, а СсылкаНаСправочник — это пустая или несвязанная ссылка на элемент справочника пользователей.
// 1. Находим существующего пользователя ИБ по имени
ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяДляВхода);
Если ПользовательИБ <> Неопределено Тогда
// 2. Получаем объект справочника
ПользовательОбъект = СсылкаНаСправочник.ПолучитьОбъект();
// 3. Получаем структуру описания из БСП
ОбновляемыеСвойства = Пользователи.НовоеОписаниеПользователяИБ();
ОбновляемыеСвойства.Вставить("Имя", ПользовательИБ.Имя);
// 4. Добавляем недостающие свойства в структуру программно
ОбновляемыеСвойства.Вставить("УникальныйИдентификатор", ПользовательИБ.УникальныйИдентификатор);
ОбновляемыеСвойства.Вставить("Действие", "Записать");
// 5. Передаем структуру в дополнительные свойства объекта
ПользовательОбъект.ДополнительныеСвойства.Вставить("ОписаниеПользователяИБ", ОбновляемыеСвойства);
// 6. Записываем объект штатным методом
ПользовательОбъект.Записать();
КонецЕсли;
Используя этот метод, вы сохраняете целостность системы. БСП отработает штатно, назначит нужные права доступа, обновит профили и свяжет записи без использования грубой загрузки данных. Это гарантирует отсутствие "плавающих" ошибок с доступом у пользователей в будущем.