Как раздать роли пользователям через встроенный язык 1С
Содержание
Роль пользователю в 1С 8.3 назначают через коллекцию Роли объекта ПользователиИнформационнойБазы: метод Роли.Добавить(Метаданные.Роли.ИмяРоли), а затем Записать(). Это базовый способ на встроенном языке — он работает и для одного пользователя, и для массовой обработки списка.
Но есть ловушка: в типовых конфигурациях (Бухгалтерия 3.0, ЗУП 3.1, УТ 11) прямое программное назначение ролей часто сбрасывается при следующей записи пользователя. Там роли раздаёт не разработчик напрямую, а механизм групп доступа. Ниже — все рабочие методы: от одной строки кода до записи через COM-соединение из внешней программы, плюс разбор, почему роль иногда «не прилипает».
Два уровня хранения ролей: платформа и типовая логика
Прежде чем писать код, нужно понять, где роль физически хранится. От этого зависит, какой метод сработает.
На уровне платформы роли привязаны к объекту ПользователиИнформационнойБазы (InfoBaseUser). У каждого пользователя ИБ есть коллекция Роли — именно её читает платформа при проверке прав. Это низкий уровень, доступный в любой конфигурации.
В типовых конфигурациях поверх этого работает подсистема «Управление доступом» из БСП. Пользователь хранится в справочнике Справочник.Пользователи, его права складываются из профилей групп доступа (Справочник.ПрофилиГруппДоступа), а сами роли платформы БСП пересчитывает автоматически. Если дописать роль напрямую в ПользователиИнформационнойБазы, БСП при следующей записи элемента справочника затрёт её обратно.
Правило простое: в вашей собственной или «тонкой» конфигурации без подсистемы доступа — работайте напрямую через ПользователиИнформационнойБазы. В типовой на БСП — через группы доступа (см. раздел про типовые ниже).
Чтобы не держать это в голове, вот сводка способов — какой когда применять:
| Способ | Когда применять | Ограничение |
|---|---|---|
ПользователиИнформационнойБазы.Роли | своя или нетиповая конфигурация, разовая правка | в типовой на БСП роль сбрасывается при записи |
| Массовая обработка в цикле | выдать роль многим пользователям сразу | нужны права администратора ИБ, на больших базах долго |
| Группы доступа и профили | типовые: Бухгалтерия, ЗУП, УТ | роль задаётся не напрямую, а через профиль группы |
| COM-соединение или HTTP-сервис | из внешней программы, скрипта, интеграции | требует настройки соединения или публикации сервиса |
Дальше — каждый способ с кодом и нюансами.
Назначение роли через объект ПользователиИнформационнойБазы
Это стандартный метод платформы. Находим пользователя по имени, добавляем роль, записываем:
Пользователь = ПользователиИнформационнойБазы.НайтиПоИмени("Иванов");
Если Пользователь <> Неопределено Тогда
Пользователь.Роли.Добавить(Метаданные.Роли.МенеджерПоПродажам);
Пользователь.Записать();
КонецЕсли;
Роли.Добавить() принимает объект метаданных роли — Метаданные.Роли.ИмяРоли, где имя совпадает с тем, как роль названа в дереве конфигурации. Передавать строку с именем нельзя, только ссылку на метаданные.
Полезные методы коллекции Роли:
- 🔎
Содержит(Роль)— проверить, есть ли роль у пользователя (вернётИстина/Ложь); - ➕
Добавить(Роль)— выдать роль; - ➖
Удалить(Роль)— отобрать одну роль; - 🧹
Очистить()— снять все роли сразу.
Перед выдачей лучше проверять, чтобы не плодить лишние записи:
Роль = Метаданные.Роли.МенеджерПоПродажам;
Если НЕ Пользователь.Роли.Содержит(Роль) Тогда
Пользователь.Роли.Добавить(Роль);
Пользователь.Записать();
КонецЕсли;
Если нужно заменить весь набор ролей, а не дополнить:
Пользователь.Роли.Очистить();
Пользователь.Роли.Добавить(Метаданные.Роли.БазовыеПрава);
Пользователь.Роли.Добавить(Метаданные.Роли.МенеджерПоПродажам);
Пользователь.Записать();
Код, меняющий состав пользователей и ролей, выполняется только на сервере и требует административных прав на информационную базу. Из обычного клиентского модуля без привилегий он выдаст ошибку доступа.
Массовое назначение ролей обработкой
Когда роль нужно выдать десяткам сотрудников, пишут внешнюю обработку . Принцип тот же, но пользователи перебираются в цикле. Чтобы не вызывать поиск по каждому имени, один раз получаем весь список:
Роль = Метаданные.Роли.ЧтениеОтчётов;
Для Каждого Пользователь Из ПользователиИнформационнойБазы.ПолучитьПользователей() Цикл
Если Пользователь.Роли.Содержит(Роль) Тогда
Продолжить;
КонецЕсли;
Пользователь.Роли.Добавить(Роль);
Пользователь.Записать();
КонецЦикла;
ПолучитьПользователей() возвращает массив всех пользователей ИБ — его удобно отфильтровать по нужному признаку (например, только активным или только из определённого списка имён).
В массив попадают и служебные учётки без интерактивного входа. Прежде чем раздавать всем прикладную роль, исключите технических пользователей (обмен, фоновые задания) — им лишние права не нужны и иногда вредны. Проще всего вести массовую выдачу по заранее согласованному списку имён, а не по всему массиву подряд.
Частый сценарий — раздать роль по списку имён из таблицы значений или из файла. Тогда заранее собираем соответствие «имя → пользователь», чтобы не искать в цикле:
Соответствие = Новый Соответствие;
Для Каждого Пользователь Из ПользователиИнформационнойБазы.ПолучитьПользователей() Цикл
Соответствие.Вставить(Пользователь.Имя, Пользователь);
КонецЦикла;
Для Каждого Имя Из СписокИмён Цикл
Пользователь = Соответствие.Получить(Имя);
Если Пользователь <> Неопределено Тогда
Пользователь.Роли.Добавить(Метаданные.Роли.ЧтениеОтчётов);
Пользователь.Записать();
КонецЕсли;
КонецЦикла;
Так один проход по базе вместо сотни отдельных запросов НайтиПоИмени.
Роли в типовых конфигурациях: группы доступа вместо прямого кода
Самая частая причина «почему роль не назначилась» в Бухгалтерии, ЗУП и УТ — попытка выдать её напрямую через ПользователиИнформационнойБазы. В конфигурациях с подсистемой «Управление доступом» это не работает
надёжно: БСП пересчитывает роли платформы из профилей групп доступа при каждой записи элемента Справочник.Пользователи.
Правильный путь в типовой — через группы доступа. Через интерфейс это делается так: Администрирование → Настройки пользователей и прав → Группы доступа (точное название раздела зависит от конфигурации, но путь начинается с раздела Администрирование). Каждая группа доступа ссылается на профиль, а профиль содержит набор ролей. Пользователь получает роли через членство в группе.
Программно модель та же: нужно добавить пользователя
в табличную часть Пользователи элемента справочника ГруппыДоступа (а не дописывать роль в объект ИБ). Логика примерно такая:
- Находим или создаём нужный профиль групп доступа с набором ролей.
- Находим группу доступа, привязанную к этому профилю.
- Добавляем ссылку на пользователя (
Справочник.Пользователи) в табличную часть группы. - Записываем элемент группы доступа.
В БСП есть служебные методы для записи пользователя ИБ и обновления его ролей из профилей. Если дорабатываете типовую — используйте штатный программный интерфейс подсистемы доступа, а не прямую правку Роли, иначе ваша доработка перестанет работать после обновления или первой же записи карточки пользователя.
Вывод: прямой код из разделов выше — для конфигураций без подсистемы доступа. Для типовых — группы доступа. Смешивать два подхода в одной базе нельзя: платформенные роли и профили разойдутся, и права будут вести себя не так, как показывает карточка пользователя.
Понять, на БСП ваша конфигурация или нет, просто: если в разделе администрирования есть справочники профилей и групп доступа, а в карточке пользователя роли не редактируются напрямую — это БСП, и работать нужно через группы.
Назначение ролей из внешней программы: COM-соединение
Когда роли нужно раздавать из внешней системы (скрипт развёртывания, кадровый портал, собственная утилита администратора), применяют внешнее соединение через COM-коннектор. Это и есть «сложный сценарий» для интеграций: код выполняется в контексте базы, но запускается снаружи.
Коннектор = Новый COMОбъект("V83.COMConnector");
Соединение = Коннектор.Connect(
"Srvr=""server-1c"";Ref=""buh"";Usr=""Администратор"";Pwd=""пароль""");
Для Каждого Пользователь Из Соединение.ПользователиИнформационнойБазы.ПолучитьПользователей() Цикл
// обработка на стороне базы
КонецЦикла;
Через объект Соединение доступен тот же контекст сервера, включая ПользователиИнформационнойБазы. Логику назначения лучше вынести в экспортную серверную процедуру конфигурации и вызывать её из внешнего соединения — так не придётся дублировать проверки прав и БСП-логику снаружи.
Два условия, без которых COM-соединение не поднимется: на машине, откуда идёт подключение, должна быть зарегистрирована компонента comcntr.dll (её ставит инсталлятор платформы), и разрядность вызывающей программы должна совпадать с разрядностью установленной 1С. Строка подключения для серверной базы начинается с Srvr и Ref, для файловой — с File.
Отдельно про REST. Штатный интерфейс OData (REST) отдаёт прикладные объекты — справочники, документы — но не управляет ролями пользователей ИБ напрямую: роли живут на уровне платформы, а не в составе данных OData. Чтобы назначать роли по HTTP из внешней системы, публикуют собственный HTTP-сервис, который внутри вызывает всё тот же ПользователиИнформационнойБазы. То есть REST здесь — это тонкая обёртка над встроенными методами, а не отдельный механизм.
Выдача роли при создании пользователя
Удобно назначать роли сразу в момент создания пользователя — чтобы не было «пустых» учёток без прав. При программном создании через СоздатьПользователя() роли добавляются до записи:
Новый = ПользователиИнформационнойБазы.СоздатьПользователя();
Новый.Имя = "Петров";
Новый.ПолноеИмя = "Петров Пётр";
Новый.АутентификацияСтандартная = Истина;
Новый.Роли.Добавить(Метаданные.Роли.БазовыеПрава);
Новый.Роли.Добавить(Метаданные.Роли.МенеджерПоПродажам);
Новый.Записать();
Обратите внимание на свойства пользователя при создании. Имя — это логин, по которому идёт вход и поиск НайтиПоИмени; ПолноеИмя — отображаемое имя в списке. Если вход выполняется под учётной записью Windows, вместо АутентификацияСтандартная задают АутентификацияОС и свойство ПользовательОС в формате домен\\учётка. Пароль для стандартной аутентификации устанавливают свойством Пароль до записи.
Если нужно, чтобы каждый новый сотрудник автоматически получал базовый набор, логику выдачи ролей размещают в обработчике, который отрабатывает при записи пользователя. В типовых конфигурациях для этого есть штатные механизмы профилей «по умолчанию» в подсистеме доступа — автозаполнение группы доступа при создании пользователя настраивается без кода, через карточку профиля, поэтому дублировать это собственным обработчиком в типовой не нужно.
Почему роль не назначается: разбор причин
Если код отработал без ошибок, а прав у пользователя не прибавилось — почти всегда дело в одной из причин ниже.
Не пытайтесь «починить» типовую, очистив роли через Роли.Очистить() и выдав ПолныеПрава напрямую. В конфигурации на БСП это создаёт расхождение между платформенными ролями и группами доступа, и права начинают вести себя непредсказуемо. Работайте через штатную подсистему.
Производительность: массовые операции с пользователями
На базе с сотнями пользователей выдача ролей в лоб может идти долго. Несколько приёмов, которые реально ускоряют.
Не ищите пользователя в цикле. НайтиПоИмени внутри перебора — это повторные обращения к списку пользователей ИБ. Один раз постройте Соответствие имя → пользователь (пример выше) и берите из него.
Выполняйте массовую выдачу в фоновом задании. Долгую обработку запускайте через ФоновыеЗадания, чтобы не держать клиентский сеанс и не упираться в тайм-ауты. Пользователь при этом может продолжать работу.
Поднимайте привилегированный режим на сервере. Если логика гарантированно корректна и права проверены заранее, обёртка УстановитьПривилегированныйРежим(Истина) снимает лишние проверки доступа на каждой итерации:
УстановитьПривилегированныйРежим(Истина);
// массовая обработка пользователей
УстановитьПривилегированныйРежим(Ложь);
Привилегированный режим отключает контроль прав. Включайте его только в проверенном серверном коде и обязательно выключайте после блока. В клиентском коде он недоступен.
Не записывайте без необходимости. Проверяйте Роли.Содержит() перед Добавить() и вызывайте Записать() только если состав ролей реально изменился — лишние записи пользователя ИБ это самая дорогая часть операции.
Частые вопросы
Можно ли назначить роль по строковому имени, без Метаданные.Роли?
Роли.Добавить() ждёт объект метаданных. Но можно получить его по имени через Метаданные.НайтиПоПолномуИмени("Роль.ИмяРоли") и передать результат в Добавить(). Так удобно, когда имя роли приходит параметром.Как снять роль у всех пользователей сразу?
ПользователиИнформационнойБазы.ПолучитьПользователей(), для каждого вызовите Роли.Удалить(Метаданные.Роли.ИмяРоли) и Записать(). В типовой на БСП убирайте роль через профиль группы доступа, а не напрямую, иначе изменение не закрепится.Нужны ли права администратора, чтобы выдавать роли кодом?
ПользователиИнформационнойБазы требуют административных прав на информационную базу и выполняются на сервере. Из-под обычного пользователя без прав администрирования они завершатся ошибкой доступа.Почему после обновления типовой мои программно выданные роли исчезли?
Как проверить, какие роли уже есть у пользователя?
НайтиПоИмени) и переберите коллекцию Роли или используйте Роли.Содержит(Метаданные.Роли.ИмяРоли) для конкретной роли. Для типовой полную картину прав лучше смотреть через отчёт по правам доступа в разделе администрирования.