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