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