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