Как в RLS-запросе разрешить полный доступ, если в регистре прав нет записей по пользователю?

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

При настройке прав доступа на уровне записей (RLS) часто возникает типовая задача: ограничить видимость объектов (например, документов ЗаказПокупателя) только теми значениями аналитики (например, курьерскими службами), которые явно указаны для пользователя в специальном регистре сведений. При этом, если для пользователя в регистре прав нет ни одной записи, система должна считать, что ограничение на него не распространяется, и возвращать значение ИСТИНА (полный доступ ко всем документам).

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

Ограничения механизма RLS в запросах

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

  1. В классических текстах RLS запрещено использовать пакетные запросы и создание временных таблиц с помощью конструкции ПОМЕСТИТЬ. Допустимы только одиночные запросы с соединениями и вложенными подзапросами.
  2. Условия с оператором ИЛИ и подзапросами в секции ГДЕ могут существенно усложнить построение оптимального плана запроса на стороне СУБД, поэтому критически важно наличие корректных индексов у регистра сведений.

Решение: составление запроса с подзапросом и проверкой соединения

Разберем рабочий вариант реализации условия в RLS. Логика строится на двух составляющих:

  1. Проверка отсутствия настроек для пользователя в регистре через конструкцию НЕ 1 В (ВЫБРАТЬ ПЕРВЫЕ 1 1 ...).
  2. Проверка совпадения реквизита документа со списком разрешенных значений через ЛЕВОЕ СОЕДИНЕНИЕ, если настройки для пользователя все же существуют.

Посмотрим на итоговый текст запроса ограничения прав:


Документ.ЗаказПокупателя КАК ЗаказПокупателя
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПраваНаЗаказыПокФ_КурьерскаяСлужба КАК ПраваНаЗаказыПокФ_КурьерскаяСлужба
        ПО ЗаказПокупателя.Ф_КурьерскаяСлужба = ПраваНаЗаказыПокФ_КурьерскаяСлужба.Ф_КурьерскаяСлужба
        И ПраваНаЗаказыПокФ_КурьерскаяСлужба.Пользователь = &ТекущийПользователь
ГДЕ
    НЕ 1 В (
        ВЫБРАТЬ ПЕРВЫЕ 1
            1
        ИЗ
            РегистрСведений.ПраваНаЗаказыПокФ_КурьерскаяСлужба КАК РегистрПроверки
        ГДЕ
            РегистрПроверки.Пользователь = &ТекущийПользователь
    )
    ИЛИ ПраваНаЗаказыПокФ_КурьерскаяСлужба.Пользователь ЕСТЬ НЕ NULL

Проанализируем, как работает данная конструкция:

  1. Перенос условия по пользователю в секцию ПО: условие ПраваНаЗаказыПокФ_КурьерскаяСлужба.Пользователь = &ТекущийПользователь обязательно указывается в секции соединения, а не в ГДЕ. Если перенести его в ГДЕ без подзапроса, левое соединение превратится во внутреннее, и строки с NULL будут отсечены.
  2. Проверка подзапросом: выражение НЕ 1 В (ВЫБРАТЬ ПЕРВЫЕ 1 1 ...) вернет ИСТИНА, если у текущего пользователя в регистре нет ни одной записи. В этом случае срабатывает левая часть оператора ИЛИ, и пользователю становятся доступны абсолютно все заказы.
  3. Проверка по соединенной таблице: если у пользователя есть записи в регистре, подзапрос вернет ЛОЖЬ, и начнет работать правая часть условия ПраваНаЗаказыПокФ_КурьерскаяСлужба.Пользователь ЕСТЬ НЕ NULL, которая пропустит только те заказы, по которым произошло успешное соединение с разрешенной курьерской службой.

Требования к индексам регистра сведений

Для того чтобы подзапрос и соединение не приводили к полному сканированию таблицы (Table Scan) при каждом чтении документов, необходимо правильно настроить структуру регистра сведений ПраваНаЗаказыПокФ_КурьерскаяСлужба:

  1. Измерение Пользователь должно располагаться первым в списке измерений регистра либо для него должно быть включено свойство Индексировать. Это обеспечит быстрый поиск по индексу в подзапросе ВЫБРАТЬ ПЕРВЫЕ 1.
  2. Измерение Ф_КурьерскаяСлужба должно быть проиндексировано для быстрого соединения с реквизитом документа.

Альтернативный подход: использование параметров сеанса

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

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

ГДЕ
    НЕ &ОграничиватьДоступПоКурьерскимСлужбам
    ИЛИ ЗаказПокупателя.Ф_КурьерскаяСлужба В (&РазрешенныеКурьерскиеСлужбы)

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

← На главную