Почему не отрабатывает запрос отчета в привилегированном режиме и как это исправить в ЗУП 2.0?

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

При работе в конфигурациях на базе обычных форм, таких как 1С:Зарплата и управление персоналом 2.0, разработчики часто сталкиваются с ситуацией, когда стандартная команда УстановитьПривилегированныйРежим(Истина) не приносит ожидаемого результата. Особенно остро эта проблема проявляется при попытке сформировать отчет, данные в котором ограничены правами доступа на уровне записей (RLS). Разберем по шагам, почему это происходит и как можно решить задачу, даже если основная конфигурация находится на поддержке и внесение изменений в общие модули нежелательно.

Разберем причину: особенности выполнения кода в толстом клиенте

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

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

Поскольку ЗУП 2.0 работает преимущественно в режиме толстого клиента, большая часть кода отчетов исполняется на стороне пользователя. В этом случае RLS всегда будет отсекать данные документов, на которые у пользователя нет прав Чтение.

Решение 1: Использование фоновых заданий для серверного выполнения

Посмотрим на ситуацию, когда мы не можем менять конфигурацию. Одним из эффективных методов обхода ограничений клиентского контекста является запуск формирования данных в фоновом задании. Фоновые задания всегда выполняются на сервере, где привилегированный режим работает в полную силу.

Рассмотрим примерную схему реализации:


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

Этот метод позволяет "перекинуть" выполнение тяжелого запроса на сервер, где RLS можно будет отключить программно.

Решение 2: Оптимизация запроса для обхода RLS (Временные таблицы)

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

Если нам нужно вывести в отчете только статистические данные (например, количество документов или суммы без детализации по сотрудникам, на которых нет прав), мы можем использовать конструкцию ВЫБРАТЬ РАЗРЕШЕННЫЕ. Но что делать, если нужны именно "закрытые" данные?

Выясним принцип работы обхода через временные таблицы:

  1. Сначала мы выбираем во временную таблицу только те поля, которые разрешены RLS (например, Ссылка, Дата).
  2. Затем, если у нас есть доступ к каким-то связанным регистрам, мы соединяем эти ссылки с данными регистров.
  3. Важно помнить: если сам документ НачислениеЗарплаты полностью закрыт на чтение в RLS, то даже Ссылка не попадет в результат запроса без привилегированного режима.

Решение 3: Внешний отчет и программная установка режима

Если вы решили сделать отчет внешним, учтите нюансы безопасного режима. При открытии внешнего отчета через Файл - Открыть, система часто включает безопасный режим, в котором метод УстановитьПривилегированныйРежим() заблокирован из соображений безопасности.

Чтобы обойти это, рекомендуется регистрировать отчет в справочнике Дополнительные отчеты и обработки. Рассмотрим, как программно включить режим в модуле объекта внешнего отчета:


Функция ПолучитьДанныеБезПроверкиПрав() Экспорт
    
    // Устанавливаем привилегированный режим
    // Это сработает только если код вызывается на сервере!
    УстановитьПривилегированныйРежим(Истина);
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   НачислениеЗарплаты.Ссылка,
        |   НачислениеЗарплаты.СуммаДокумента
        |ИЗ
        |   Документ.НачислениеЗарплаты КАК НачислениеЗарплаты";
    
    Результат = Запрос.Выполнить();
    Возврат Результат.Выгрузить();
    
КонецФункции

Решение 4: COM-соединение (Крайний случай)

Если конфигурация полностью закрыта, а права RLS настроены крайне жестко, профессионалы иногда используют метод "внешнего подключения к самому себе". Мы создаем COMОбъект("V83.COMConnector") (или V82), авторизуемся под пользователем с полными правами и выполняем запрос в этой сессии.

Рассмотрим этот процесс:

  1. Создается новое соединение с базой.
  2. Выполняется запрос через NewObject("Query") в контексте COM-соединения.
  3. Результат сериализуется (например, в ЗначениеВСтрокуВнутр) и возвращается в основной сеанс.

Важно: Этот метод сильно расходует лицензии и ресурсы сервера, поэтому используйте его только в крайнем случае.

Подведем итоги

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

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

← На главную