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