При разработке отчетов на СКД часто возникает задача показать пользователю данные, к которым у него нет прав доступа (например, ограничение на уровне RLS). Попытка просто вызвать УстановитьПривилегированныйРежим(Истина) внутри метода ПриКомпоновкеРезультата часто приводит к тому, что отчет выводится пустым. Давайте разберемся, почему это происходит и как решить задачу архитектурно правильно.
Основная причина заключается в том, что ПриКомпоновкеРезультата выполняется в контексте, где система уже инициализировала механизм компоновки данных. Если права пользователя ограничены, то на этапе компиляции запроса СКД платформа автоматически применяет ограничения доступа к таблицам базы данных. Установка привилегированного режима внутри этого метода не отменяет уже наложенные ограничения, так как план выполнения запроса был сформирован до того, как вы сменили режим доступа.
Самый надежный способ обойти ограничения прав — это не позволять СКД обращаться к «закрытым» объектам напрямую. Мы можем подготовить данные заранее, используя привилегированный контекст. Для этого выполним следующие шаги:
Привилегированный.ТаблицаЗначений.Пример реализации функции в модуле:
Функция ПолучитьДанныеДляОтчета(ПараметрыОтчета) Экспорт
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ * ИЗ Документ.ВашДокумент КАК Док";
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Теперь в событии ПриКомпоновкеРезультата вы вызываете эту функцию, получаете таблицу и передаете её в качестве внешнего набора данных. Это позволяет «подсунуть» СКД готовые данные, не заставляя её самостоятельно обращаться к таблицам, на которые у пользователя нет прав.
Этот метод является наиболее правильным с архитектурной точки зрения. Вы не «обманываете» систему, а используете стандартный механизм работы с внешними данными.
Наборы данных новый элемент: Набор данных - объект.ДанныеОтчета.ПриКомпоновкеРезультата, установите этот набор данных:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Получаем данные в привилегированном режиме
Данные = МойПривилегированныйМодуль.ПолучитьДанныеДляОтчета(Параметры);
// Передаем данные в СКД
ВнешниеНаборы = Новый Структура("ДанныеОтчета", Данные);
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.ПолучитьНастройки(), ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(Макет, ВнешниеНаборы, ДанныеРасшифровки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Несмотря на то что использование привилегированного режима решает задачу отображения данных, мы рекомендуем также рассмотреть настройку RLS (ограничение доступа на уровне записей). Использование привилегированного режима — это потенциальная «дыра» в безопасности, так как он предоставляет полные права на весь код, выполняемый внутри блока. Использование шаблонов ограничений RLS позволяет системе автоматически фильтровать данные, отображая пользователю только то, что ему разрешено, без необходимости переводить исполнение кода в привилегированный режим.
Важное примечание: Всегда старайтесь минимизировать объем кода, исполняемого в привилегированном режиме. Если проблему можно решить через стандартные настройки доступа, используйте их — это сделает систему более предсказуемой и безопасной.