Как настроить шаблон RLS для разных видов документов с разным набором реквизитов?

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

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

Попытка написать условие через конструкцию ВЫБОР КОГДА или логические операторы приводит к ошибке платформы. Разберем, почему так происходит и какими способами можно правильно решить эту задачу.

В чем причина ошибки платформы при обращении к реквизитам?

Рассмотрим стандартную логику, которую пытаются применить в тексте запроса RLS:


ТекущаяТаблица ИЗ #ТекущаяТаблица КАК ТекущаяТаблица
ГДЕ ВЫБОР 
    КОГДА ТИПЗНАЧЕНИЯ(ТекущаяТаблица.Ссылка) = ТИП(Документ.ТипДок1) 
        ТОГДА ТекущаяТаблица.Субконто1 = &Организация
    КОГДА ТИПЗНАЧЕНИЯ(ТекущаяТаблица.Ссылка) = ТИП(Документ.ТипДок2) 
        ТОГДА ТекущаяТаблица.Организация = &Организация
    ИНАЧЕ ИСТИНА 
КОНЕЦ

При выполнении такого запроса платформа 1С выдает ошибку о том, что реквизит Субконто1 или Организация не найден в проверяемой таблице метаданных.

Проанализируем причину такого поведения:

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

Выяснив причину, рассмотрим эффективные способы решения этой проблемы.

Способ 1. Передача имени реквизита через параметры шаблона RLS

Самый простой и правильный подход при использовании стандартных шаблонов RLS в ролях — отказаться от обращения к конкретным именам реквизитов внутри самого текста шаблона. Вместо этого имя реквизита передается как параметр подстановки при вызове шаблона для конкретного объекта метаданных.

Определим универсальный текст шаблона ограничений (например, с именем ОграничениеПоОрганизации):


ТекущаяТаблица ИЗ #ТекущаяТаблица КАК ТекущаяТаблица
ГДЕ ТекущаяТаблица.#Параметр(1) = &Организация

Теперь при назначении прав на конкретные документы в роли вызываем шаблон с соответствующим параметром:

  1. Для объекта Документ.ТипДок1 указываем: #ОграничениеПоОрганизации("Субконто1")
  2. Для объекта Документ.ТипДок2 указываем: #ОграничениеПоОрганизации("Организация")

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

Способ 2. Использование инструкций препроцессора RLS

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

Посмотрим на пример реализации такого шаблона:


#Если "#ИмяТекущейТаблицы" = "Документ.ТипДок1" #Тогда
    ТекущаяТаблица ИЗ #ТекущаяТаблица КАК ТекущаяТаблица
    ГДЕ ТекущаяТаблица.Субконто1 = &Организация
#ИначеЕсли "#ИмяТекущейТаблицы" = "Документ.ТипДок2" #Тогда
    ТекущаяТаблица ИЗ #ТекущаяТаблица КАК ТекущаяТаблица
    ГДЕ ТекущаяТаблица.Организация = &Организация
#Иначе
    ТекущаяТаблица ИЗ #ТекущаяТаблица КАК ТекущаяТаблица
    ГДЕ ИСТИНА
#КонецЕсли

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

Способ 3. Ограничение прав для журналов документов

Отдельный случай — ограничение прав на уровне журналов документов. Если шаблон RLS применяется к журналу, обратиться напрямую к реквизитам входящих в него документов нельзя.

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


ТекущаяТаблица ИЗ #ТекущаяТаблица КАК ТекущаяТаблица
ГДЕ ТекущаяТаблица.Организация = &Организация

Способ 4. Архитектурное решение БСП (Ключи доступа и регистры)

В современных типовых конфигурациях на базе Библиотеки Стандартных Подсистем (БСП) используется механизм **универсального RLS**. В этом подходе отказываются от сложных условий в запросах RLS в пользу высокой производительности.

Схема работы БСП:

  1. При записи документа в модуле менеджера (в процедуре ПриЗаполненииОграниченияДоступа) средствами BSL проверяется, какой реквизит отвечает за организацию (Субконто1, Организация или другой).
  2. Рассчитанные права и ключи доступа записываются в специализированные регистры сведений (например, НастройкиПравДоступаПользователей или регистры ключей доступа).
  3. Запрос RLS в роли становится предельно простым и проверяет разрешенные данные по ключу доступа, не обращаясь к реквизитам самих документов.

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

← На главную