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