Почему не работает отчет у пользователя при включенном RLS и как это исправить

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

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

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

Разбор проблемного запроса

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


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

Проблема заключается в том, что у пользователя настроен RLS на чтение документа РасчетЗарплаты. Когда система встречает ЛЕВОЕ СОЕДИНЕНИЕ с табличной частью документа, на который наложены ограничения, механизм RLS пытается внедрить свои условия непосредственно в тело запроса. Если логика RLS сложная (например, включает проверку подразделений или групп доступа физлиц), результирующий SQL-запрос становится перегруженным. Конструкция ГДЕ ... ЕСТЬ NULL в сочетании с ограничениями прав часто приводит к тому, что оптимизатор запросов 1С не может корректно обработать выборку разрешенных данных, что и вызывает фатальную ошибку прав доступа.

Способ 1. Использование временных таблиц для упрощения RLS

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

Сначала выберем все разрешенные переработки во временную таблицу. На этом этапе RLS отработает только для одной таблицы, что значительно снизит вероятность ошибки.


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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ВТ_Переработки.Ссылка КАК Ссылка,
    ВТ_Переработки.ФизЛицо КАК ФизЛицо
ИЗ
    ВТ_Переработки КАК ВТ_Переработки
ЛЕВОЕ СОЕДИНЕНИЕ 
    Документ.РасчетЗарплаты.ПрочиеНачисленияИШтрафы КАК РасчетЗарплатыПрочиеНачисленияИШтрафы
ПО 
    (ВТ_Переработки.Ссылка = РасчетЗарплатыПрочиеНачисленияИШтрафы.Документ)
ГДЕ
    РасчетЗарплатыПрочиеНачисленияИШтрафы.Документ ЕСТЬ NULL

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

Способ 2. Выполнение запроса в привилегированном режиме

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

Разберем последовательность действий:

  1. Создадим на сервере экспортную процедуру в модуле с установленным флагом "Привилегированный".
  2. В этой процедуре выполним запрос без использования РАЗРЕШЕННЫЕ, так как права проверяться не будут.
  3. Выгрузим результат запроса в ТаблицаЗначений.
  4. В схеме компоновки данных создадим Внешний набор данных.
  5. Перед формированием отчета передадим полученную таблицу значений в СКД.

Этот метод гарантирует отсутствие ошибок прав доступа, однако требует осторожности. Проанализируем риски: если вы выведете в отчет данные, которые пользователю видеть запрещено (например, суммы зарплаты), это будет нарушением политики безопасности. Поэтому в привилегированном режиме стоит получать только идентификаторы или агрегированные данные.

Способ 3. Использование вспомогательного регистра

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

Мы можем создать регистр СтатусОбработкиПереработок, в который при проведении документа РасчетЗарплаты будет записываться информация о том, что конкретная переработка "закрыта". Тогда наш запрос в отчете превратится в простую выборку из одной таблицы документов с левым соединением к легкому регистру сведений. На регистр сведений можно либо не накладывать RLS вовсе, либо настроить его гораздо проще, чем на документы.

Технические нюансы платформы 8.3

Выясним причину, почему ВЫБРАТЬ РАЗРЕШЕННЫЕ иногда игнорируется платформой. В версиях платформы 8.3.15–8.3.18 был зафиксирован ряд ошибок, связанных с оптимизацией запросов при наличии LEFT JOIN к таблицам, доступ к которым полностью закрыт для пользователя. В этих случаях платформа вместо пустой таблицы (результат отсутствия прав) выбрасывала исключение.

Рекомендации по проверке настроек:

Резюме

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

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

← На главную