При разработке внешних отчетов на базе системы компоновки данных (СКД) часто возникает задача ограничить круг лиц, которые могут формировать этот отчет и видеть содержащиеся в нем данные. В отличие от встроенных отчетов конфигурации, где права можно гибко настроить в дереве объектов метаданных, внешние отчеты требуют особого подхода. В этой статье мы подробно разберем, как реализовать проверку прав программно и с помощью встроенных средств СКД.
Самый быстрый и надежный способ запретить использование отчета — вставить проверку прав в модуль объекта отчета. Для этого мы воспользуемся предопределенной процедурой ПриКомпоновкеРезультата. Эта процедура вызывается системой в тот момент, когда пользователь нажимает кнопку Сформировать.
Рассмотрим простейший пример, когда нам нужно просто прервать выполнение, если у пользователя нет определенной роли. Разберем код:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Проверяем наличие роли "ОсобыеПрава" у текущего пользователя
Если Не РольДоступна("ОсобыеПрава") Тогда
// Генерируем исключение, которое остановит процесс формирования
ВызватьИсключение НСтр("ru = 'Недостаточно прав доступа для формирования данного отчета!'");
КонецЕсли;
КонецПроцедуры
В данном случае, если проверка РольДоступна возвращает Ложь, система выдаст критическое сообщение об ошибке, и отчет не будет построен. Это жесткий, но эффективный метод "отсечения" неавторизованных пользователей.
Если мы хотим, чтобы система вела себя более "дружелюбно", вместо вызова исключения можно вывести информационное сообщение в окно сообщений или непосредственно в табличный документ. Для этого нам потребуется отключить стандартную обработку формирования отчета и описать процесс вывода программно.
Проанализируем ситуацию: когда мы устанавливаем СтандартнаяОбработка = Ложь, мы берем на себя ответственность за инициализацию компоновщика, выполнение макета и вывод результата. Рассмотрим пример кода, который делает это правильно:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Проверяем роль (можно проверять сразу несколько через ИЛИ)
Если Не (РольДоступна("ОсобыеПрава") Или РольДоступна("ПолныеПрава")) Тогда
СтандартнаяОбработка = Ложь; // Отменяем автоматический вывод
// Сообщаем пользователю о проблеме
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(НСтр("ru = 'У вас недостаточно прав для просмотра этих данных.'"));
// Очищаем результат, чтобы пользователь не видел старых данных
ДокументРезультат.Очистить();
Возврат;
КонецЕсли;
// Если права есть, мы можем либо оставить СтандартнаяОбработка = Истина,
// либо сформировать отчет вручную для более тонкой настройки.
КонецПроцедуры
Иногда требуется не просто запретить отчет целиком, а выполнить дополнительные действия при наличии прав. В этом случае мы полностью описываем цикл компоновки. Посмотрим на пример кода, который часто применяется в профессиональной разработке:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь; // Мы сами управляем процессом
Если РольДоступна("РазрешенныйДоступ") Тогда
// 1. Получаем настройки пользователя
НастройкиОтчета = ЭтотОбъект.КомпоновщикНастроек.ПолучитьНастройки();
// 2. Формируем макет компоновки
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(ЭтотОбъект.СхемаКомпоновкиДанных, НастройкиОтчета, ДанныеРасшифровки);
// 3. Инициализируем процессор компоновки
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
// 4. Выводим результат в табличный документ
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Иначе
// Если прав нет, просто выводим текст прямо в ячейку отчета
ДокументРезультат.Очистить();
Область = ДокументРезультат.Область(1, 1);
Область.Текст = "Доступ запрещен. Обратитесь к администратору.";
Область.ЦветТекста = ЦветаСтиля.ЦветОшибкиКритичной;
КонецЕсли;
КонецПроцедуры
Выясним, как можно ограничить доступ не ко всему отчету, а только к его отдельным частям (например, скрыть колонку "Себестоимость" для менеджеров по продажам). В СКД предусмотрен встроенный механизм управления правами на поля.
Выполним следующие шаги:
Важный нюанс: Если у пользователя нет указанной роли, поле просто исчезнет из доступных полей компоновщика. Он не сможет выбрать его в группировках, отборах или выбранных полях. Это наиболее "чистый" способ с точки зрения платформы 1С.
Рассмотрим ситуацию, когда отчет должен работать для всех, но данные должны фильтроваться в зависимости от прав. Например, руководитель видит все подразделения, а мастер — только свое. Мы можем использовать проверку ролей прямо в выражениях параметров СКД.
Разберем алгоритм настройки:
&ТолькоСвоиДанные.НЕ РольДоступна("ПолныеПрава").
ГДЕ (НЕ &ТолькоСвоиДанные) ИЛИ (Ответственный = &ТекущийПользователь)
Такой подход позволяет избежать использования тяжелого механизма RLS (Row Level Security), который может замедлять работу системы, особенно на больших объемах данных.
Если вы работаете в современной конфигурации (УТ 11, ERP, БП 3.0), рекомендуется не "хардкодить" роли внутри отчета, а использовать возможности подсистемы "Дополнительные отчеты и обработки".
Проанализируем преимущества этого метода:
Для реализации этого метода достаточно в модуле объекта внешнего отчета правильно описать функцию СведенияОВнешнейОбработке(), указав тип объекта как "Отчет". После регистрации отчета в справочнике, управление доступом переходит на сторону стандартных средств администрирования 1С.
Подводя итог, можно выделить три основных уровня защиты внешнего отчета:
ПриКомпоновкеРезультата в модуле объекта. Это самый надежный способ для защиты конфиденциальных алгоритмов формирования.Помните, что проверка прав в коде через РольДоступна() чувствительна к точному написанию имени роли (как оно задано в конфигураторе). Будьте внимательны при переносе отчета между разными базами данных, где набор ролей может отличаться.