Как настроить отбор в динамическом списке по данным регистра при отсутствии прав на его просмотр

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

В практике разработки на платформе 1С:Предприятие часто возникает ситуация, когда необходимо ограничить доступ пользователей к определенным регистрам сведений из соображений безопасности. Однако бизнес-логика может требовать, чтобы документы в списке фильтровались на основании данных из этих «засекреченных» регистров. Основная сложность заключается в том, что Динамический список — это интерфейсный элемент, который работает в контексте текущего пользователя и проверяет не только право Чтение, но и право Просмотр.

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

Понимание разницы между правами Чтение и Просмотр

Прежде чем переходить к коду, проанализируем, как платформа обрабатывает права доступа. Право Чтение позволяет получать данные запросом в коде (особенно в привилегированных модулях) и использовать их для внутренних вычислений. Право Просмотр управляет видимостью этих данных в элементах интерфейса: формах, списках и отчетах.

Динамический список напрямую связан с Системой Компоновки Данных (СКД). Если поле из регистра попадает в список доступных полей выбора, платформа автоматически проверяет право на просмотр. Если его нет — выполнение запроса блокируется.

Решение 1: Использование конструкции расширения языка запросов

Один из самых простых способов «обмануть» механизм проверки прав в динамическом списке — это использование фигурных скобок {}. Эти конструкции позволяют указать платформе, что поле должно использоваться только для отбора, но не должно быть доступно для вывода в колонки или выбора пользователем вручную.

Рассмотрим пример запроса в динамическом списке:


ВЫБРАТЬ
    ДокументРеализация.Ссылка КАК Ссылка,
    ДокументРеализация.Номер КАК Номер,
    ДокументРеализация.Дата КАК Дата
ИЗ
    Документ.РеализацияТоваровУслуг КАК ДокументРеализация
ГДЕ
    ДокументРеализация.Ссылка В (
        ВЫБРАТЬ
            Рег.Объект
        ИЗ
            РегистрСведений.СекретныеСтатусы КАК Рег
        {ГДЕ
            Рег.Статус.* КАК СтатусИзРегистра}
    )

В данном примере использование {ГДЕ ...} позволяет платформе обрабатывать условие на уровне СКД. Если пользователю не дано право на просмотр регистра, но есть право на чтение, такая конструкция в некоторых версиях платформы позволяет выполнить отбор, если поле не выведено в видимые колонки списка.

Решение 2: Передача параметров через привилегированный модуль

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

Шаг 1. Создадим функцию в серверном модуле с установленным флагом «Привилегированный»:


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

Шаг 2. В форме списка документа при создании на сервере или при изменении условий отбора вызываем эту функцию и передаем результат в динамический список:


&НаСервере
Процедура УстановитьОтборПоРегистру(ВыбранныйСтатус)
    СписокДокументов = МойПривилегированныйМодуль.ПолучитьСписокРазрешенныхДокументов(ВыбранныйСтатус);
    
    // Очищаем старый параметр и устанавливаем новый
    Список.Параметры.УстановитьЗначениеПараметра("МассивСсылок", СписокДокументов);
КонецПроцедуры

Шаг 3. Текст запроса динамического списка при этом должен выглядеть максимально просто:


ВЫБРАТЬ
    Документ.Ссылка,
    Документ.Дата,
    Документ.Номер
ИЗ
    Документ.РеализацияТоваровУслуг КАК Документ
ГДЕ
    Документ.Ссылка В (&МассивСсылок)

Этот метод гарантирует, что пользователь никогда не увидит структуру регистра, а платформа не заблокирует запрос, так как обращение к регистру происходит под полными правами в привилегированном контексте.

Решение 3: Программная модификация схемы компоновки данных

Посмотрим на ситуацию, когда отбор должен быть динамическим и настраиваемым. Мы можем программно изменить настройки компоновки данных динамического списка. Это позволяет внедрять сложные условия, не меняя основной текст запроса в конфигураторе.

Разберем по шагам, как это сделать в коде формы:

  1. Получим КомпоновщикНастроек нашего списка.
  2. Добавим новый элемент отбора.
  3. Установим использование этого отбора в зависимости от прав или внешних условий.

Важно помнить, что если мы используем КомпоновщикНастроек.Настройки.Отбор, платформа все равно может проверить права. Поэтому для «секретных» данных лучше использовать именно параметры (как в Решении 2), внедряя их в запрос через ГДЕ Ссылка В (&Список).

Решение 4: Создание промежуточного «буферного» регистра

Если данные в секретном регистре меняются не слишком часто, а пользователей в системе много, постоянные запросы через привилегированный модуль могут создать нагрузку. В этом случае проанализируем возможность создания вспомогательного регистра.

Алгоритм действий:

Таким образом, в динамическом списке мы будем соединяться с публичным регистром. Это чистое архитектурное решение, которое не требует «хаков» с правами доступа.

Решение 5: Применение фоновых заданий для подготовки данных

Если объем данных в регистре исчисляется миллионами записей, то получение массива ссылок (как в Решении 2) может привести к зависанию формы при открытии. Чтобы избежать этого, рассмотрим вариант с фоновым выполнением.

При открытии формы запускается фоновое задание, которое под полными правами собирает нужные ссылки во временную таблицу или кэш. Пока задание выполняется, список может показывать сообщение «Загрузка данных...» или отображать неполный список. Как только фоновый процесс завершается, форма получает оповещение и обновляет параметр &МассивСсылок. Это обеспечивает максимальную отзывчивость интерфейса при работе с большими объемами данных, защищенных правами доступа.

Важные рекомендации по безопасности

При использовании любого из этих методов помните:

Выбор конкретного метода зависит от ваших требований к производительности и сложности условий отбора. Для простых задач идеально подходит Решение 2 (Привилегированный модуль), для высоконагруженных систем — Решение 4 (Буферный регистр).

← На главную