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