Как обновить ключи доступа при программной записи объектов с флагом ОбменДанными.Загрузка = Истина?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей
← На главную

При работе с крупными информационными базами на платформе 1С:Предприятие 8.3, использующими механизм производительного RLS (Record Level Security), разработчики часто сталкиваются с ситуацией, когда программное изменение объектов не приводит к актуализации прав доступа. Особенно остро эта проблема проявляется при использовании режима ОбменДанными.Загрузка = Истина. В данной статье мы подробно разберем, почему это происходит, как работают механизмы БСП (Библиотеки стандартных подсистем) в этом режиме и какими способами можно добиться корректного обновления ключей доступа для объектов и их зависимых сущностей.

Анализ механизма работы производительного RLS и флага Загрузка

Рассмотрим стандартную ситуацию: в конфигурации «Управление торговлей 11» необходимо массово изменить Группу доступа у справочника Партнеры. Для ускорения процесса программист устанавливает флаг ОбменДанными.Загрузка = Истина. Перед началом подобных операций рекомендуется провести просмотр и анализ прав и ролей (поможет отчет для анализа прав доступа и ограничений RLS), чтобы точно понимать текущую структуру ограничений. После выполнения операции обнаруживается, что сам Партнер доступен (или ограничен) согласно новым правилам, а связанные с ним Контактные лица выдают ошибку нарушения прав доступа.

Выясним причину такого поведения. В системе реализованы подписки на события, такие как УправлениеДоступомПередЗаписьюОбъекта и УправлениеДоступомПриЗаписиОбъекта. Проанализируем код этих подписок: практически во всех типовых решениях первой строкой идет проверка: Если Источник.ОбменДанными.Загрузка Тогда Возврат; КонецЕсли;. Это сделано намеренно для обеспечения высокой скорости загрузки данных при обмене, так как расчет ключей доступа — крайне ресурсоемкая операция, требующая анализа множества регистров.

Проблема заключается в том, что в производительном RLS существует понятие ведущего объекта. Например, доступ к Контактному лицу полностью определяется доступом к Партнеру, к которому оно привязано. Когда мы записываем Партнера с флагом Загрузка, система не запускает цепочку обновления прав для зависимых объектов. В итоге в регистре сведений КлючиДоступаКОбъектам для Контактных лиц остаются старые, неактуальные идентификаторы ключей.

Способ 1. Принудительная синхронизация ключей через программный интерфейс

Если нам необходимо обновить ключи «здесь и сейчас» для конкретного объекта, мы можем воспользоваться методами общего модуля ОбщегоНазначенияУТ (или аналогичными в вашей конфигурации). Разберем пример кода, который позволяет инициировать обновление:


ПартнерОбъект = СсылкаНаПартнера.ПолучитьОбъект();
ПартнерОбъект.ГруппаДоступа = НоваяГруппаДоступа;
ПартнерОбъект.ОбменДанными.Загрузка = Истина;

// Подготавливаем данные для синхронизации до записи
ПараметрыСинхронизации = ОбщегоНазначенияУТ.ПараметрыСинхронизацииКлючей();
ОбщегоНазначенияУТ.ПодготовитьДанныеДляСинхронизацииКлючей(ПартнерОбъект, ПараметрыСинхронизации);

ПартнерОбъект.Записать();

// Выполняем синхронизацию после записи
ОбщегоНазначенияУТ.СинхронизироватьКлючи(ПартнерОбъект);

Важный нюанс: этот метод хорошо работает для самого записываемого объекта, но может не затронуть все подчиненные связи, если алгоритм синхронизации в конкретной версии БСП настроен на оптимизацию и игнорирует зависимости при явном вызове для одного объекта.

Способ 2. Использование очереди обновления ключей доступа

Для массовых изменений в базах с миллионами записей (например, номенклатуры или контрагентов) использование прямой записи без флага Загрузка неприемлемо из-за блокировок и низкой скорости. Правильным подходом будет использование регистра сведений «Объекты для обновления ключей доступа». Это специальная очередь, которую обрабатывает регламентное задание Обновление ключей доступа. В сложных случаях, когда автоматика не справляется, может потребоваться точечный пересчет прав доступа для пользователя или для группы пользователя.

Проанализируем алгоритм этого решения:

  1. Записываем основные объекты (например, Партнеров) с установленным ОбменДанными.Загрузка = Истина.
  2. Программно добавляем записи в регистр ОбъектыДляОбновленияКлючейДоступа для каждого измененного объекта.
  3. Если мы знаем, что изменились ведущие объекты, необходимо добавить в очередь и зависимые объекты (всех Контактных лиц этих партнеров).

Пример кода для постановки в очередь:


// Предположим, МассивСсылок содержит ссылки на измененных Партнеров и их Контактных лиц
МенеджерЗаписи = РегистрыСведений.ОбъектыДляОбновленияКлючейДоступа.СоздатьНаборЗаписей();

Для Каждого Ссылка Из МассивСсылок Цикл
    НоваяЗапись = МенеджерЗаписи.Добавить();
    НоваяЗапись.Объект = Ссылка;
КонецЦикла;

МенеджерЗаписи.Записать(Ложь); // Добавляем записи, не затирая существующие в очереди

После этого система в фоновом режиме пересчитает права только для указанных ссылок, не затрагивая остальную базу и не вызывая полного пересчета, как это делает обработка «Обновление вспомогательных данных».

Способ 3. Использование метода УправлениеДоступом.ОбновитьКлючиДоступа()

В современных версиях БСП (начиная с 3.1) предусмотрен универсальный метод в программном интерфейсе модуля УправлениеДоступом. Чтобы лучше ориентироваться в доступном инструментарии, рекомендуем изучить справочник по методам БСП (с примерами использования). Мы можем передать в него массив ссылок, и система сама определит необходимость обновления. Посмотрим на пример:


МассивОбъектов = Новый Массив;
МассивОбъектов.Добавить(СсылкаНаПартнера);
// Обязательно добавляем зависимые объекты, так как при Загрузка=Истина автоопределение связей может быть ограничено
МассивОбъектов.Добавить(СсылкаНаКонтактноеЛицо);

УправлениеДоступом.ОбновитьКлючиДоступа(МассивОбъектов);

Этот метод является наиболее «чистым» с точки зрения архитектуры 1С, так как он использует внутренние механизмы подсистемы управления доступом и гарантирует актуальность данных в регистрах КлючиДоступаКОбъектам и НаборыЗначенийДоступа.

Рекомендации по отладке

Если вышеописанные методы не помогают, проанализируем ситуацию глубже. Рекомендуется установить точку останова в общем модуле УправлениеДоступомСлужебный, в процедуре ОбновитьКлючиДоступаПриЗаписиОбъекта. Также полезно провести быструю проверку прав доступа на объект метаданных и выполнить анализ прав доступа к объекту, чтобы убедиться, что роли настроены корректно. Проверьте следующие моменты:

Резюме: Режим ОбменДанными.Загрузка = Истина отключает автоматическое обновление прав для обеспечения производительности. При его использовании обязанность по актуализации ключей доступа перекладывается на разработчика. Использование очереди обновления через регистр ОбъектыДляОбновленияКлючейДоступа является самым безопасным и эффективным методом для высоконагруженных систем.

← На главную