Как сформировать отчет СКД без проверки прав (в привилегированном режиме)

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

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

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

Почему возникает проблема доступа при обращении к реквизитам через точку?

Проанализируем ситуацию: у пользователя есть полные права на справочник Подразделения, но ограничены права на документы-регистраторы (например, разрешено видеть документы только своего подразделения). В запросе отчета СКД мы обращаемся к полю ПартииТоваровНаСкладах.Регистратор.Подразделение.

Когда СУБД выполняет этот запрос, платформа «1С:Предприятие» делает неявное левое соединение таблицы регистра накопления с таблицами всех возможных документов-регистраторов. Поскольку на эти документы наложены правила RLS, платформа автоматически добавляет в SQL-запрос ограничивающие условия ГДЕ... для каждой таблицы документов. В результате запрос завершается ошибкой или возвращает пустую выборку. Наша задача — заставить платформу выполнить запрос к СУБД в привилегированном контексте, проигнорировав настройки RLS.

Решение 1: Двухэтапная компоновка макета (Рекомендация фирмы 1С)

Фирма «1С» рекомендует разделять процесс формирования отчета СКД на два логических этапа:

  1. Компоновка макета — выполняется в обычном режиме под правами текущего пользователя. Это гарантирует, что в интерфейсе настроек отчета пользователь увидит только те поля, которые ему разрешено видеть согласно его роли.
  2. Выполнение запроса и вывод данных — выполняется в привилегированном режиме. На этом этапе происходит непосредственное обращение к базе данных в обход ограничений RLS.

Для реализации этого подхода откроем модуль объекта нашего отчета и переопределим предопределенную процедуру ПриКомпоновкеРезультата. Рассмотрим пример кода:


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

Разберем важный нюанс: в методе Инициализировать процессора компоновки данных четвертым параметром мы передаем значение Истина (параметр ВозможностьИспользованияВнешнихФункций). Это позволяет использовать экспортные функции общих модулей в выражениях СКД при работе в привилегированном режиме.

Решение 2: Тотальный привилегированный режим

Бывают ситуации, когда пользователю нужно дать возможность строить отчет по полям, к которым у него в конфигураторе вообще не выдано прав (например, служебные справочники или закрытые регистры сведений). Если мы применим первый способ, то на Этапе 1 метод КомпоновщикМакета.Выполнить просто вырежет недоступные поля из настроек компоновщика, и пользователь увидит пустые колонки или «красные кресты» на месте группировок.

В таком случае мы вынуждены выполнять весь цикл компоновки в привилегированном режиме. Посмотрим на реализацию этого метода:


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

Обратите внимание: данный способ требует осторожности. Пользователи смогут увидеть данные объектов базы данных, к которым у них нет прямого доступа согласно политикам безопасности вашей компании.

Решение 3: Использование внешнего набора данных (Набор данных - Объект)

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

Выясним, как это сделать по шагам:

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

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

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

Ограничение для внешних отчетов и механизмов БСП

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

Чтобы обойти это ограничение платформы, у вас есть два пути:

  1. Отключить безопасный режим при регистрации отчета в БСП. В модуле регистрации внешнего отчета в процедуре СведенияОВнешнейОбработке() необходимо явно прописать параметр: ПараметрыРегистрации.Вставить("БезопасныйРежим", Ложь); Обратите внимание, что для загрузки такого отчета в базу данных пользователю потребуются административные права.
  2. Вынести логику получения данных в общий привилегированный модуль. Если политика безопасности вашей компании категорически запрещает запуск внешних отчетов вне безопасного режима, создайте в самой конфигурации общий модуль со свойствами Сервер, Вызов сервера и установленным флагом Привилегированный. Внутри этого модуля напишите экспортную функцию получения таблицы значений. Внешний отчет в безопасном режиме будет вызывать эту серверную функцию конфигурации — этот вызов отработает успешно и в привилегированном контексте.

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

← На главную