При разработке механизмов ограничения доступа на уровне записей (RLS) программисты часто используют Параметры сеанса. Это удобный инструмент, позволяющий фильтровать данные в зависимости от контекста текущего пользователя, например, по конкретному сотруднику, подразделению или организации. Однако можно столкнуться с неприятной ситуацией: в формах списков данные отображаются корректно, а в отчетах RLS как будто игнорирует изменения, внесенные в параметр сеанса в процессе работы.
В этой статье мы разберем, почему возникает этот «глюк», как работает архитектура фоновых заданий в 1С и какие существуют проверенные способы решения данной проблемы.
Рассмотрим типичную ситуацию. В системе настроено ограничение на чтение регистра накопления. Текст ограничения выглядит следующим образом:
ТекТаб ГДЕ ТекТаб.Сотрудник = &ТекущийСотрудник
Здесь ТекущийСотрудник — это параметр сеанса. При запуске системы он инициализируется значением по умолчанию. В процессе работы пользователь может программно изменить это значение, например, выбрав другого сотрудника в специальной форме. После этого в формах списка документов или регистров данные начинают фильтроваться по новому сотруднику. Но как только пользователь открывает отчет, сформированный на базе СКД, данные в нем отображаются по старому значению параметра сеанса, которое было установлено при старте системы.
Проанализируем причину такого поведения. В современных версиях платформы 1С:Предприятие 8.3 отчеты по умолчанию формируются в фоновом задании. С точки зрения архитектуры платформы, фоновое задание — это отдельный сеанс на сервере.
Когда мы выполняем код:
ПараметрыСеанса.ТекущийСотрудник = ВыбранныйСотрудник;
Мы меняем значение параметра только в рамках нашего текущего клиентского сеанса. Фоновое задание, которое запускается для формирования отчета, ничего не знает об этих изменениях. При создании сеанса фонового задания платформа повторно вызывает обработчик УстановкаПараметровСеанса в модуле сеанса. Если этот обработчик просто считывает данные «как при первом запуске», то отчет получит старое (инициализационное) значение параметра, и RLS отработает не так, как ожидает пользователь.
Самый простой, но не всегда предпочтительный способ — заставить отчет формироваться в контексте основного сеанса. Если отчет строится не в фоновом задании, он будет использовать те же значения ПараметрыСеанса, что и текущая форма.
Разберем, как это сделать:
ВыполнятьВФоновомЗадании в значение Ложь (если используется стандартная подсистема «Варианты отчетов»).Важно: этот метод лишает пользователя возможности продолжать работу с интерфейсом, пока отчет формируется, что может быть критично для тяжелых отчетов.
Чтобы фоновое задание могло «подхватить» актуальное значение, измененное пользователем, это значение должно быть сохранено где-то в базе данных. Рассмотрим алгоритм реализации через Регистр сведений.
Проанализируем шаги реализации:
НастройкиПользователейСеанса с измерениями Пользователь (или НомерСеанса) и ресурсом ЗначениеПараметра.УстановкаПараметровСеанса, добавляем логику чтения из этого регистра.Пример кода в модуле сеанса:
Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
Если ТребуемыеПараметры = Неопределено Или ТребуемыеПараметры.Найти("ТекущийСотрудник") <> Неопределено Тогда
// Сначала пытаемся получить значение из регистра
АктуальноеЗначение = РегистрыСведений.НастройкиПользователейСеанса.ПолучитьЗначениеДляТекущегоСеанса();
Если ЗначениеЗаполнено(АктуальноеЗначение) Тогда
ПараметрыСеанса.ТекущийСотрудник = АктуальноеЗначение;
Иначе
// Инициализация по умолчанию
ПараметрыСеанса.ТекущийСотрудник = Справочники.Сотрудники.ПустаяСсылка();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Поскольку фоновое задание при старте вызовет этот код, оно получит актуальное значение из базы данных, и RLS в отчете отработает корректно.
Выясним, является ли динамическое изменение параметров сеанса лучшим решением. Использование ПараметрыСеанса в RLS наиболее эффективно, когда они завязаны на константные или редко меняющиеся настройки (роли, основные подразделения пользователя). Если логика доступа должна меняться «на лету» в зависимости от действий пользователя в форме, возможно, стоит перенести часть фильтрации на уровень параметров СКД.
Однако, если стоит задача именно жесткого ограничения прав (чтобы пользователь физически не мог увидеть данные другого сотрудника), рекомендуется привязывать RLS к объектам, которые имеют физическое отражение в БД (например, справочник ГруппыДоступа или НастройкиПрав), а не к динамически меняющимся переменным в памяти сеанса.
Проблема «глюка» RLS в отчетах — это не ошибка платформы, а следствие изоляции сеансов. При изменении параметров сеанса помните, что фоновое задание — это новый сеанс. Чтобы отчет «видел» ваши изменения, всегда обеспечивайте передачу этого состояния через базу данных или отключайте фоновое выполнение отчета.