Как вывести в отчет СКД данные, ограниченные правами РЛС (RLS)?

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

Часто при разработке отчетов в 1С возникает сложная задача: как показать пользователю полные оборотные данные или движения, если часть измерений (например, подразделение, склад или организация) скрыта от него настройками прав на уровне записей (RLS). Проанализируем типичную ситуацию: есть отчет по пробегу и перемещению транспортных средств. Транспорт перемещается из Подразделения А в Подразделение Б. Если диспетчер видит по РЛС только Подразделение А, то при формировании отчета за период он либо не увидит перемещение вовсе, либо получит некорректные данные. Давайте разберем по шагам, как правильно "подружить" систему компоновки данных (СКД) и RLS.

Почему стандартный запрос и привилегированный режим не спасают?

Первое, что приходит на ум разработчику — выполнить формирование отчета в привилегированном режиме, используя УстановитьПривилегированныйРежим(Истина). Но посмотрим на пример из практики: этот метод "в лоб" не сработает. Для корректного решения этой задачи можно применить готовый инструмент для запуска отчетов СКД в привилегированном режиме.

Выясним причину:

  1. Ограничения Компоновщика настроек. При инициализации настроек СКД платформа анализирует права текущего пользователя. Если у пользователя нет права "Просмотр" на конкретный справочник (например, на чужое Подразделение), СКД просто вырежет это поле из доступных и выбранных полей. Данные физически не попадут в результат.
  2. Безопасный режим СКД. Во время вычисления выражений системы компоновки данных (в вычисляемых полях или параметрах) происходит автоматический переход в безопасный режим платформы. В нем привилегированный режим отключается. Любое обращение к чужому подразделению через точку (например, ПодразделениеПолучатель.Наименование) выдаст ошибку или пустоту.
  3. Коварство конструкции РАЗРЕШЕННЫЕ. Если в исходный запрос СКД добавить ВЫБРАТЬ РАЗРЕШЕННЫЕ, это предотвратит ошибку прав доступа, но платформа просто "молча" отфильтрует строки, где есть закрытые по РЛС ссылки. Данные о перемещении ТС исчезнут из отчета полностью.

Решение 1: Использование внешнего набора данных (Таблица Значений)

Рассмотрим подробнее самый надежный способ обхода ограничений платформы. Нам необходимо подготовить данные программно в привилегированном серверном контексте и передать их в СКД как таблицу значений.

Проанализируем алгоритм действий:

  1. В схеме компоновки данных (макете) меняем тип набора данных на Объект.
  2. В наборе данных СКД поля, которые ограничиваются по РЛС, делаем строковыми, а не ссылочными. Если оставить тип "СправочникСсылка", СКД снова попытается применить права и удалит поле.
  3. В серверном коде (например, в модуле объекта отчета) включаем УстановитьПривилегированныйРежим(Истина).
  4. Выполняем запрос к базе данных без конструкции РАЗРЕШЕННЫЕ. В самом запросе заменяем ссылочные закрытые поля на их строковое представление с помощью функции запроса ПРЕДСТАВЛЕНИЕ().
  5. Выгружаем результат в Таблицу Значений и передаем ее в процессор компоновки.

Посмотрим на пример программного вывода отчета из Таблицы Значений:


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

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

Решение 2: Архитектурный подход (Денормализация данных)

Если разработка отчета через внешний набор данных с Таблицей Значений кажется избыточной или отчет должен строиться пользователями динамически, рассмотрим архитектурное решение. Часто попытки обойти РЛС в отчете говорят о недостатках проектирования регистров.

Если диспетчерам или логистам критически важно видеть оборот транспорта по всем подразделениям (несмотря на то, что в самом справочнике Подразделений они видят только свое), правильным подходом будет создание отдельного денормализованного регистра.

Например, создается оборотный регистр накопления ПеремещенияТранспортаДляОтчетов. На этот регистр назначаются права на чтение без жестких ограничений RLS (либо создается отдельная роль специально для работы с этим отчетом). Документ перемещения при проведении пишет данные в этот регистр. Отчет на СКД строится по данному регистру абсолютно стандартным образом. Это избавляет систему от сложных программных костылей при компоновке результата и ускоряет работу отчета.

← На главную