Смена ролей пользователя 1С из кода: встроенный язык, БСП и внешнее соединение
Содержание
Чтобы программно изменить роль в 1С, найдите пользователя через ПользователиИнформационнойБазы.НайтиПоИмени(), добавьте или удалите роль в его коллекции Роли и вызовите Записать(). Код выполняется на сервере под пользователем с правом «Администрирование» или в привилегированном режиме. Новый набор прав пользователь получит при следующем входе в базу.
Это работает в «голой» конфигурации и в самописных решениях. В типовых конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11) роли напрямую лучше не трогать: ими управляют профили и группы доступа, и ручная правка будет перезаписана. Там администратор меняет роль иначе — включает пользователя в нужную группу доступа. Для массовой правки в нескольких базах подходит внешнее COM-соединение.
Как устроены права: роль, пользователь ИБ и группа доступа
В 1С:Предприятии 8.3 права задаются ролями. Роль — объект метаданных: в нём разработчик отмечает, что можно делать с каждым справочником, документом, регистром и отчётом. Сама по себе роль ни к кому не привязана.
Привязка живёт у пользователя информационной базы. Это служебный объект платформы, его видно в Конфигураторе: Администрирование → Пользователи. У каждого пользователя ИБ есть:
- 👤 имя и полное имя;
- 🔑 пароль или настройки аутентификации ОС;
- 🧩 коллекция
Роли— список ролей, доступных в сеансе; - 🆔 уникальный идентификатор, по которому его находят надёжнее, чем по имени.
Права суммируются. Если в одной роли документ доступен только на чтение, а в другой — на запись, пользователь сможет его записать. Отдельной роли «запретить» нет.
В конфигурациях на Библиотеке стандартных подсистем (БСП) поверх этой схемы надстроен ещё один слой:
| Уровень | Где хранится | Кто меняет |
|---|---|---|
| Роль | Метаданные конфигурации | Разработчик в Конфигураторе |
| Пользователь ИБ и его роли | Список пользователей платформы | Платформа по команде кода |
| Профиль групп доступа | Справочник «Профили групп доступа» | Администратор в режиме Предприятия |
| Группа доступа | Справочник «Группы доступа» | Администратор в режиме Предприятия |
| Пользователь | Справочник «Пользователи» | Администратор в режиме Предприятия |
Профиль — это набор ролей. Группа доступа связывает профиль со списком пользователей и ограничениями (например, по организациям). При записи группы БСП сама пересчитывает коллекцию Роли у каждого пользователя ИБ. Поэтому в типовых решениях источник правды — группы доступа, а не роли пользователя.
Что подготовить перед запуском кода
Программная смена ролей — операция с правами, ошибка в ней может закрыть доступ всем. Перед работой проверьте четыре вещи.
- Права исполнителя. Код, который меняет пользователей ИБ, должен работать под пользователем с правом «Администрирование» в одной из его ролей. Второй вариант — привилегированный режим:
УстановитьПривилегированныйРежим(Истина)в серверной процедуре или общий модуль с флагом «Привилегированный». - Контекст выполнения. Объект
ПользователиИнформационнойБазыдоступен на сервере, в толстом клиенте и через внешнее соединение. В тонком и веб-клиенте его нет. - Точные имена ролей. В коде используется имя роли из метаданных, а не синоним. Синоним «Бухгалтер» и имя
Бухгалтермогут совпадать, но часто не совпадают. Имена смотрите в Конфигураторе в веткеОбщие → Роли. - Резервная копия. Перед массовой правкой выгрузите базу в
.dtили сделайте копию средствами СУБД.
Не снимайте административную роль с единственного администратора. Платформа не даст записать такого пользователя, если в базе не останется ни одного пользователя с правом «Администрирование». Но если вы по ошибке закроете доступ, придётся восстанавливаться из копии.
Пустой список пользователей — особый случай. Пока в базе нет ни одного пользователя ИБ, любой вход идёт с полными правами. Первый же созданный пользователь должен получить административную роль, иначе платформа его не запишет.
Изменение роли пользователя на встроенном языке
Базовый приём одинаков для любой конфигурации: найти пользователя ИБ, поправить коллекцию Роли, записать. Ниже — полный пример серверной процедуры, которая добавляет одну роль и снимает другую.
&НаСервереБезКонтекста
Функция ИзменитьРолиПользователя(ИмяПользователя, ИмяДобавить, ИмяУдалить)
ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователя);
Если ПользовательИБ = Неопределено Тогда
Возврат "Пользователь не найден: " + ИмяПользователя;
КонецЕсли;
РольДобавить = Метаданные.Роли.Найти(ИмяДобавить);
РольУдалить = Метаданные.Роли.Найти(ИмяУдалить);
Если РольДобавить = Неопределено Или РольУдалить = Неопределено Тогда
Возврат "Роль не найдена в метаданных";
КонецЕсли;
Если Не ПользовательИБ.Роли.Содержит(РольДобавить) Тогда
ПользовательИБ.Роли.Добавить(РольДобавить);
КонецЕсли;
Если ПользовательИБ.Роли.Содержит(РольУдалить) Тогда
ПользовательИБ.Роли.Удалить(РольУдалить);
КонецЕсли;
Попытка
ПользовательИБ.Записать();
Исключение
Возврат "Ошибка записи: " + ОписаниеОшибки();
КонецПопытки;
Возврат "Готово";
КонецФункции
Что здесь важно:
- 🔍
Метаданные.Роли.Найти()возвращаетНеопределено, если имени нет. ОбращениеМетаданные.Роли.Бухгалтерв таком случае упадёт с ошибкой, поэтомуНайти()надёжнее для имён из параметров. - ✅
Содержит()передДобавить()защищает от лишних изменений и делает код безопасным для повторного запуска. - 💾 Без
Записать()изменения останутся в памяти и пропадут.
Как полностью заменить набор ролей
Если пользователю нужен строго определённый список прав, сначала очистите коллекцию, потом заполните заново:
ПользовательИБ.Роли.Очистить();
Для Каждого ИмяРоли Из СтрРазделить("Бухгалтер,ЧтениеОтчетов", ",") Цикл
Роль = Метаданные.Роли.Найти(СокрЛП(ИмяРоли));
Если Роль <> Неопределено Тогда
ПользовательИБ.Роли.Добавить(Роль);
КонецЕсли;
КонецЦикла;
ПользовательИБ.Записать();
Поиск по идентификатору вместо имени
Имя пользователя могут переименовать, идентификатор не меняется. Если вы храните ссылку на пользователя в своём справочнике, сохраняйте ПользовательИБ.УникальныйИдентификатор и ищите через ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(УИД). В БСП этот идентификатор лежит в реквизите ИдентификаторПользователяИБ справочника «Пользователи».
Обойти всех пользователей базы можно через ПользователиИнформационнойБазы.ПолучитьПользователей() — метод возвращает массив.
Роли текущего сеанса фиксируются при входе. Если вы поменяли роли пользователю, который сейчас работает, проверка РольДоступна() в его сеансе будет показывать старое состояние до перезапуска программы.
Типовые конфигурации на БСП: меняем роль через группу доступа
В Бухгалтерии 3.0, ЗУП 3.1, УТ 11 и других решениях на БСП прямая правка ПользовательИБ.Роли даёт временный результат. При следующей записи группы доступа, профиля или карточки пользователя подсистема «Управление доступом» пересчитает роли по профилям. Добавленная вручную роль исчезнет, снятая — вернётся.
Правильный путь — включить пользователя в группу доступа с нужным профилем. В интерфейсе это делается в Администрирование → Настройки пользователей и прав, а программно — через справочник «Группы доступа»:
&НаСервере
Процедура ВключитьВГруппуДоступа(ПользовательСсылка, ГруппаСсылка)
ГруппаОбъект = ГруппаСсылка.ПолучитьОбъект();
Если ГруппаОбъект.Пользователи.Найти(ПользовательСсылка, "Пользователь") = Неопределено Тогда
НоваяСтрока = ГруппаОбъект.Пользователи.Добавить();
НоваяСтрока.Пользователь = ПользовательСсылка;
ГруппаОбъект.Записать();
КонецЕсли;
КонецПроцедуры
Здесь ПользовательСсылка — элемент справочника «Пользователи», а не объект ПользовательИнформационнойБазы. После записи группы БСП сама обновит роли пользователя ИБ.
Чтобы снять права, удалите строку пользователя из табличной части Пользователи той же группы и запишите её.
В программном интерфейсе общего модуля УправлениеДоступом в современных версиях БСП есть процедуры ВключитьПрофильПользователю и ВыключитьПрофильПользователю. Они сами находят или создают персональную группу доступа для профиля. Перед использованием откройте модуль в Конфигураторе и проверьте описание параметров в комментарии к процедуре: состав параметров зависит от версии БСП в вашей конфигурации.
Не меняйте состав ролей в профилях, поставляемых с конфигурацией. При обновлении релиза поставляемые профили обновятся, и ваши правки пропадут. Нужен другой набор ролей — скопируйте профиль и правьте копию.
Смена роли пользователя 1С через COM-соединение
Внешнее соединение нужно, когда роли надо поменять снаружи: из другой базы 1С, по расписанию или сразу в десятке баз. Работает через COM-объект V83.COMConnector, который предоставляет библиотека comcntr.dll из каталога bin платформы.
Если COM-объект не создаётся, зарегистрируйте библиотеку из командной строки, запущенной от имени администратора:
regsvr32 "C:\Program Files\1cv8\8.3.25.1000\bin\comcntr.dll"
Номер версии в пути подставьте свой. Разрядность имеет значение: 64-битный процесс видит только 64-битную регистрацию.
Пример кода, который выполняется в любой базе 1С (в обработке, на сервере или в толстом клиенте) и меняет роль в другой базе:
Коннектор = Новый COMОбъект("V83.COMConnector");
СтрокаСоединения = "Srvr=""srv1c"";Ref=""buh"";Usr=""Администратор"";Pwd=""***"";";
Попытка
База = Коннектор.Connect(СтрокаСоединения);
Исключение
Сообщить("Не удалось подключиться: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
ПользовательИБ = База.ПользователиИнформационнойБазы.НайтиПоИмени("Иванова");
Роль = База.Метаданные.Роли.Найти("ЧтениеОтчетов");
Если ПользовательИБ <> Неопределено И Роль <> Неопределено Тогда
Если Не ПользовательИБ.Роли.Содержит(Роль) Тогда
ПользовательИБ.Роли.Добавить(Роль);
ПользовательИБ.Записать();
КонецЕсли;
КонецЕсли;
Для файловой базы строка соединения выглядит так: File="C:\Bases\Buh";Usr="Администратор";Pwd="***";.
Объект роли берут из метаданных подключённой базы (База.Метаданные), а не своей. Роль из чужих метаданных в коллекцию не добавится.
Пользователь, под которым идёт подключение, должен иметь право «Внешнее соединение» и право «Администрирование». Учётные данные не храните в коде: читайте их из защищённых настроек или запрашивайте при запуске.
Альтернатива без COM: обработка при запуске
Если COM недоступен, создайте внешнюю обработку
с кодом смены ролей в модуле и запустите клиент с параметром /Execute:
"C:\Program Files\1cv8\8.3.25.1000\bin\1cv8.exe" ENTERPRISE /S "srv1c\buh" /N "Администратор" /P "***" /Execute "C:\Scripts\roles.epf"
Обработка откроется сразу после входа. Этот вариант удобен для одной-двух баз, для массовой правки COM всё же проще.
Управляемые формы: где писать код смены ролей
В управляемом приложении код формы разделён на клиентский и серверный. В тонком и веб-клиенте нет объекта ПользователиИнформационнойБазы, поэтому чтение и запись ролей — только в серверных процедурах. Клиент лишь передаёт параметры и показывает результат.
Типичная схема для обработки с кнопкой:
- Команда формы
&НаКлиентесобирает выбранные значения: имя пользователя, имена ролей. - Вызывает функцию
&НаСервереБезКонтекста, передаёт ей строки. - Серверная функция меняет роли и возвращает текст результата.
- Клиент показывает результат через
ПоказатьПредупреждение()или выводит в поле формы.
&НаСервереБезКонтекста лучше &НаСервере: на сервер не передаются данные формы, вызов быстрее.
Если обработку будут запускать пользователи без административных прав, вынесите код в общий модуль с флагами «Сервер» и «Привилегированный». Тогда смена ролей пройдёт, но доступ к такой обработке нужно ограничить отдельной ролью, иначе любой сможет выдать себе полные права.
Для списка ролей в форме удобно заполнить список значений на сервере:
Для Каждого Роль Из Метаданные.Роли Цикл
СписокРолей.Добавить(Роль.Имя, Роль.Синоним);
КонецЦикла;
Пользователь видит понятные синонимы, а в код уходят имена.
Ошибки при программной смене ролей и как их разобрать
Почти все сбои сводятся к нескольким причинам. Ловите их через Попытка … Исключение и пишите ОписаниеОшибки() в журнал регистрации методом ЗаписьЖурналаРегистрации() — так проще разбирать запуск по расписанию.
Ещё одна частая ловушка — внешнее соединение с базой, в которой идёт обновление конфигурации или установлена блокировка начала сеансов. Подключение не пройдёт, пока блокировку не снимут. Скрипт по расписанию стоит запускать в окно, когда регламентных операций нет.
Частые вопросы
Можно ли изменить роль пользователя, который сейчас в базе?
Как узнать, какие роли уже есть у пользователя?
Для Каждого Роль Из ПользовательИБ.Роли Цикл Сообщить(Роль.Имя); КонецЦикла;. Код выполняйте на сервере.Можно ли создать новую роль программно?
Как проверить роль текущего пользователя?
РольДоступна("ИмяРоли") или РольДоступна(Метаданные.Роли.ИмяРоли). Она проверяет роли текущего сеанса.