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