Как ограничить доступ к документам по группам пользователей в 1С:УПП с помощью RLS?

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

При работе в крупных информационных базах на базе конфигурации «1С:Управление производственным предприятием» (УПП) часто возникает задача разграничения прав доступа. Типичный пример: руководство казначейства требует, чтобы менеджеры разных отделов (групп пользователей) не видели документы Заявка на расходование денежных средств друг друга. При этом стандартные механизмы настройки прав по организациям или подразделениям не всегда подходят из-за организационной структуры предприятия.

В данной статье мы подробно разберем, почему у автора темы на форуме не взлетел классический запрос RLS, проанализируем ограничения платформы «1С:Предприятие» при работе с иерархией в запросах ограничений и рассмотрим три надежных практических способа решения этой задачи.

Анализ ошибок: почему не сработал код автора?

Автор темы пытался использовать конструкции вида:


ГДЕ Ответственный = &ТекущийПользователь 
// или
ГДЕ Родитель.Ответственный = &ТекущийПользователь

Выясним причину, почему эта логика ошибочна и система выдает ошибку:

  1. Отсутствие реквизита у документа: У документа Заявка на расходование денежных средств (как и у любого другого документа в системе) физически нет реквизита Родитель. Документы не являются иерархическими объектами. Иерархию (папки) имеет справочник Пользователи.
  2. Неверная адресация полей: Реквизит Ответственный в документе ссылается на элемент справочника Пользователи. Чтобы проверить, находится ли ответственный за документ в той же папке, что и текущий сеансовый пользователь, синтаксически верный запрос должен был выглядеть так: ГДЕ Ответственный.Родитель = &ТекущийПользователь.Родитель. Однако и такое решение использовать на практике категорически не рекомендуется.

Технические ограничения платформы 1С при работе с RLS

Попытка использовать обращение через точку к реквизитам родителя (Ответственный.Родитель.Родитель) или оператор В ИЕРАРХИИ непосредственно в тексте RLS приводит к двум критическим проблемам:

Рассмотрим по шагам три профессиональных способа решения этой задачи.


Способ №1: Использование параметров сеанса и фиксированного массива (Рекомендуемый код)

Проанализируем ситуацию: чтобы база данных работала быстро, RLS-запрос должен быть максимально простым и сравнивать данные по индексам. Оптимальное решение — перенести всю тяжелую работу по расчету иерархии и состава доступных пользователей на этап запуска сеанса работы пользователя.

Выполним следующую последовательность действий:

Шаг 1. Создание параметра сеанса
В конфигураторе создадим новый параметр сеанса с именем ДоступныеПользователи. В качестве типа укажем ФиксированныйМассив.

Шаг 2. Заполнение параметра сеанса при старте системы
Откроем Модуль сеанса и найдем процедуру УстановкаПараметровСеанса. Пропишем код, который определит текущего пользователя, найдет его группу (папку) в справочнике Пользователи и соберет всех пользователей из этой папки в массив:


Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
    
    Если ТребуемыеПараметры = Неопределено Или ТребуемыеПараметры.Найти("ДоступныеПользователи") <> Неопределено Тогда
        
        ТекущийПользовательСистемы = ПараметрыСеанса.ТекущийПользователь;
        МассивПользователей = Новый Массив;
        
        // Если пользователь не задан, доступ закрыт
        Если ЗначениеЗаполнено(ТекущийПользовательСистемы) Тогда
            
            // Получаем родительскую группу текущего пользователя
            РодительПользователя = ТекущийПользовательСистемы.Родитель;
            
            Если ЗначениеЗаполнено(РодительПользователя) Тогда
                // Запрос для получения всех подчиненных пользователей в данной ветке иерархии
                Запрос = Новый Запрос;
                Запрос.Текст = 
                    "ВЫБРАТЬ
                    |   Пользователи.Ссылка КАК Ссылка
                    |ИЗ
                    |   Справочник.Пользователи КАК Пользователи
                    |ГДЕ
                    |   Пользователи.Ссылка В ИЕРАРХИИ(&Родитель)";
                
                Запрос.УстановитьПараметр("Родитель", РодительПользователя);
                РезультатЗапроса = Запрос.Выполнить();
                
                Если Не РезультатЗапроса.Пустой() Тогда
                    МассивПользователей = РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Ссылка");
                КонецЕсли;
            Иначе
                // Если пользователь лежит в корне справочника, он видит только себя
                МассивПользователей.Добавить(ТекущийПользовательСистемы);
            EndIf;
            
        КонецЕсли;
        
        // Записываем полученный список в параметр сеанса в виде ФиксированногоМассива
        ПараметрыСеанса.ДоступныеПользователи = Новый ФиксированныйМассив(МассивПользователей);
        
    КонецЕсли;
    
КонецПроцедуры

Шаг 3. Настройка RLS в роли
Теперь перейдем к настройке роли (например, создадим новую или отредактируем существующую роль для казначеев). В ограничении доступа на чтение для объекта Документ.ЗаявкаНаРасходованиеДенежныхСредств пропишем лаконичное и очень быстрое условие:

ГДЕ Ответственный В (&ДоступныеПользователи)

Почему это работает быстро? СУБД получает готовый плоский список идентификаторов пользователей. Сравнение происходит мгновенно по первичному ключу таблицы, без дополнительных тяжелых соединений таблиц.


Способ №2: Использование справочника «Группы пользователей» вместо папок

Использовать папки внутри справочника Пользователи для разделения прав — это архитектурно негибкое решение. В реальном бизнесе один сотрудник может временно выполнять обязанности другого или входить сразу в несколько проектных групп (например, «Казначейство» и «Администрация»). Элемент справочника может находиться только в одной папке.

Для реализации связи «многие ко многим» в типовых конфигурациях 1С предназначен отдельный справочник ГруппыПользователей. В нем состав пользователей определяется табличной частью ПользователиГруппы.

Посмотрим на пример запроса RLS, который позволит пользователю видеть документы тех коллег, с которыми он состоит хотя бы в одной общей группе пользователей:


ТекущаяТаблица ИЗ #ТекущаяТаблица КАК ТекущаяТаблица
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ГруппыПользователей.ПользователиГруппы КАК СоставГруппы
    ПО СоставГруппы.Пользователь = &ТекущийПользователь
ГДЕ ТекущаяТаблица.Ответственный В (
    ВЫБРАТЬ РАЗЛИЧНЫЕ СоставГруппыОтветственного.Пользователь
    ИЗ Справочник.ГруппыПользователей.ПользователиГруппы КАК СоставГруппыОтветственного
    ГДЕ СоставГруппыОтветственного.Ссылка = СоставГруппы.Ссылка
)

Разберем логику запроса:

  1. Система определяет, в какие группы (элементы справочника ГруппыПользователей) входит текущий авторизованный пользователь (&ТекущийПользователь).
  2. Для каждой найденной группы выбираются все остальные пользователи, состоящие в ней.
  3. Документ становится доступен для просмотра, если значение реквизита Ответственный входит в этот результирующий список.

Способ №3: Использование типового механизма RLS в УПП (без изменения конфигурации)

Разберем ситуацию, когда вносить изменения в конфигурацию (снимать с поддержки, дописывать код) крайне нежелательно. В УПП 1.3 уже встроен мощный готовый универсальный механизм разграничения прав доступа на уровне записей.

Нам достаточно правильно настроить систему в режиме «1С:Предприятие»:

  1. Перейдем в настройки параметров учета и убедимся, что включена константа «Ограничивать доступ на уровне записей».
  2. Откроем справочник Группы пользователей и создадим нужные группы сотрудников (например, «Отдел продаж Восток», «Отдел продаж Запад»). Заполним состав этих групп.
  3. Перейдем в меню: Сервис -> Настройка доступа пользователей -> Настройка доступа на уровне записей.
  4. В открывшейся форме настроек выберем вид объекта доступа «Пользователи».
  5. Для каждой группы пользователей зададим правила: укажем элементы справочника Пользователи, чьи документы им разрешено просматривать.

Типовой механизм RLS в УПП автоматически свяжет эти настройки через регистры сведений НастройкиПравДоступаПользователей и задействует их при формировании списков документов. Документы казначейства по умолчанию используют реквизит Ответственный для сопоставления с видом доступа «Пользователи».

Резюме и рекомендации

Выбор конкретного метода зависит от требований к производительности вашей системы и необходимости кастомизации:

← На главную