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

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

Начнем с анализа важной и часто встречающейся задачи в разработке на платформе 1С 8.3. Мы будем разбираться, как программно получить полный список всех ролей, которые назначены определенному пользователю в информационной базе. Эта функциональность критически важна для создания гибких и безопасных решений, позволяя нам динамически управлять видимостью элементов формы и адаптировать поведение системы под конкретные полномочия пользователя. Например, нам может понадобиться скрыть определенные кнопки, поля или даже целые разделы формы (для этого также можно использовать готовое расширение для настройки доступности элементов формы), если у пользователя нет соответствующей роли, или вывести список всех ролей пользователя для целей аудита и администрирования и анализа прав.

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

Использование объекта ПользовательИнформационнойБазы для получения списка ролей

Для того чтобы программно получить список ролей пользователя в 1С 8.3, мы будем активно использовать системный объект ПользовательИнформационнойБазы. Этот объект является центральным звеном при работе с информацией о пользователях информационной базы и их правах доступа. Он предоставляет нам доступ не только к общим данным пользователя, таким как имя или полное имя, но и, что самое главное для нашей задачи, к коллекции его назначенных ролей.

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

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

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


&НаКлиенте
Процедура ПроверитьРолиТекущегоПользователя()
    // 1. Получаем объект, представляющий текущего пользователя информационной базы.
    // Важно использовать блок Попытка-Исключение, так как в некоторых сценариях (например,
    // при запуске тонкого клиента без предварительной аутентификации или в режиме
    // автономной работы без синхронизации) ТекущийПользователь может быть Неопределено
    // или возникнет исключение доступа.
    Перем ТекущийПользователь;
    Попытка
        ТекущийПользователь = ПользователиИнформационнойБазы.ТекущийПользователь();
    Исключение Э
        Сообщить("Внимание! Не удалось определить текущего пользователя. Возможно, не настроена авторизация или отсутствуют права. " + Э.Описание, СтатусСообщения.Важное);
        Возврат;
    КонецПопытки;

    Если ТекущийПользователь = Неопределено Тогда
        Сообщить("Текущий пользователь не определен в системе. Проверьте настройки пользователей.", СтатусСообщения.Важное);
        Возврат;
    КонецЕсли;

    Сообщить("Обнаружены следующие роли у текущего пользователя '" + ТекущийПользователь.Имя + "':");
    
    // 2. Свойство Роли возвращает коллекцию объектов "РольПользователя".
    // Каждый объект "РольПользователя" имеет свойство Имя (имя роли).
    Если ТекущийПользователь.Роли.Количество() = 0 Тогда
        Сообщить("  У текущего пользователя не назначено ни одной явной роли.");
    Иначе
        Для Каждого Роль Из ТекущийПользователь.Роли Цикл
            // 3. Выводим имя каждой назначенной роли.
            Сообщить("  - " + Роль.Имя);
        КонецЦикла;
    КонецЕсли;

    Сообщить("Операция получения ролей текущего пользователя успешно завершена.");
КонецПроцедуры

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

Получение списка ролей для произвольного пользователя

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

Разберем процесс получения ролей для произвольного пользователя по шагам:

  1. Поиск пользователя: Для поиска пользователя по имени мы используем метод ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователя). Если пользователь имеет уникальный идентификатор (SID), который нам известен, мы можем использовать более надежный метод ПользователиИнформационнойБазы.НайтиПоSID(SIDПользователя). Оба метода возвращают объект ПользовательИнформационнойБазы или Неопределено, если пользователь не найден.
  2. Обращение к свойству "Роли": После успешного обнаружения пользователя, процесс получения списка ролей аналогичен получению ролей текущего пользователя — мы обращаемся к его свойству Роли.
  3. Извлечение имен ролей: Как и в предыдущем случае, мы перебираем коллекцию ролей и извлекаем имена каждой роли.

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

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


&НаСервере
// Функция возвращает массив строк - имен ролей указанного пользователя.
// Возвращает Неопределено, если пользователь не найден или возникла ошибка доступа.
Функция ПолучитьМассивРолейПользователя(ИмяПользователя)

    // Ищем пользователя по имени. Это более удобно для демонстрации,
    // но в реальных системах, особенно если имена могут меняться,
    // более надежным может быть поиск по уникальному идентификатору SID.
    Перем Пользователь;
    Попытка
        Пользователь = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователя);
    Исключение Э
        // Обработка возможных ошибок при поиске пользователя, например, недостаточные права.
        Сообщить("Ошибка при поиске пользователя '" + ИмяПользователя + "': " + Э.Описание, СтатусСообщения.Важное);
        Возврат Неопределено;
    КонецПопытки;

    Если Пользователь = Неопределено Тогда
        Сообщить("Пользователь с именем '" + ИмяПользователя + "' не найден в информационной базе.", СтатусСообщения.Важное);
        Возврат Неопределено;
    КонецЕсли;

    // Создаем новый массив для хранения имен ролей, который будет возвращен функцией.
    МассивИмен Ролей = Новый Массив;

    // Перебираем коллекцию ролей пользователя, которую мы получили из свойства "Роли",
    // и добавляем имя каждой роли в наш массив.
    Для Каждого Роль Из Пользователь.Роли Цикл
        МассивИменРолей.Добавить(Роль.Имя);
    КонецЦикла;

    Возврат МассивИменРолей;

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

&НаСервере
Процедура ПримерВызоваПолучения РолейПроизвольногоПользователя()
    Перем ИмяПользователяДляПроверки;
    ИмяПользователяДляПроверки = "Администратор"; // Пример имени пользователя для проверки.
                                                // Замените на реальное имя пользователя в вашей базе.

    Сообщить("Попытка получения ролей для пользователя '" + ИмяПользователяДляПроверки + "'.");

    МассивРолей = ПолучитьМассивРолейПользователя(ИмяПользователяДляПроверки);

    Если МассивРолей <> Неопределено Тогда
        Если МассивРолей.Количество() = 0 Тогда
            Сообщить("У пользователя '" + ИмяПользователяДляПроверки + "' не назначено явных ролей.");
        Иначе
            Сообщить("Обнаружены следующие роли у пользователя '" + ИмяПользователяДляПроверки + "':");
            Для Каждого ИмяРоли Из МассивРолей Цикл
                Сообщить("  - " + ИмяРоли);
            КонецЦикла;
        КонецЕсли;
    Иначе
        Сообщить("Не удалось получить список ролей для пользователя '" + ИмяПользователяДляПроверки + "'. Проверьте имя пользователя и наличие прав на чтение информации о пользователях.", СтатусСообщения.Важное);
    КонецЕсли;
    Сообщить("Операция получения ролей произвольного пользователя завершена.");
КонецПроцедуры

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

Особенности работы с ролями и правами: Разница между списком ролей и проверкой наличия прав

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

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

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

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


&НаКлиенте
Процедура ПроверитьНаличиеКонкретнойРолиИлиПрава()
    Перем ИмяПроверяемойРоли;
    ИмяПроверяемойРоли = "АдминистраторСистемы"; // Пример имени роли, права которой мы хотим проверить.
                                                // Может быть также именем объекта метаданных,
                                                // например: "Справочник.Номенклатура.Просмотр"

    Сообщить("Проверяем наличие прав, соответствующих роли '" + ИмяПроверяемойРоли + "'.");

    // Функция НаличиеПравДоступа() проверяет, есть ли у текущего пользователя
    // права, определяемые указанной строкой (имя роли или имя права).
    // Возвращает Истина, если права есть, Ложь - в противном случае.
    Если НаличиеПравДоступа(ИмяПроверяемойРоли) Тогда
        Сообщить("  Текущий пользователь имеет права, соответствующие роли '" + ИмяПроверяемойРоли + "'.", СтатусСообщения.Информация);
        // В этом блоке мы можем активировать функционал, доступный только для пользователей с этими правами.
        // Например, сделать видимой кнопку "НастройкиАдминистратора".
        // Элементы.НастройкиАдминистратора.Видимость = Истина;
    Иначе
        Сообщить("  Текущий пользователь НЕ имеет прав, соответствующих роли '" + ИмяПроверяемойРоли + "'.", СтатусСообщения.Важное);
        // Здесь мы можем скрыть или деактивировать соответствующий функционал.
        // Элементы.НастройкиАдминистратора.Видимость = Ложь;
    КонецЕсли;

    // Можно также проверить наличие конкретного права (например, право на просмотр отчета)
    // без привязки к конкретной роли, используя полное имя права из конфигурации.
    // Пример:
    // Если НаличиеПравДоступа("Отчет.ОтчетПоПродажам.Просмотр") Тогда
    //     Сообщить("У пользователя есть право на просмотр отчета по продажам.");
    // КонецЕсли;

    Сообщить("Проверка наличия прав завершена.");
КонецПроцедуры

В чем же принципиальная и важнейшая разница между ПользовательИнформационнойБазы.Роли и НаличиеПравДоступа()?

Резюмируя:

Дополнительные аспекты и рекомендации по работе с ролями в 1С

Мы подробно рассмотрели основные методы получения и проверки ролей. Теперь давайте проанализируем несколько важных аспектов и дадим практические рекомендации, которые следует учитывать при работе с ролями и правами в 1С, чтобы ваши решения были надежными, безопасными и производительными.

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

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

    • Используйте ПользовательИнформационнойБазы.Роли только тогда, когда вам действительно необходим весь список имен ролей. Избегайте частых вызовов этой функции в циклах или при массовых операциях, если только это не является критически важным.
    • Для простой проверки наличия конкретного права или принадлежности к роли, всегда предпочтительнее использовать НаличиеПравДоступа(). Эта функция оптимизирована для быстрой проверки и не извлекает полный список ролей, что значительно снижает накладные расходы.
  3. Безопасность и Принцип Наименьших Привилегий:

    Всегда следуйте принципу наименьших привилегий (Principle of Least Privilege). Предоставляйте пользователям и ролям только те права, которые абсолютно необходимы для выполнения их функциональных обязанностей. В современных конфигурациях рекомендуется изучить работу с правами и ролями через БСП, используя подсистему "Пользователи" для более гибкого управления доступом и программной проверки полномочий.

  4. Кэширование данных о ролях:

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

  5. Использование SID вместо имени пользователя:

    Помимо имени, каждый пользователь в 1С имеет уникальный и неизменный идентификатор — SID (Security IDentifier). Использование SID и программный поиск пользователей может быть более надежным в долгосрочной перспективе, так как имя пользователя может быть изменено администратором, в то время как SID остается постоянным на протяжении всего жизненного цикла пользователя. Если вы храните ссылки на пользователей, рассмотрите возможность хранения их SID.

  6. Обработка ошибок и исключений:

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

  7. Метаданные ролей:

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

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

← На главную