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