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