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