При настройке прав доступа в системе 1С:Предприятие разработчики часто сталкиваются с дилеммой: пользователю необходимо показать отчет, содержащий служебные данные (например, количества или спецификации номенклатуры), но при этом нельзя давать ему возможность интерактивно открывать эти объекты, просматривать их списки или редактировать формы.
В этой статье мы подробно разберем, почему стандартный механизм Системы компоновки данных (СКД) скрывает такие поля, почему обычная установка привилегированного режима не помогает решить проблему «в лоб», и проанализируем три практических способа обхода этого ограничения с примерами кода.
Для начала выясним причину такого поведения платформы. В роли пользователя для каждого объекта метаданных настраиваются два связанных, но принципиально разных права:
Поскольку СКД спроектирована как инструмент формирования отчетов непосредственно для пользователя, она жестко контролирует право «Просмотр». Если у пользователя есть право на чтение справочника, но отсутствует право на его просмотр, СКД принудительно «вырезает» эти поля из доступных. Они исчезают из выбранных полей, группировок и отборов, в результате чего отчет формируется неполным или пустым.
Попытка просто вызвать команду УстановитьПривилегированныйРежим(Истина) в модуле отчета перед формированием не приносит результата. Давайте разберем по шагам, почему это происходит:
КомпоновщикНастроек.ПриКомпоновкеРезультата передаются уже очищенные настройки, в которых нужных полей попросту нет. Включение привилегированного режима на этом этапе не может вернуть то, что уже было удалено платформой.Ниже рассмотрим три надежных способа решения этой проблемы.
---
Этот способ является наиболее элегантным, так как позволяет использовать стандартную схему компоновки (запрос к базе данных), но принудительно отключает валидацию прав интерактивного просмотра при генерации макета.
Для реализации этого метода нам потребуется переопределить стандартную обработку вывода отчета в модуле объекта отчета. Мы перехватываем компоновку в событии ПриКомпоновкеРезультата и передаем специальный параметр в компоновщик макета.
Рассмотрим пример кода:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Отменяем стандартный вывод отчета платформой
СтандартнаяОбработка = Ложь;
// Получаем текущие настройки (они могут быть дефолтными или измененными пользователем)
НастройкиОтчета = КомпоновщикНастроек.ПолучитьНастройки();
// Инициализируем компоновщик макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
// Ключевой обход: Шестой параметр метода Выполнить() называется "ПроверятьДоступностьПолей".
// Передавая в него значение ЛОЖЬ, мы заставляем СКД игнорировать отсутствие права "Просмотр".
МакетКомпоновки = КомпоновщикМакета.Выполнить(
СхемаКомпоновкиДанных,
НастройкиОтчета,
ДанныеРасшифровки,
,
,
Ложь // ПроверятьДоступностьПолей = Ложь
);
// Инициализируем процессор компоновки и выводим данные
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
КонецПроцедуры
Преимущества решения: Мы сохраняем структуру СКД, можем использовать сложные запросы, агрегатные функции и виртуальные таблицы.
Важный нюанс: Этот вариант сработает в том случае, если пользователь не успел сбросить или перенастроить структуру полей вручную через форму настроек, где эти поля всё равно будут скрыты для интерактивного выбора.
---
Если вам требуется гарантировать стабильность вывода полей независимо от действий пользователя в интерфейсе настроек, лучшим выбором будет использование внешнего набора данных.
Суть метода заключается в том, что СКД не делает прямых запросов к «запрещенному» справочнику. Вместо этого мы программно на сервере в привилегированном режиме выбираем данные, помещаем их в простую Таблицу Значений и передаем в схему компоновки как внешний объект.
Выясним, как настроить данный механизм по шагам:
ТаблицаСпецификаций.Номенклатура с типом ссылки на разрешенный справочник Номенклатура и Количество с типом Число). Так как сам справочник Спецификации в полях набора данных напрямую не фигурирует в качестве типа значения, платформа не будет применять к колонкам жесткие интерфейсные ограничения.
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Получаем таблицу данных с помощью привилегированного запроса
ТаблицаДанных = ПолучитьДанныеВПривилегированномРежиме();
// Помещаем таблицу во внешний набор данных
ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ТаблицаСпецификаций", ТаблицаДанных);
// Компонуем макет стандартным образом
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(
СхемаКомпоновкиДанных,
КомпоновщикНастроек.ПолучитьНастройки(),
ДанныеРасшифровки
);
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
// Передаем структуру внешних наборов данных вторым параметром
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьДанныеВПривилегированномРежиме()
УстановитьПривилегированныйРежим(Истина);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СпецификацииНоменклатуры.Номенклатура КАК Номенклатура,
| СпецификацииНоменклатуры.Количество КАК Количество
|ИЗ
| Справочник.СпецификацииНоменклатуры КАК СпецификацииНоменклатуры";
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Преимущества решения: Абсолютная надежность. СКД оперирует уже готовой таблицей значений в оперативной памяти и не накладывает никаких ограничений на вывод строк или чисел, полученных из скрытых источников.
---
Рассмотрим альтернативный административный подход. Если вам не хочется переписывать логику отчетов, усложнять СКД программным выводом или переходить на внешние наборы данных, можно пойти от обратного.
Давайте предоставим пользователю полноценные права на «Чтение» и «Просмотр» объекта в роли. В этом случае СКД без каких-либо доработок выведет все поля. Но чтобы предотвратить интерактивное открытие справочника пользователем (чтобы он не мог зайти в него через функции технического специалиста, по ссылке или из других форм), мы заблокируем открытие форм на программном уровне.
Для реализации этого метода откроем модуль формы списка и модуль формы элемента нужного справочника (в нашем примере — Спецификации) и пропишем проверку роли в событии создания формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Если у пользователя нет полных прав (или специальной разрешающей роли),
// мы просто запрещаем открытие формы.
Если Не РольДоступна("ПолныеПрава") Тогда
ВызватьИсключение "Недостаточно прав доступа для просмотра данного объекта!";
КонецЕсли;
КонецПроцедуры
Преимущества решения: Отчеты работают «из коробки» стандартными средствами платформы без дополнительного программирования СКД.
Недостатки решения: Способ считается «обходным» (или, как выразились на форуме, решением «на отъебись»). Пользователь все еще сможет увидеть значения полей в универсальном отчете или выгрузить их через консоль запросов, так как на уровне СУД и метаданных ограничения отсутствуют.
---
Мы проанализировали три метода обхода ограничений прав в СКД. Выбор конкретного пути зависит от архитектуры вашей конфигурации: