Почему встроенный отчет СКД выводит пустой результат под ограниченными правами, даже если включен привилегированный режим?

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

Разработчики прикладных решений на платформе «1С:Предприятие 8» часто сталкиваются с ситуацией: в конфигурацию добавляется новый отчет на базе Системы компоновки данных (СКД). Для корректного обхода ограничений прав доступа (например, RLS или отсутствия у пользователя прямых прав на чтение некоторых таблиц) разработчик программно включает привилегированный режим непосредственно перед выводом отчета. Под полными правами все работает безукоризненно, но стоит запустить отчет под пользователем с ограниченными правами — и перед нами оказывается пустая таблица.

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

Анализ исходного программного кода формирования отчета

Рассмотрим стандартный подход к перехвату формирования отчета. В модуле объекта отчета переопределяется обработчик события ПриКомпоновкеРезультата:


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

Сама процедура генерации макета и вывода данных вынесена в общий модуль с включенным признаком Привилегированный:


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

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

Причина 1. Поведение Компоновщика настроек на клиенте

Главная архитектурная особенность СКД заключается в том, что объект КомпоновщикНастроек инициализируется на клиенте (или в контексте обычного сеанса пользователя) и тесно связан с его правами доступа.

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

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

Причина 2. Ограничения Безопасного режима в вычисляемых полях

Выясним еще одну важную деталь, упомянутую в ходе обсуждения. Платформа «1С:Предприятие» принудительно переключает исполнение кода в Безопасный режим, если в схеме компоновки данных используются вычисляемые поля или выражения ресурсов, вызывающие функции общих модулей.

В безопасном режиме действие любого привилегированного режима полностью блокируется платформой. Команда УстановитьПривилегированныйРежим(Истина) внутри безопасного контекста игнорируется, и система начинает проверять реальные права пользователя на уровне СУБД (включая RLS), что приводит к пустому результату или ошибкам доступа.

Причина 3. Неактуальность вспомогательных данных БСП (Кэш метаданных)

Это наиболее распространенная организационно-техническая проблема при разработке в базах на основе Библиотеки стандартных подсистем (БСП). Именно она стала причиной «пустого отчета» у автора темы.

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

Как запустить обновление вспомогательных данных принудительно:

  1. Параметр запуска конфигурации: Запустите сеанс «1С:Предприятие» в режиме отладки с ключом командной строки: /C ЗапуститьОбновлениеИнформационнойБазы.
  2. Программный вызов обновления: Выполните в консоли кода (или в режиме отладки) следующую инструкцию:
    
    Справочники.ИдентификаторыОбъектовМетаданных.ОбновитьДанныеСправочника(Истина, Ложь);
    
  3. Использование внешней обработки: Примените обработку ОбновлениеВспомогательныхДанных.epf из состава дистрибутива БСП, чтобы точечно обновить только измененные отчеты.

Альтернативное решение: Переход на Набор данных - Объект

Если специфика бизнес-логики требует, чтобы у пользователя вообще не было прав «Просмотр» на прикладные таблицы, стандартная схема СКД с набором данных типа «Запрос» работать не сможет из-за ограничений КомпоновщикаНастроек.

В этом случае рекомендуется использовать следующую архитектурную схему:

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

Посмотрим на пример реализации заполнения внешнего набора данных:


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

Резюме

Если ваш встроенный отчет возвращает пустой результат под ограниченными правами, действуйте по следующему чек-листу:

  1. Выполните полное обновление вспомогательных данных ИБ (актуализируйте справочник идентификаторов объектов метаданных БСП).
  2. Проверьте наличие прав «Просмотр» у пользователя на все объекты метаданных, фигурирующие в запросе СКД, чтобы избежать усечения настроек в КомпоновщикеНастроек.
  3. Убедитесь, что в вычисляемых полях не вызываются функции, принудительно переводящие работу СКД в безопасный режим, блокирующий привилегированный контекст.
  4. При невозможности предоставления прав на таблицы базы данных используйте Набор данных - Объект с предварительной подготовкой таблиц значений в привилегированных модулях.
← На главную