Как проверить наличие конкретной роли у пользователя, если у него есть полные права в 1С?

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

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

Анализ проблемы: почему стандартные методы не подходят

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

Кроме того, если роль создана или назначена непосредственно в режиме "1С:Предприятие" через профили групп доступа, а не в конфигураторе напрямую пользователю, сеанс может не сразу подхватить изменения, либо логика РольДоступна() отработает некорректно в контексте разделения прав БСП.

Решение 1: Использование расширения для переопределения логики

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

Нам потребуется создать расширение и добавить в него модуль Пользователи. Мы можем перехватить метод ЭтоПолноправныйПользователь(). Однако, как отмечают специалисты, этот метод может быть слишком глобальным. Если "Главный бухгалтер" не должен считаться полноправным во всей системе, а только в рамках конкретного документа, нам нужно более узкое решение.

Решение 2: Прямой запрос к таблицам прав доступа БСП

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

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


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

Важный нюанс: В коде выше используется соединение с таблицей ролей профиля. Обратите внимание, что в современных версиях БСП роль в табличной части профиля может храниться как ссылка на справочник ИдентификаторыОбъектовМетаданных. В таком случае в условии ГДЕ нужно сравнивать не наименование профиля, а именно имя роли из метаданных, что делает проверку независимой от переименований в интерфейсе.

Решение 3: Использование специализированных методов современных версий БСП

Если ваша конфигурация использует БСП версии 3.0 и выше, проанализируем наличие более современных методов. В модуле УправлениеДоступом существуют функции, которые позволяют получить список всех доступных ролей пользователя без учета "административного фильтра".

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


// Пример использования современного метода БСП
МассивРолей = УправлениеДоступом.РолиДоступныПользователю(Пользователи.АвторизованныйПользователь());
Если МассивРолей.Найти("ВашаСпециальнаяРоль") <> Неопределено Тогда
    // Логика разрешена
КонецЕсли;

Рекомендации по правильной архитектуре прав

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

  1. Не используйте поиск по "Наименованию": Администратор может переименовать профиль "Главный бухгалтер" в "Старший бухгалтер", и строковая проверка в коде перестанет работать. Всегда опирайтесь на Имя роли в конфигураторе.
  2. Функциональные опции: Вместо жесткого кода проверки роли в модуле документа, попробуйте привязать видимость или доступность полей к Функциональной опции. Это позволит управлять логикой из режима "1С:Предприятие".
  3. Идентификаторы метаданных: При написании запросов к таблицам БСП всегда делайте соединение со справочником ИдентификаторыОбъектовМетаданных, чтобы точно идентифицировать объект роли.
  4. Приоритет прав: Помните, что если вы программно запрещаете редактирование, это может вызвать конфликты с регламентными заданиями, которые выполняются под полными правами. Всегда предусматривайте проверку УстановкаПривилегированногоРежима(Истина), если действие должно быть выполнено системой гарантированно.

Таким образом, мы разобрали несколько способов обхода стандартного поведения системы для точечной проверки прав. Выбор метода зависит от версии вашей БСП и критичности задачи. Использование прямого запроса (Решение 2) является наиболее универсальным для старых конфигураций, в то время как Решение 3 предпочтительно для новых систем.

← На главную