Как вывести данные в СКД, если у пользователя нет прав на просмотр объекта?

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

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

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

В чем разница между правами «Чтение» и «Просмотр»?

Для начала выясним причину такого поведения платформы. В роли пользователя для каждого объекта метаданных настраиваются два связанных, но принципиально разных права:

  1. «Чтение» (Read) — управляет доступом к данным на уровне СУБД. Если право предоставлено, платформа разрешает выполнять запросы к физическим таблицам базы данных.
  2. «Просмотр» (View) — управляет интерактивным отображением данных. Без этого права пользователь не может увидеть объект в интерфейсе: открыть форму списка, форму элемента, выбрать элемент в поле ввода.

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

Почему не работает стандартный «ПривилегированныйРежим»?

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

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

Ниже рассмотрим три надежных способа решения этой проблемы.

---

Решение 1: Программное отключение проверки прав доступа в компоновщике макета

Этот способ является наиболее элегантным, так как позволяет использовать стандартную схему компоновки (запрос к базе данных), но принудительно отключает валидацию прав интерактивного просмотра при генерации макета.

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

Рассмотрим пример кода:


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

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

Важный нюанс: Этот вариант сработает в том случае, если пользователь не успел сбросить или перенастроить структуру полей вручную через форму настроек, где эти поля всё равно будут скрыты для интерактивного выбора.

---

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

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

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

Выясним, как настроить данный механизм по шагам:

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

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

&НаСервереБезКонтекста
Функция ПолучитьДанныеВПривилегированномРежиме()
    
    УстановитьПривилегированныйРежим(Истина);
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	СпецификацииНоменклатуры.Номенклатура КАК Номенклатура,
        |	СпецификацииНоменклатуры.Количество КАК Количество
        |ИЗ
        |	Справочник.СпецификацииНоменклатуры КАК СпецификацииНоменклатуры";
        
    Возврат Запрос.Выполнить().Выгрузить();
    
КонецФункции

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

---

Решение 3: Интерфейсный обход (Ограничение на уровне форм объектов)

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

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

Для реализации этого метода откроем модуль формы списка и модуль формы элемента нужного справочника (в нашем примере — Спецификации) и пропишем проверку роли в событии создания формы:


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

Преимущества решения: Отчеты работают «из коробки» стандартными средствами платформы без дополнительного программирования СКД.

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

---

Резюме и рекомендации

Мы проанализировали три метода обхода ограничений прав в СКД. Выбор конкретного пути зависит от архитектуры вашей конфигурации:

← На главную