Как программно изменить роли пользователя в 1С и исправить ошибку "Поле объекта не обнаружено (Роли)"

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

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

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


ПользовательИб = ПользователиИнформационнойБазы.НайтиПоИмени(Строка(ПараметрыСеанса.ТекущийПользователь));
ПользовательИб.Роли.Добавить(Метаданные.Роли.ОграниченнаяРоль);
ПользовательИб.Записать();

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

Анализ причины ошибки: разница между пользователем ИБ и пользователем-справочником

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

В платформе 1С существует два основных понятия "пользователя":

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

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

В результате метод ПользователиИнформационнойБазы.НайтиПоИмени(...) не находит пользователя с таким именем и возвращает Неопределено. Попытка обратиться к свойству Неопределено.Роли и вызывает ошибку "Поле объекта не обнаружено".

Правильные способы программного изменения ролей

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

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

Это самый прямой и надежный способ получить объект пользователя ИБ, под которым в данный момент работает система.

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

Посмотрим на пример:


&НаСервере
Процедура НазначитьРольТекущемуПользователю()

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

КонецПроцедуры

Способ 2: Поиск пользователя по известному имени (логину)

Если вам нужно изменить роли не текущего, а другого пользователя, и вы знаете его точное имя для входа в систему (логин), можно использовать метод НайтиПоИмени(). Главное — передавать в него именно логин, а не ФИО из справочника.

Пример кода:


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

КонецПроцедуры

Способ 3: Связь через уникальный идентификатор (для типовых конфигураций с БСП)

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

Этот способ является предпочтительным, так как он не зависит от возможного изменения имени пользователя (логина).

Разберем по шагам:

  1. Получаем ссылку на элемент справочника "Пользователи" (например, из ПараметрыСеанса.ТекущийПользователь).
  2. Из этого элемента получаем значение реквизита с UUID.
  3. Используем метод ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору() для поиска пользователя ИБ.

Пример реализации:


&НаСервере
Процедура ИзменитьРольДляПользователяИзСправочника(ПользовательСправочник)
    
    // ПользовательСправочник - это ссылка на элемент справочника "Пользователи"
    Если НЕ ЗначениеЗаполнено(ПользовательСправочник) Тогда
        Возврат;
    КонецЕсли;

    // 1. Получаем UUID пользователя ИБ из реквизита справочника
    // В типовых конфигурациях для этого лучше использовать функции общего модуля.
    // Если же его нет, можно получить значение реквизита напрямую.
    ИдентификаторПользователяИБ = ПользовательСправочник.ИдентификаторПользователяИБ;
    
    // 2. Проверяем, что идентификатор получен
    Если ИдентификаторПользователяИБ = Неопределено Или ИдентификаторПользователяИБ = Новый УникальныйИдентификатор() Тогда
        Сообщить("Для пользователя " + ПользовательСправочник + " не установлен идентификатор пользователя ИБ.");
        Возврат;
    КонецЕсли;
        
    // 3. Ищем пользователя ИБ по его UUID
    ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(ИдентификаторПользователяИБ);
    
    Если ПользовательИБ <> Неопределено Тогда
        // Добавляем нужную роль
        ПользовательИБ.Роли.Добавить(Метаданные.Роли.НужнаяРоль);
        ПользовательИБ.Записать();
        Сообщить("Роль успешно добавлена.");
    Иначе
        Сообщить("Пользователь ИБ с указанным идентификатором не найден.");
    КонецЕсли;
    
КонецПроцедуры

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

При программной работе с ролями стоит учитывать несколько важных моментов:

← На главную