Как программно или настроечно ограничить видимость кнопки или реквизита в 1С:ERP 2.4 по группам доступа?

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

В процессе кастомизации крупных конфигураций на базе БСП (таких как 1С:ERP, 1С:КА или 1С:УТ) часто возникает задача ограничить доступ к определенным элементам формы (кнопкам, флажкам, полям ввода) для конкретных пользователей. Например, нам нужно скрыть флажок Цена включает НДС в документе «Приобретение товаров и услуг» для всех сотрудников, кроме бухгалтеров и администраторов.

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

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

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


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

При выполнении подобного кода под правами обычного пользователя система выдает ошибку Нарушение прав доступа или падает с ошибкой несоответствия типов. Проанализируем причины:

  1. Ограничение RLS (Row Level Security): Обычные пользователи в ERP не имеют прав на чтение всего справочника ГруппыДоступа. Попытка обратиться к нему напрямую в коде формы без использования привилегированного режима всегда будет приводить к ошибке нарушения прав.
  2. Конструкция «НЕ Массив» в параметрах: Попытка передать отрицание массива через оператор НЕ в метод УстановитьПараметр вызывает ошибку типа Булево, так как логическое «НЕ» применимо только к булевым типам данных. Отрицание должно находиться в тексте самого запроса: ГДЕ НЕ ГруппыДоступа.Ссылка В (&Ссылка).
  3. Ошибки связей в запросе: В типовой конфигурации 1С:ERP у справочника ГруппыДоступа нет реквизита Пользователь в шапке. Пользователи хранятся в табличной части. Соответственно, условие соединения через ПО ГруппыДоступа.Пользователь = ПользователиСистемы.Ссылка не сработает. Также логическое соединение по условию «И» (AND) для автора, ответственного и пользователя вернет результат только в том случае, если это одно и то же лицо во всех полях, что крайне маловероятно.
  4. Поиск по наименованию: Использование НайтиПоНаименованию("Бухгалтерия Бухгалтер") крайне ненадежно. Если администратор в режиме предприятия переименует группу доступа, код перестанет работать.

Перейдем к правильным вариантам решения задачи.

Решение 1. Использование механизма ролей и БСП (Рекомендуемый способ)

Стандарты разработки 1С настоятельно рекомендуют не завязываться в программном коде на конкретные группы доступа. Группы доступа — это административная сущность пользовательского режима. Правильный подход строится по цепочке: Роль (Конфигуратор) -> Профиль группы доступа (Предприятие) -> Группа доступа (Предприятие).

Разберем по шагам, как реализовать эту схему:

Шаг 1. Создание роли в конфигураторе

В основной конфигурации или в расширении создадим новую роль, например, СТ_РазрешитьИзменениеЦеныВключаяНДС. Права на объекты этой роли давать не нужно — она будет служить только «маркером» доступа.

Шаг 2. Добавление роли в профиль и назначение пользователям

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

Шаг 3. Программная проверка в форме документа

Теперь в модуле формы документа (например, ПриобретениеТоваровУслуг) в процедуре ПриСозданииНаСервере мы можем быстро и безопасно проверить доступность роли с помощью встроенных функций БСП:


&НаСервере
Процедура СТ_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем доступность роли у текущего пользователя
    ДоступностьКнопки = Пользователи.РолиДоступны("СТ_РазрешитьИзменениеЦеныВключаяНДС");
    
    // Управляем видимостью или доступностью элемента формы
    Элементы.ЦенаВключаетНДС.Доступность = ДоступностьКнопки;
    
КонецПроцедуры

Преимущества этого подхода: Метод Пользователи.РолиДоступны() работает очень быстро, не требует написания сложных запросов, учитывает суперправа администраторов (для них функция всегда вернет Истина) и полностью соответствует стандартам разработки 1С.

Решение 2. Настройка видимости через свойства элемента (Без кода)

Если мы не хотим писать программный код, можно воспользоваться платформенным механизмом пользовательской видимости.

Разберем, как это сделать:

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

Этот способ удобен тем, что полностью исключает написание кода и поддерживается платформой на уровне интерфейса.

Решение 3. Корректный запрос к группам доступа в привилегированном режиме

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

Ниже представлен корректный шаблон функции, которую следует разместить в привилегированном общем модуле:


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

Проанализируем ключевые особенности этого запроса:

В модуле формы вызов этой функции будет выглядеть следующим образом:


&НаСервере
Процедура СТ_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    МассивГрупп = Новый Массив;
    МассивГрупп.Добавить("Бухгалтерия Бухгалтер");
    МассивГрупп.Добавить("Закрытие месяца");
    МассивГрупп.Добавить("Администраторы");
    
    // Вызываем нашу привилегированную функцию из общего модуля СТ_РаботаСДоступом
    Доступ Разрешен = СТ_РаботаСДоступом.ПроверитьВхождениеТекущегоПользователяВГруппы(МассивГрупп);
    
    Элементы.ЦенаВключаетНДС.Видимость = ДоступРазрешен;
    
КонецПроцедуры

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

← На главную