Почему возникает ошибка прав доступа при формировании отчета СКД и как ее правильно решить?

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

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

В чем суть проблемы: «Чтение» против «Просмотра»

Для того чтобы понять природу этой ошибки, давайте разберем фундаментальное различие между двумя правами доступа в системе прав «1С»:

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

Коварство составных типов данных (поле «Регистратор»)

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

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

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

Способ решения №1: Ограничение типа с помощью оператора ВЫРАЗИТЬ

Если нам не хочется давать пользователю право на «Просмотр» всех типов документов в системе, мы можем оптимизировать сам текст запроса в схеме компоновки данных. Для этого мы явным образом укажем платформе, типы каких именно документов мы ожидаем получить из поля Регистратор. Делается это с помощью конструкции ВЫРАЗИТЬ.

Рассмотрим пример. Вместо прямого обращения к реквизитам регистратора:


ВЫБРАТЬ
    ТоварыНаСкладах.Период КАК Период,
    ТоварыНаСкладах.Регистратор.Номер КАК НомерДокумента,
    ТоварыНаСкладах.Регистратор.Дата КАК ДатаДокумента
ИЗ
    РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах

Мы применим явное приведение типов в запросе СКД:


ВЫБРАТЬ
    ТоварыНаСкладах.Period КАК Период,
    ВЫРАЗИТЬ(ТоварыНаСкладах.Регистратор КАК Документ.ПоступлениеТоваровУслуг).Номер КАК НомерПоступления,
    ВЫРАЗИТЬ(ТоварыНаСкладах.Регистратор КАК Документ.ПоступлениеТоваровУслуг).Дата КАК ДатаПоступления
ИЗ
    РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах
ГДЕ
    ТоварыНаСкладах.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг

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

Способ решения №2: Разделение компоновки и вывода (Привилегированный режим)

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

Однако здесь кроется важная архитектурная деталь. Если мы просто включим привилегированный режим перед формированием отчета, то пользователь в форме настроек отчета увидит абсолютно все доступные поля конфигурации, включая те, которые ему видеть не положено по соображениям безопасности. Фирма «1С» рекомендует использовать методику разделения компоновки макета и его исполнения.

Давайте разберем этот алгоритм по шагам:

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

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


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

Благодаря такому разделению мы строго соблюдаем требования безопасности (пользователь не увидит недоступные структуры данных в настройках компоновщика), но при этом отчет сформируется корректно, поскольку сам запрос выполнится на уровне СУБД без ограничений.

Важные нюансы для внешних отчетов

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

В безопасном режиме вызов метода УстановитьПривилегированныйРежим(Истина) будет проигнорирован платформой. Чтобы код привилегированного режима отработал, при регистрации внешнего отчета в справочнике дополнительных обработок необходимо настроить режим совместимости и явным образом установить параметр БезопасныйРежим = Ложь (или запросить разрешение на использование привилегированного режима у администратора системы).

Почему ключевое слово РАЗРЕШЕННЫЕ не помогает?

Часто разработчики пытаются решить проблемы с правами добавлением ключевого слова РАЗРЕШЕННЫЕ в начало запроса СКД. Например:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ТоварыНаСкладах.Регистратор
ИЗ
    РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах

Важно четко понимать разницу в механизмах работы платформы:

Резюме

Мы выяснили, что СКД жестко требует интерактивного права «Просмотр» на все выводимые объекты из-за своей интерактивной природы. Для успешного обхода этого ограничения без предоставления пользователям лишних прав в интерфейсе используйте:

  1. Оператор ВЫРАЗИТЬ в запросах СКД для сужения состава типов у реквизитов с составным типом данных (таких как Регистратор).
  2. Разделение формирования отчета на этап компоновки (в обычном режиме) и этап вывода (в привилегированном режиме) в процедуре ПриКомпоновкеРезультата модуля объекта отчета.
← На главную