Как программно проверить вхождение пользователя в группу доступа в расширении 1С

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

При разработке расширений для современных конфигураций 1С, таких как «Бухгалтерия предприятия 3.0», часто возникает задача ограничить выполнение определенных действий (например, нажатие кнопки в обработке) в зависимости от прав пользователя — для этого подойдёт автоматизация проверок прав доступа без программирования. Однако стандартная проверка РольДоступна() не всегда подходит, так как права могут быть распределены по множеству профилей и групп доступа, которые администратор настраивает в пользовательском режиме. В этой статье мы подробно разберем, как правильно реализовать проверку прав на основе справочника Группы доступа, проанализируем возможные ошибки и рассмотрим лучшие практики программирования в среде 1С.

Почему стандартная проверка роли может не работать

Прежде всего, давайте разберем ситуацию, когда разработчик пытается использовать функцию РольДоступна(). В типовых решениях на базе БСП (Библиотеки стандартных подсистем) роли обычно объединяются в Профили групп доступа, а те, в свою очередь, назначаются пользователям через Группы доступа. Если роли внутри группы не уникальны или их список часто меняется, проверка конкретной роли в коде становится ненадежной. Кроме того, администратор может создать новую группу доступа с тем же набором ролей, но с другими ограничениями RLS. Поэтому привязка к вхождению пользователя в конкретную группу (например, «Управление») иногда является более простым и понятным административным решением — есть инструмент настройки интерактивных ролей и прав доступа.

Метод 1. Проверка через табличную часть справочника «Группы доступа»

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

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

Разберем по шагам реализацию в модуле команды или формы:


&НаСервере
Функция ПроверитьПраваПользователяСервер()
    
    // 1. Находим ссылку на нужную группу доступа
    // В данном примере ищем по наименованию "Управление"
    ГруппаДоступа = Справочники.ГруппыДоступа.НайтиПоНаименованию("Управление");
    
    Если ГруппаДоступа.Пустая() Тогда
        // Если группа не найдена, логику определяем сами: либо запрещаем, либо разрешаем
        Возврат Ложь;
    КонецЕсли;

    // 2. Получаем текущего пользователя. 
    // В типовых лучше использовать общий модуль Пользователи
    ТекущийПользователь = Пользователи.ТекущийПользователь();

    // 3. Проверяем наличие пользователя в табличной части
    // Используем метод Найти для быстрого поиска по колонке "Пользователь"
    СтрокаПоиска = ГруппаДоступа.Пользователи.Найти(ТекущийПользователь, "Пользователь");
    
    Если СтрокаПоиска <> Неопределено Тогда
        Возврат Истина; // Пользователь найден в группе
    Иначе
        Возврат Ложь;   // Пользователь не входит в группу
    КонецЕсли;

КонецФункции

&НаКлиенте
Процедура Сформировать(Команда)
    
    Если Не ПроверитьПраваПользователяСервер() Тогда
        Предупреждение("У вас нет прав доступа для выполнения этой операции!");
        Возврат;
    КонецЕсли;
    
    // Продолжение логики формирования документов
    // ...
КонецПроцедуры

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

Особенности работы в расширениях

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

Второй важный момент: для того чтобы обращаться к справочнику ГруппыДоступа из кода расширения, этот справочник (и, возможно, справочник Пользователи) должен быть добавлен в расширение. Однако, если вы используете стандартные вызовы через Справочники.ГруппыДоступа в модуле, который уже находится в контексте расширения, платформа обычно это позволяет, но лучше явно контролировать наличие объектов в составе расширения для корректной типизации. Для этой задачи есть система управления доступом к объектам и формам.

Метод 2. Оптимальный подход через регистр «Состав групп доступа»

Проверка через табличную часть справочника имеет недостаток: если в группе сотни пользователей, метод ГруппаДоступа.Пользователи.Найти() заставит систему считать весь объект из базы, что неэффективно. В системе 1С существует вспомогательный регистр сведений «Состав групп доступа». Он специально предназначен для быстрой проверки прав. Рассмотрим, как написать запрос к этому регистру.


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

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

Метод 3. Использование программного интерфейса БСП (рекомендуется)

Если ваша конфигурация построена на БСП (как «Бухгалтерия предприятия 3.0»), лучше не изобретать велосипед, а использовать готовые функции модуля УправлениеДоступом. Разберем пример проверки профиля пользователя. Профиль — это более стабильная сущность, чем конкретная группа доступа.


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

Проблема прав доступа (RLS)

Проанализируем ситуацию: что если у самого пользователя нет прав на чтение справочника ГруппыДоступа? В этом случае ваш программный код выдаст ошибку доступа при попытке выполнить поиск. Чтобы этого избежать, проверку следует выполнять в привилегированном режиме. Это позволит программе прочитать список групп «от имени системы».


&НаСервере
Функция БезопаснаяПроверкаПрав()
    
    УстановитьПривилегированныйРежим(Истина);
    
    // Здесь размещаем код поиска группы или запрос к регистру
    Результат = ПользовательВходитВГруппу("Управление");
    
    УстановитьПривилегированныйРежим(Ложь);
    
    Возврат Результат;
    
КонецФункции

Советы по улучшению кода

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

  1. Избегайте поиска по наименованию. Администратор может случайно изменить «Управление» на «Управление (новое)», и ваш код перестанет работать. Лучше создать Предопределенный элемент в расширении для профиля или группы доступа, либо использовать константу/настройку, где администратор сам выберет нужную группу.
  2. Кеширование. Если кнопка «Сформировать» нажимается часто, не стоит каждый раз обращаться к базе данных. Можно один раз при открытии формы проверить права и сохранить результат в переменную формы ДоступРазрешен.
  3. Информативность. Вместо простого исключения ВызватьИсключение, лучше использовать ОбщегоНазначенияКлиентСервер.СообщитьПользователю, чтобы пользователь понимал, к кому обратиться для получения прав.

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

← На главную