Роли пользователя в коде 1С: поиск, добавление и запись с проверками

· 9 мин

Содержание

Чтобы установить роль пользователю в 1С программно, найдите пользователя через ПользователиИнформационнойБазы.НайтиПоИмени(), добавьте в его коллекцию Роли объект Метаданные.Роли.ИмяРоли и вызовите Записать(). Код выполняется только на сервере и под пользователем с правом «Администрирование» или в привилегированном режиме.

Есть одна ловушка. В типовых конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11) роли напрямую не назначают: их раздаёт подсистема управления доступом через профили и группы доступа. Роль, добавленная мимо неё, пропадёт при ближайшем пересчёте ролей. Ниже оба варианта: для своей конфигурации без БСП и для типовой.

Как в 1С устроены роли и права пользователей

Роль — это объект метаданных конфигурации. В ней записан набор прав: чтение, добавление, изменение, проведение и так далее для каждого справочника, документа, регистра. Плюс общие права: «Администрирование», «Тонкий клиент», «Внешнее соединение».

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

Что из этого можно менять кодом, а что нельзя:

ДействиеВ режиме «Предприятие» кодомГде делается
Создать новую роль❌ нельзяКонфигуратор или расширение
Изменить права внутри роли❌ нельзяКонфигуратор или расширение
Получить список ролей✅ даМетаданные.Роли
Назначить роль пользователю✅ даПользовательИБ.Роли.Добавить()
Снять роль с пользователя✅ даПользовательИБ.Роли.Удалить()
Создать пользователя ИБ✅ даПользователиИнформационнойБазы.СоздатьПользователя()

Права пользователя складываются из всех его ролей. Если хотя бы одна роль разрешает действие, оно доступно. Запретить что-то «ролью-запретом» нельзя: роли только добавляют права.

Ограничения на уровне записей (RLS) живут внутри ролей. Поэтому назначение роли сразу включает и её ограничения.

Отсюда практическое правило: выдавать права точечно, набором маленьких ролей под задачу, а не одной большой ролью «на всё». Тогда снять доступ к одному участку можно одной строкой кода, не задев остальное.

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

Код работы с пользователями падает чаще всего не из-за ошибок в алгоритме, а из-за неправильного окружения. Проверьте четыре вещи.

1. Контекст выполнения — сервер

Менеджер ПользователиИнформационнойБазы на клиенте недоступен. Код размещайте:

  • 📦 в общем модуле с флагом «Сервер» (без «Клиент»);
  • 📝 в модуле формы в процедуре с директивой &НаСервере или &НаСервереБезКонтекста;
  • 🔌 во внешней обработке — в модуле объекта, который вызывается с сервера.

При работе через COM-соединение или внешнее соединение действует тот же программный интерфейс, контекст уже серверный.

2. Права того, кто запускает

Изменять пользователей может только тот, у кого есть право «Администрирование» на конфигурацию. Проверка в коде:

Если Не ПравоДоступа("Администрирование", Метаданные) Тогда
    ВызватьИсключение "Недостаточно прав для изменения пользователей.";
КонецЕсли;

3. Привилегированный режим

Если код должен работать от имени рядового пользователя (например, регламентное задание или обработка выдачи доступа менеджерам), включите привилегированный режим на время операции:

УстановитьПривилегированныйРежим(Истина);
// ... работа с пользователями ...
УстановитьПривилегированныйРежим(Ложь);

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

4. Есть ли в конфигурации БСП

Откройте любую типовую конфигурацию : если в разделе Администрирование → Настройки пользователей и прав есть «Профили групп доступа» и «Группы доступа», в базе работает подсистема управления доступом БСП. Тогда смотрите раздел про типовые конфигурации ниже, а не только базовый код.

Перед запуском кода
Выполнено: 0 / 5

Если нужной роли нет: создание и настройка в конфигураторе

Программно создать роль во время работы базы нельзя. Роль появляется только при изменении метаданных. Два пути.

Через конфигуратор

  1. Откройте конфигурацию: Конфигурация → Открыть конфигурацию.
  2. В дереве метаданных найдите ветку Общие → Роли, через контекстное меню добавьте новую роль.
  3. Задайте имя латиницей или кириллицей без пробелов, например ОтветственныйЗаСклад. Именно его потом указывают в коде.
  4. На закладке прав отметьте нужные объекты и действия. Для общих прав выделите корень дерева — саму конфигурацию.
  5. Сохраните и выполните Конфигурация → Обновить конфигурацию базы данных.

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

Через расширение конфигурации

Расширения (с платформы 8.3.6) позволяют добавить свою роль, не трогая основную конфигурацию. Роль расширения видна в Метаданные.Роли после подключения расширения, и её можно назначать тем же кодом.

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

Чтобы новая роль была доступна для назначения, расширение должно быть подключено к базе и активно. Иначе Метаданные.Роли.Найти() вернёт Неопределено.

Поиск ролей и пользователей: работа с коллекциями

Найти роль по имени

Обращение Метаданные.Роли.ПолныеПрава упадёт с ошибкой, если роли с таким именем нет. Для имени из строки безопаснее метод Найти():

РольМД = Метаданные.Роли.Найти("ОтветственныйЗаСклад");
Если РольМД = Неопределено Тогда
    ВызватьИсключение "Роль ОтветственныйЗаСклад не найдена в конфигурации.";
КонецЕсли;

Вывести все роли конфигурации

Для Каждого РольМД Из Метаданные.Роли Цикл
    Сообщить(РольМД.Имя + " — " + РольМД.Синоним);
КонецЦикла;

Имя нужно для кода, Синоним — то, что видит администратор в списке пользователей.

Найти пользователя

У менеджера ПользователиИнформационнойБазы есть три способа:

  • 🔎 НайтиПоИмени("Иванов") — по имени для входа (не по полному имени);
  • 🆔 НайтиПоУникальномуИдентификатору(УИД) — по идентификатору, надёжно при переименовании;
  • 📋 ПолучитьПользователей() — массив всех пользователей базы.

Оба метода поиска возвращают Неопределено, если пользователь не найден. Проверяйте это всегда.

Узнать роли пользователя и наличие конкретной роли

ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени("Иванов");
Для Каждого РольМД Из ПользовательИБ.Роли Цикл
    Сообщить(РольМД.Имя);
КонецЦикла;

ЕстьРоль = ПользовательИБ.Роли.Содержит(Метаданные.Роли.ПолныеПрава);

Для текущего сеанса есть короткий путь: РольДоступна("ИмяРоли"). Он проверяет роли того, кто сейчас работает в программе.

Кто в базе имеет нужную роль

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

Как назначить роль пользователю программно: готовый код

Базовый вариант для конфигурации без БСП

Функция в общем серверном модуле. Возвращает Истина, если роль добавлена, и Ложь, если она уже была.

Функция НазначитьРольПользователю(ИмяПользователя, ИмяРоли) Экспорт

    ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователя);
    Если ПользовательИБ = Неопределено Тогда
        ВызватьИсключение СтрШаблон("Пользователь ""%1"" не найден.", ИмяПользователя);
    КонецЕсли;

    РольМД = Метаданные.Роли.Найти(ИмяРоли);
    Если РольМД = Неопределено Тогда
        ВызватьИсключение СтрШаблон("Роль ""%1"" не найдена.", ИмяРоли);
    КонецЕсли;

    Если ПользовательИБ.Роли.Содержит(РольМД) Тогда
        Возврат Ложь;
    КонецЕсли;

    ПользовательИБ.Роли.Добавить(РольМД);
    ПользовательИБ.Записать();
    Возврат Истина;

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

Пока не вызван Записать(), изменения живут только в памяти. Если забыть эту строку, код отработает без ошибок, а роль не появится.

Снять роль

ПользовательИБ.Роли.Удалить(Метаданные.Роли.ОтветственныйЗаСклад);
ПользовательИБ.Записать();

Метод Очистить() снимает все роли разом. Применяйте его только если сразу после него добавляете новый набор.

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

Процедура НазначитьРольСписку(МассивИмен, ИмяРоли) Экспорт

    РольМД = Метаданные.Роли.Найти(ИмяРоли);
    Если РольМД = Неопределено Тогда
        ВызватьИсключение СтрШаблон("Роль ""%1"" не найдена.", ИмяРоли);
    КонецЕсли;

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

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

Создать пользователя сразу с ролью

Если пользователя ещё нет, его создают и наполняют ролями до первой записи:

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

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

Когда новая роль начнёт действовать

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

Вариант для типовых конфигураций на БСП

В БП 3.0, ЗУП 3.1, УТ 11 роли пользователю выдаёт подсистема управления доступом. Схема такая:

  • 🧩 профиль группы доступа — набор ролей («Бухгалтер», «Кладовщик»);
  • 👥 группа доступа — профиль плюс список участников и, при необходимости, ограничения;
  • 👤 пользователь — элемент справочника Пользователи, связанный с пользователем ИБ.

Правильный программный путь — добавить пользователя в группу доступа и записать её. При записи подсистема сама пересчитает роли участников.

Процедура ДобавитьВГруппуДоступа(ПользовательСсылка, НаименованиеГруппы) Экспорт

    ГруппаСсылка = Справочники.ГруппыДоступа.НайтиПоНаименованию(НаименованиеГруппы, Истина);
    Если ГруппаСсылка.Пустая() Тогда
        ВызватьИсключение СтрШаблон("Группа доступа ""%1"" не найдена.", НаименованиеГруппы);
    КонецЕсли;

    ГруппаОбъект = ГруппаСсылка.ПолучитьОбъект();
    Если ГруппаОбъект.Пользователи.Найти(ПользовательСсылка, "Пользователь") <> Неопределено Тогда
        Возврат;
    КонецЕсли;

    НоваяСтрока = ГруппаОбъект.Пользователи.Добавить();
    НоваяСтрока.Пользователь = ПользовательСсылка;
    ГруппаОбъект.Записать();

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

Если в базе включена упрощённая настройка прав (профили отмечаются флажками прямо в карточке пользователя по кнопке «Права доступа »), группы доступа создаются под каждого пользователя автоматически. Там проще назначить профиль через карточку, а в коде опираться на экспортные процедуры общего модуля УправлениеДоступом вашей версии БСП.

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

Ошибки при назначении ролей и журнал регистрации

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

Попытка
    Добавлена = НазначитьРольПользователю(ИмяПользователя, ИмяРоли);
    Если Добавлена Тогда
        ЗаписьЖурналаРегистрации("Права.НазначениеРоли",
            УровеньЖурналаРегистрации.Информация, , ,
            СтрШаблон("Пользователю %1 назначена роль %2", ИмяПользователя, ИмяРоли));
    КонецЕсли;
Исключение
    ЗаписьЖурналаРегистрации("Права.НазначениеРоли",
        УровеньЖурналаРегистрации.Ошибка, , ,
        ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    ВызватьИсключение;
КонецПопытки;

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

Своё имя события («Права.НазначениеРоли») удобно для отбора. Найти записи можно в Администрирование → Обслуживание → Журнал регистрации или в конфигураторе через Администрирование → Журнал регистрации, отбор по событию.

Если привилегированный режим включался в начале процедуры, выключайте его и в ветке Исключение. Иначе он останется включённым до конца серверного вызова.

Диагностика: выберите симптом

Частые вопросы

Можно ли создать роль программно в режиме «Предприятие»?
Нет. Роль — объект метаданных, она создаётся только в конфигураторе или в расширении. Кодом можно лишь назначать существующие роли.
Как дать права временно, на одну операцию?
Роль для этого не нужна. Выполните операцию на сервере в привилегированном режиме и выключите его сразу после.
Работает ли этот код в файловой базе?
Да. Менеджер пользователей и коллекция ролей одинаковы для файлового и клиент-серверного варианта, код выполняется в серверном контексте в обоих случаях.
Чем РольДоступна() отличается от Роли.Содержит()?
РольДоступна() проверяет роли текущего сеанса. Роли.Содержит() проверяет сохранённые роли любого пользователя ИБ, в том числе того, кто сейчас не в программе.
Можно ли назначить роль через COM-соединение из другой программы?
Да, через внешнее соединение доступны те же ПользователиИнформационнойБазы и Метаданные.Роли. Подключаться нужно под пользователем с правом «Администрирование».