Как исправить ошибку «Недостаточно прав для работы с таблицей» в СКД при использовании полей составного типа?

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

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

Однако при попытке сформировать отчет под обычным пользователем (не с полными правами) возникает ошибка «Недостаточно прав для работы с таблицей». Разберем подробнее, почему так происходит, почему стандартные операторы языка запросов не спасают и как правильно обойти это ограничение.

Выясним причину возникновения ошибки

Проанализируем структуру регистра сведений ВерсииОбъектов. Его измерение Объект имеет составной тип данных, который включает в себя ссылки практически на все документы и справочники конфигурации (в некоторых случаях — тип ЛюбаяСсылка).

Оптимизатор запросов платформы 1С и механизм контроля прав (включая ограничения на уровне записей — RLS) устроены таким образом, что они проверяют доступность таблиц на этапе компиляции запроса. То есть эта проверка происходит еще до того, как физически будут применены ваши фильтры по конкретному типу документа.

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

Почему не помогают стандартные приемы в запросе?

Посмотрим на типичные попытки разработчиков решить эту проблему "в лоб" и разберем, почему они не работают.

  1. Использование оператора ВЫБРАТЬ РАЗРЕШЕННЫЕ

    Добавив конструкцию ВЫБРАТЬ РАЗРЕШЕННЫЕ, мы действительно избавляемся от ошибки нехватки прав. Однако появляется другая проблема: пользователи теряют возможность добавить отбор по полю ДатаВерсии. Почему так? СКД перед отрисовкой пользовательских настроек анализирует доступность полей. Видя РАЗРЕШЕННЫЕ для поля составного типа, часть таблиц которого недоступна, СКД в целях безопасности автоматически "вырезает" такие поля из списка доступных для отбора и сортировки. Система предотвращает косвенное получение информации о скрытых данных.

  2. Ограничение по типу через ССЫЛКА или ВЫРАЗИТЬ

    Посмотрим на пример запроса, где разработчик попытался явно указать тип данных:

    
    ВЫБРАТЬ РАЗРЕШЕННЫЕ
        ВЫРАЗИТЬ(ВерсииОбъектов.Объект КАК Документ.ЗаказГрузоотправителя) КАК Заказ,
        МИНИМУМ(ВерсииОбъектов.ДатаВерсии) КАК ДатаВерсии
    ПОМЕСТИТЬ ДатыСозданияЗаказов
    ИЗ
        РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
    

    Этот подход тоже не работает. Как мы выяснили ранее, проверка прав идет на этапе компиляции. Операторы ВЫРАЗИТЬ или условия ГДЕ Объект ССЫЛКА Документ применяются позже. Платформа все равно сначала попытается проверить права на весь составной тип и снова выдаст ошибку.

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

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

Разберем по шагам:

  1. В модуле объекта отчета создаем функцию, которая выполняет запрос к базе данных. Чтобы обойти проверку прав, перед выполнением запроса включаем УстановитьПривилегированныйРежим(Истина).
  2. Выполняем запрос, в котором собираем нужные данные (ссылку на документ и дату версии), и выгружаем результат в Таблицу Значений (ТЗ).
  3. В схеме компоновки данных добавляем новый набор данных — Набор данных - объект. Называем его, например, ТаблицаВерсий.
  4. Прописываем поля в этом наборе данных, чтобы СКД понимала структуру нашей ТЗ.
  5. Связываем основной набор данных (где выбираются заказы) с нашим новым набором ТаблицаВерсий на вкладке "Связи наборов данных".
  6. В модуле отчета в обработчике ПриКомпоновкеРезультата передаем сформированную ТЗ в процессор компоновки данных.

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

Решение 2: Программная компоновка в привилегированном режиме

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

Разберем алгоритм действий в модуле объекта отчета:


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

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

Решение 3: Инвертирование связей и ручное управление полями

Иногда помогает перестроение логики запроса внутри самой СКД. Попробуем пойти «от обратного»:

  1. Сделаем основной таблицей запроса конкретный нужный нам документ.
  2. К нему левым соединением будем присоединять регистр ВерсииОбъектов.
  3. Самое важное: на вкладке "Наборы данных" в СКД необходимо снять галочку «Автозаполнение».
  4. После отключения автозаполнения, нам придется прописать все доступные поля СКД вручную, жестко указывая нужный тип ссылки для поля соединения.

Этот метод позволяет заставить СКД не разворачивать составной тип при анализе доступных полей, так как мы берем управление структурой полей на себя.

Решение 4: Корректировка прав с использованием RLS

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

Проанализируем, на какие именно документы платформа "ругается" (обычно это видно в Журнале Регистрации). Мы можем выдать пользователю в его роли галочку на право «Чтение» этих документов. А чтобы он фактически не мог просматривать чужие данные, закроем доступ к самим записям этих таблиц на уровне RLS (ограничение доступа к данным). Для быстрой локализации проблемы можно использовать обработку для определения нарушений прав доступа.

В таком случае проверка прав на этапе компиляции запроса пройдет успешно (ведь базовое право на таблицу есть), а оператор ВЫБРАТЬ РАЗРЕШЕННЫЕ корректно отсечет недоступные строки, при этом не ломая структуру полей СКД для пользовательских отборов.

← На главную