Почему RLS не запрещает менять дату запрета изменения в форме и как это исправить?

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

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

Причина поведения: разделение уровней СУБД и интерфейса

Проанализируем архитектуру работы ограничений доступа в платформе 1С:Предприятие 8.3:

  1. RLS работает только на уровне базы данных: Ограничение прав на чтение и изменение срабатывает исключительно при обращении к СУБД. Платформа перехватывает запросы и транзакции записи. Она не анализирует динамически каждую ячейку или реквизит формы при вводе символов пользователем.
  2. Данные формы находятся в оперативной памяти клиента: Все интерактивные манипуляции происходят с объектами и реквизитами, считанными в память. До момента фиксации транзакции пользователь может изменять значения любых полей, если для них явно не установлен запрет на уровне интерфейса.
  3. Откат транзакции не очищает форму: Когда пользователь пытается сохранить строку с недоступной организацией, платформа инициирует транзакцию записи набора записей регистра. В этот момент RLS генерирует исключение, транзакция откатывается, но состояние элементов управления на клиенте не сбрасывается автоматически к исходным значениям.
  4. Составной тип данных поля «Объект»: В регистре ДатыЗапретаИзменения измерение Объект может содержать не только ссылки на справочник Организации, но и другие типы (пользователи, группы пользователей, разделы дат запрета). Использование простого шаблона #ПоЗначениям без проверки типа может давать непредвиденный результат.

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

Способ 1. Блокировка редактирования строк через события формы

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

Для этого в расширении конфигурации перехватим событие таблицы формы ПередНачаломИзменения. Если строка относится к запрещенной организации, мы устанавливаем параметр Отказ = Истина:


&НаКлиенте
Процедура Расш_ПередНачаломИзменения(Элемент, Отказ)
    
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Проверяем доступность объекта на сервере
    Если НЕ ОбъектДоступенДляРедактирования(ТекущиеДанные.Объект) Тогда
        Отказ = Истина;
        ПоказатьПредупреждение(, "У вас нет прав на изменение даты запрета по данной организации.");
    КонецЕсли;

КонецПроцедуры

Также полезно динамически управлять доступностью полей при перемещении по строкам списка с помощью события ПриАктивизацииСтроки:


&НаКлиенте
Процедура Расш_ПриАктивизацииСтроки(Элемент)
    
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    ДоступноРедактирование = ОбъектДоступенДляРедактирования(ТекущиеДанные.Объект);
    Элементы.ТаблицаДатыЗапретаДатаЗапрета.ТолькоПросмотр = НЕ ДоступноРедактирование;

КонецПроцедуры

Способ 2. Проверка прав через интерфейс БСП

Разберем, как правильно реализовать проверку прав на сервере. Вместо попыток симулировать запись данных в транзакции для отлова ошибки, используем штатные механизмы подсистемы управления доступом БСП (Библиотеки Стандартных Подсистем):


&НаСервереБезКонтекста
Функция ОбъектДоступенДляРедактирования(Знач ПроверяемыйОбъект)
    
    // Если объект не является организацией (например, раздел дат), проверяем общую логику
    Если ТипЗнч(ПроверяемыйОбъект) <> Тип("СправочникСсылка.Организации") Тогда
        Возврат Истина;
    КонецЕсли;
    
    // Проверка доступа к значению через стандартный модуль БСП
    Возврат УправлениеДоступом.ДоступноЗначение(ПроверяемыйОбъект);

КонецФункции

Метод УправлениеДоступом.ДоступноЗначение проверяет, входит ли переданная ссылка в список разрешенных для текущего пользователя с учетом всех действующих групп доступа и ограничений RLS.

Способ 3. Ограничение видимости недоступных организаций в списке

Посмотрим на альтернативный сценарий: исключить саму возможность увидеть или выбрать «чужие» организации. Здесь применимы два основных приема:

  1. Наложение RLS на чтение: Если ограничить в роли не только право «Редактирование», но и право «Чтение», платформа автоматически отфильтрует записи регистра и элементы справочника организаций при формировании динамического списка. Однако учитывайте, что это может повлиять на общие отчеты, если они строятся без привилегированного режима.
  2. Программный фильтр списка выбора: При добавлении новой строки в форму настройки дат запрета мы можем программно ограничить выбор только теми организациями, которые разрешены пользователю:

&НаСервере
Процедура НастроитьСписокВыбораОрганизаций()
    
    // Получаем массив доступных организаций через метод БСП
    МассивРазрешенных = УправлениеДоступом.РазрешенныеЗначенияВМассиве(
        ПланыВидовХарактеристик.ВидыДоступа.Организации
    );
    
    // Устанавливаем отбор для поля выбора на форме
    ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект");
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
    ЭлементОтбора.ПравоеЗначение = МассивРазрешенных;
    ЭлементОтбора.Использование = Истина;

КонецПроцедуры

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

← На главную