Как передать список значений в параметр сеанса для настройки RLS в 1С?

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

При настройке ограничений прав доступа на уровне записей (RLS) разработчики регулярно сталкиваются с задачей ограничить чтение или изменение данных списком разрешенных объектов, например филиалов или складов. В шаблоне ограничения обычно используется конструкция с проверкой вхождения ссылки во входной параметр. Однако при попытке настроить такой отбор через параметры сеанса возникает сложность: платформа 1С не поддерживает тип СписокЗначений для параметров сеанса. Разберем, как правильно реализовать такое ограничение, какой тип данных применить и как корректно заполнить параметр в коде.

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

ГДЕ Ссылка В (&СписокФилиалов)

Выясним причину возникающих затруднений и пошагово реализуем рабочее решение.

Почему нельзя использовать СписокЗначений и что выбрать взамен

В дереве метаданных у объекта ПараметрСеанса отсутствует возможность выбрать тип СписокЗначений, поскольку параметры сеанса должны хранить строго сериализуемые типы, обеспечивающие быстрое взаимодействие между клиентом, сервером и СУБД. Если для единичного значения подходит ссылка на справочник, то для набора элементов платформа предоставляет специальный тип — ФиксированныйМассив.

Главная особенность объекта ФиксированныйМассив заключается в том, что он является неизменяемым. У него нет методов Добавить(), Удалить() или Очистить(). Поэтому инициализация значения выполняется через промежуточный объект Массив.

Реализация через ФиксированныйМассив: пошаговый алгоритм

Разберем по шагам, как настроить конфигурацию и написать программный код для заполнения параметра сеанса.

  1. Создание параметра сеанса в метаданных: Добавим новый параметр сеанса с именем СписокФилиалов. В качестве типа данных укажем ФиксированныйМассив.
  2. Подготовка списка разрешенных элементов: Поскольку напрямую добавить элементы в фиксированный массив нельзя, сначала создадим стандартный объект Массив и заполним его ссылками на филиалы.
  3. Передача массива в параметр сеанса: Создадим экземпляр типа ФиксированныйМассив, передав в его конструктор подготовленный обычный массив, и присвоим результат параметру сеанса.

Посмотрим на пример заполнения параметра сеанса в процедуре УстановкаПараметровСеанса модуля сеанса (МодульСеанса):


Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
    
    // Проверяем инициализацию параметра "по требованию"
    Если ТребуемыеПараметры = Неопределено 
        Или ТребуемыеПараметры.Найти("СписокФилиалов") <> Неопределено Тогда
        
        УстановитьПривилегированныйРежим(Истина);
        
        ОбычныйМассив = Новый Массив;
        
        // Заполняем массив разрешенными ссылками (например, выборкой из регистра или реквизита)
        // Для примера добавим доступные филиалы методом Добавить()
        ОбычныйМассив.Добавить(Справочники.Филиалы.НайтиПоНаименованию("Северный"));
        ОбычныйМассив.Добавить(Справочники.Филиалы.НайтиПоНаименованию("Южный"));
        
        // Преобразуем обычный массив в ФиксированныйМассив и записываем в параметр
        ПараметрыСеанса.СписокФилиалов = Новый ФиксированныйМассив(ОбычныйМассив);
        
    КонецЕсли;

КонецПроцедуры

Обратим внимание на вызов УстановитьПривилегированныйРежим(Истина). При получении прав пользователя из базы данных рекомендуется включать привилегированный режим, чтобы правила RLS не блокировали служебные запросы самой системы во время старта или при первом обращении к параметру.

Ограничения использования конструкции «В (&Список)» и альтернативные подходы

Хотя вариант с фиксированным массивом полностью решает задачу автора, рассмотрим подробнее архитектурные особенности этого подхода при промышленной эксплуатации базы данных.

1. Нагрузка на СУБД:
Когда условие RLS содержит конструкцию Ссылка В (&СписокФилиалов), платформа транслирует массив в SQL-запрос как список перечисления значений в блоке IN (...). Если филиалов или складов у пользователя десятки, это работает штатно. Однако если список разрастается до сотен или тысяч записей, размер SQL-запроса существенно увеличивается, а СУБД перестает эффективно кэшировать планы выполнения запросов. Это приводит к замедлению открытия динамических списков и построения отчетов.

2. Кэширование значения в сеансе:
Параметр сеанса кэшируется на все время работы пользователя. Если администратор добавит сотруднику доступ к новому филиалу, изменения не вступят в силу, пока пользователь не перезапустит программу или пока параметр не будет пересчитан принудительно через программный код.

Альтернативное решение: связь через регистр сведений

Для высоконагруженных систем или списков с динамически меняющимися правами разберем более производительное решение без использования массива филиалов в параметрах сеанса.

Создадим непериодический регистр сведений, например НастройкиПравПоФилиалам, с измерениями Пользователь и Филиал. В этом случае в параметрах сеанса достаточно хранить только ссылку на текущего пользователя (&ТекущийПользователь), а условие RLS в роли переписать через подзапрос:


ГДЕ Ссылка В 
    (ВЫБРАТЬ 
        РС.Филиал 
    ИЗ 
        РегистрСведений.НастройкиПравПоФилиалам КАК РС 
    ГДЕ 
        РС.Пользователь = &ТекущийПользователь)

Такой подход обеспечивает два важных преимущества: во-первых, СУБД выполняет оптимизированное внутреннее соединение таблиц на уровне сервера баз данных; во-вторых, изменение прав пользователя в регистре сведений начинает действовать мгновенно без перезапуска клиентского приложения 1С.

← На главную