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

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

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

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

Почему возникает ошибка прав при обращении к регистратору?

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

  1. Неявные соединения таблиц: На уровне SQL-запроса платформа формирует неявные левые соединения (LEFT JOIN) со всеми физическими таблицами документов, входящих в составной тип регистратора. Если у текущей роли пользователя нет даже базового права на чтение метаданных хотя бы одного из этих видов документов, СУБД блокирует выполнение запроса до наложения каких-либо условий.
  2. Ограничение конструкции ВЫБРАТЬ РАЗРЕШЕННЫЕ: Ключевое слово РАЗРЕШЕННЫЕ эффективно отсекает записи, закрытые на уровне RLS (по ограничениям доступа к данным), но оно бессильно, если у пользователя полностью отсутствует право «Чтение» на сам объект метаданных в дереве конфигурации.
  3. Разыменование составных полей: Попытка получить реквизит через точку (например, Регистратор.Валюта) заставляет систему опрашивать метаданные всех типов документов, имеющих данный реквизит, что повторно вызывает проверку прав на каждый отдельный объект.

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

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

Посмотрим на пример правильного оформления начала запроса:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
	ПрочиеРасходыОбороты.Организация КАК Организация,
	ПрочиеРасходыОбороты.Регистратор КАК Регистратор,
	ПрочиеРасходыОбороты.СуммаОборот КАК СуммаОборот
ИЗ
	РегистрНакопления.ПрочиеРасходы.Обороты(&НачалоПериода, &КонецПериода, Регистратор, Организация = &Организация) КАК ПрочиеРасходыОбороты

Если после добавления РАЗРЕШЕННЫЕ ошибка сохраняется, значит, причина кроется в полном отсутствии прав на уровне метаданных, и нам потребуются более тонкие механизмы.

Способ 2. Явное приведение типа через ВЫРАЗИТЬ

Если в отчете требуется получить реквизиты конкретного вида документа (например, валюту, курс или контрагента), а мы заранее знаем точный тип документа-регистратора, необходимо исключить неявное обращение ко всем остальным типам. Для этого используем оператор ВЫРАЗИТЬ.

Разберем пример, в котором мы жестко ограничиваем составной тип регистратора до одного документа:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
	ПрочиеРасходыОбороты.Регистратор КАК Регистратор,
	ВЫРАЗИТЬ(ПрочиеРасходыОбороты.Регистратор КАК Документ.ПриобретениеУслугПрочихАктивов).Валюта КАК Валюта,
	ВЫРАЗИТЬ(ПрочиеРасходыОбороты.Регистратор КАК Документ.ПриобретениеУслугПрочихАктивов).Курс КАК Курс,
	ПрочиеРасходыОбороты.СуммаОборот КАК СуммаОборот
ИЗ
	РегистрНакопления.ПрочиеРасходы.Обороты(
		&НачалоПериода,
		&КонецПериода,
		Регистратор,
		Организация = &Организация
			И Регистратор ССЫЛКА Документ.ПриобретениеУслугПрочихАктивов
	) КАК ПрочиеРасходыОбороты

Благодаря явному приведению типа платформа 1С построит соединение исключительно с таблицей Документ.ПриобретениеУслугПрочихАктивов. Проверка прав на остальные документы конфигурации производиться не будет.

Способ 3. Переход на реальную таблицу регистра с фильтрацией по типу ссылки

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

Посмотрим, как переписать запрос на реальную таблицу:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
	ТаблицаРегистра.Период КАК Период,
	ТаблицаРегистра.Регистратор КАК Регистратор,
	ДокументАктивов.Валюта КАК Валюта,
	ДокументАктивов.КурсВзаиморасчетов КАК Курс,
	ТаблицаРегистра.Сумма КАК СуммаОборот
ИЗ
	РегистрНакопления.ПрочиеРасходы КАК ТаблицаРегистра
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПриобретениеУслугПрочихАктивов КАК ДокументАктивов
		ПО ТаблицаРегистра.Регистратор = ДокументАктивов.Ссылка
ГДЕ
	ТаблицаРегистра.Период МЕЖДУ &НачалоПериода И &КонецПериода
	И ТаблицаРегистра.Организация = &Организация

Внутреннее соединение (INNER JOIN) физически отсекает все движения других документов и исключает необходимость обращения к метаданным запрещенных объектов.

Способ 4. Разделение запроса через связи наборов данных в СКД

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

  1. Набор данных 1 (Запрос): Выбирает агрегированные данные из регистра накопления. В нем выбирается только само поле Регистратор без разыменования через точку.
  2. Набор данных 2 (Запрос): Выбирает реквизиты (валюту, курс и т.д.) напрямую из таблицы конкретного документа (например, Документ.ПриобретениеУслугПрочихАктивов), где поле Ссылка выступает ключевым.
  3. Вкладка «Связи наборов данных»: Настраиваем связь между источником (Набор 1) и приемником (Набор 2) по условию Регистратор = Ссылка.

При таком подходе СКД выполняет два изолированных запроса к базе данных и сопоставляет поля в оперативной памяти сервера, гарантируя отсутствие конфликта прав на уровне СУБД.

Способ 5. Программное формирование отчета в привилегированном режиме

В случаях, когда отчет является управленческим и должен показывать сводные финансовые данные независимо от персональных прав пользователя на первичные документы, мы можем выполнить компоновку данных в привилегированном режиме прямо в модуле объекта отчета.

Разберем по шагам реализацию обработчика ПриКомпоновкеРезультата в модуле объекта отчета:


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

Вызов УстановитьПривилегированныйРежим(Истина) временно отключает проверку прав доступа и RLS на время формирования макета и вывода результата, позволяя пользователю сформировать отчет без выдачи избыточных прав на редактирование или просмотр первичной документации.

← На главную