Текущий пользователь 1С во встроенном языке, запросах и СКД
Содержание
Текущего пользователя в 1С получают тремя способами. Имя строкой даёт функция ИмяПользователя(). Объект пользователя информационной базы — ПользователиИнформационнойБазы.ТекущийПользователь(). Ссылку на элемент справочника «Пользователи» в типовых конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11) возвращает Пользователи.ТекущийПользователь().
Какой из них брать, зависит от задачи. Для подписи в отчёте хватит строки. Для отбора документов по полю «Ответственный» нужна ссылка на справочник. Для проверки ролей и способа входа — объект пользователя ИБ. Всё ниже относится к платформе 1С:Предприятие 8.3 и не зависит от конкретной конфигурации, кроме мест, где упомянута БСП.
Функции глобального контекста и объект текущего пользователя
Платформа даёт несколько готовых средств. Сведём их в таблицу.
| Что нужно | Чем получить | Где работает | Что вернёт |
|---|---|---|---|
| Имя для входа | ИмяПользователя() | клиент и сервер | строка, например Иванова |
| Полное имя | ПолноеИмяПользователя() | клиент и сервер | строка, например Иванова Мария Петровна |
| Объект пользователя ИБ | ПользователиИнформационнойБазы.ТекущийПользователь() | сервер, толстый клиент | ПользовательИнформационнойБазы |
| Данные сеанса | ПолучитьТекущийСеансИнформационнойБазы() | сервер | СеансИнформационнойБазы |
| Ссылка на справочник (БСП) | Пользователи.ТекущийПользователь() | сервер | СправочникСсылка.Пользователи |
Простейший пример — вывести имя на клиенте:
&НаКлиенте
Процедура ПоказатьПользователя(Команда)
Сообщить("Вы вошли как: " + ПолноеИмяПользователя());
КонецПроцедуры
Если в базе нет ни одного пользователя, обе функции возвращают пустую строку. Это нормальная ситуация для демо- и тестовых баз.
Что есть у объекта ПользовательИнформационнойБазы
Объект даёт больше, чем имя. Полезные свойства:
- 🆔
УникальныйИдентификатор— не меняется при переименовании, по нему надёжно связывать данные; - 👤
ИмяиПолноеИмя— то же, что возвращают функции глобального контекста; - 🔐
Роли— коллекция назначенных ролей; - 🪪
АутентификацияСтандартная,АутентификацияОС— какие способы входа разрешены; - 💻
ПользовательОС— учётная запись Windows, привязанная к пользователю, в виде\\ДОМЕН\логин; - 🌐
Язык— язык интерфейса пользователя.
&НаСервере
Функция ОписаниеТекущегоПользователя()
ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Возврат СтрШаблон("%1 (%2), вход через ОС: %3",
ПользовательИБ.ПолноеИмя,
Строка(ПользовательИБ.УникальныйИдентификатор),
?(ПользовательИБ.АутентификацияОС, "да", "нет"));
КонецФункции
Менеджер ПользователиИнформационнойБазы недоступен в тонком клиенте и веб-клиенте. Вызов из процедуры с директивой &НаКлиенте даёт ошибку Переменная не определена (ПользователиИнформационнойБазы). Переносите код в серверную процедуру формы или в общий модуль с флагом «Вызов сервера».
Сведения о сеансе
Иногда важен не сам пользователь, а его подключение: с какого компьютера он зашёл, через какой клиент, когда начал работу. Для этого есть объект сеанса:
&НаСервере
Процедура ВывестиДанныеСеанса()
Сеанс = ПолучитьТекущийСеансИнформационнойБазы();
Сообщить("Компьютер: " + Сеанс.ИмяКомпьютера);
Сообщить("Приложение: " + Сеанс.ИмяПриложения);
Сообщить("Начало сеанса: " + Формат(Сеанс.НачалоСеанса, "ДЛФ=DT"));
КонецПроцедуры
Номер сеанса отдельно возвращает НомерСеансаИнформационнойБазы(). Удобно для журналов и диагностики, когда один пользователь открыл два окна.
Имя компьютера доступно и без объекта сеанса: функция ИмяКомпьютера() работает и на клиенте, и на сервере. Учтите, что на сервере она вернёт имя сервера 1С, а не рабочего места пользователя. Для имени рабочего места в клиент-серверном варианте берите ИмяКомпьютера из сеанса.
Пользователь ИБ, элемент справочника и учётная запись Windows
Здесь путаются чаще всего. В 1С 8.3 живут три разных «пользователя».
- Пользователь информационной базы. Его хранит платформа. Видно в Конфигураторе:
Администрирование → Пользователи. У него логин, пароль, роли. - Элемент справочника «Пользователи». Это данные конфигурации. Именно на него ссылаются реквизиты «Ответственный», «Автор», «Менеджер» в документах. В БСП элемент связан с пользователем ИБ через реквизит
ИдентификаторПользователяИБ. - Пользователь операционной системы. Учётная запись Windows, под которой запущен клиент. С пользователем ИБ связан только при входе через аутентификацию ОС.
Ссылка на справочник в типовой конфигурации
В конфигурациях на БСП правильный путь — программный интерфейс подсистемы «Пользователи»:
&НаСервере
Процедура ЗаполнитьОтветственного()
Объект.Ответственный = Пользователи.ТекущийПользователь();
КонецПроцедуры
Тот же вызов есть на клиенте: ПользователиКлиент.ТекущийПользователь(). Он берёт значение из параметров, которые клиент получил при старте, и не делает лишний серверный вызов.
Если в базе есть внешние пользователи (например, личный кабинет контрагента), Пользователи.ТекущийПользователь() при их входе вызывает исключение. Для универсального кода есть Пользователи.АвторизованныйПользователь(): он вернёт ссылку либо на «Пользователи», либо на «Внешние пользователи».
Связь в обратную сторону
Когда на руках ссылка на справочник, а нужен объект платформы:
&НаСервере
Функция ПользовательИБПоСсылке(СсылкаНаПользователя)
Ид = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаНаПользователя, "ИдентификаторПользователяИБ");
Возврат ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(Ид);
КонецФункции
Метод вернёт Неопределено, если у элемента нет пользователя ИБ: например, это сотрудник, которому не дали права входа.
Не ищите элемент справочника по наименованию через НайтиПоНаименованию(ИмяПользователя()). Имя для входа и наименование элемента часто расходятся, а однофамильцы ломают поиск. Связывайте по уникальному идентификатору.
Логин Windows
Узнать учётную запись ОС на клиенте Windows можно через COM-объект:
&НаКлиенте
Функция ЛогинWindows()
Сеть = Новый COMОбъект("WScript.Network");
Возврат Сеть.UserDomain + "\" + Сеть.UserName;
КонецФункции
Код работает только на Windows и не работает
в веб-клиенте. Если пользователь входит через аутентификацию ОС, надёжнее брать свойство ПользовательОС у объекта пользователя ИБ на сервере.
Текущий пользователь в запросах и СКД
В языке запросов нет функции «текущий пользователь». Значение передают параметром.
Обычный запрос
&НаСервере
Функция МоиНепроведённыеДокументы()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Реализация.Ссылка,
| Реализация.Дата
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ
| Реализация.Ответственный = &ТекущийПользователь
| И НЕ Реализация.Проведен";
Запрос.УстановитьПараметр("ТекущийПользователь", Пользователи.ТекущийПользователь());
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Параметр — ссылка на справочник, а не строка имени. Сравнение по ссылке работает по индексу и не ломается при смене ФИО.
Динамический список
Для списка на форме параметр задают при создании:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Список.Параметры.УстановитьЗначениеПараметра("ТекущийПользователь",
Пользователи.ТекущийПользователь());
КонецПроцедуры
В тексте запроса списка (включён флаг «Произвольный запрос») условие то же: ГДЕ Таблица.Ответственный = &ТекущийПользователь.
Отчёт на СКД
В схеме компоновки параметр ТекущийПользователь появится автоматически, как только он встретится в тексте набора данных. Заполнить его проще всего в модуле объекта отчёта:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра(
"ТекущийПользователь", Пользователи.ТекущийПользователь());
КонецПроцедуры
Чтобы пользователь не подменил значение в настройках, на закладке «Параметры» схемы снимите у параметра флаг доступности в пользовательских настройках.
Отбор в отчёте — не защита данных. Пользователь с правом на конфигуратор или на консоль запросов увидит всё. Если чужие документы показывать нельзя, нужны ограничения доступа на уровне записей (RLS), а не параметр в запросе.
Фоновые задания, регламентные задания и внешние обработки
Кто «текущий пользователь» внутри фонового кода — зависит от того, как код запущен.
| Как запущен код | Под каким пользователем выполняется |
|---|---|
ФоновыеЗадания.Выполнить() из сеанса пользователя | под тем же пользователем, что запустил задание |
| Регламентное задание с заполненным свойством «Пользователь» | под указанным пользователем |
| Регламентное задание без пользователя | имя может быть пустым, проверяйте это явно |
| Внешняя обработка, открытая пользователем | под пользователем, который её открыл |
| Внешнее соединение (COM) | под пользователем из строки соединения |
Фоновое задание помнит, кто его запустил
Длительная операция, запущенная кнопкой, работает с правами нажавшего. ИмяПользователя() внутри вернёт его имя, Пользователи.ТекущийПользователь() — его ссылку. Передавать пользователя параметром не нужно.
Но если задание запускают от имени одного пользователя для другого (например, менеджер ставит рассылку для отдела), передавайте адресата параметром процедуры. Текущий пользователь в фоне — это всегда тот, кто запустил.
Регламентные задания
Регламентному заданию пользователь назначается в его свойствах. В типовых конфигурациях это делается через Администрирование → Обслуживание → Регламентные операции → Регламентные и фоновые задания, в карточке задания. Если пользователь не указан, рассчитывать на заполненное имя нельзя.
Защитный код в процедуре задания:
Процедура ОтправитьНапоминания() Экспорт
Если ПустаяСтрока(ИмяПользователя()) Тогда
ЗаписьЖурналаРегистрации("Напоминания",
УровеньЖурналаРегистрации.Предупреждение, , ,
"Задание запущено без пользователя, отправка пропущена");
Возврат;
КонецЕсли;
// основная логика
КонецПроцедуры
Внешние обработки
Внешняя обработка не получает никаких особых прав. Она работает под пользователем, который её открыл, и видит только то, что разрешают его роли.
Если обработка подключена через справочник «Дополнительные отчёты и обработки» в безопасном режиме, включить привилегированный режим из неё нельзя. Код, который рассчитывает обойти права через УстановитьПривилегированныйРежим(Истина), в ней не сработает.
Проверка ролей и прав текущего пользователя
Получить пользователя обычно нужно, чтобы решить: показывать ли кнопку, разрешать ли действие. Для этого есть готовые функции, перебирать роли вручную не нужно.
Платформенные функции
- ✅
РольДоступна("ПолныеПрава")— назначена ли роль текущему пользователю. Можно передать объект метаданных:РольДоступна(Метаданные.Роли.ПолныеПрава). - ✅
ПравоДоступа("Изменение", Метаданные.Документы.РеализацияТоваровУслуг)— есть ли у пользователя право на объект, с учётом всех его ролей.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
МожноМенять = ПравоДоступа("Изменение", Метаданные.Справочники.Номенклатура);
Элементы.ФормаЗаписатьИЗакрыть.Доступность = МожноМенять;
КонецПроцедуры
ПравоДоступа предпочтительнее РольДоступна. Проверка конкретной роли ломается, когда администратор выдаёт те же права другой ролью или профилем групп доступа. Проверка права — нет.
Функции БСП
В типовых конфигурациях есть обёртки, которые учитывают устройство профилей:
- 🛡️
Пользователи.ЭтоПолноправныйПользователь()— у пользователя полные права; - 🛡️
Пользователи.РолиДоступны("ДобавлениеИзменениеНоменклатуры, ПолныеПрава")— доступна хотя бы одна из перечисленных ролей.
Обе выполняются на сервере. Имена ролей в типовых меняются от релиза к релизу, поэтому перед использованием сверьте их в Конфигураторе, в ветке «Общие → Роли».
Список ролей пользователя
Для отладки или журнала можно вывести все роли:
&НаСервере
Функция РолиТекущегоПользователя()
Результат = Новый Массив;
Для Каждого Роль Из ПользователиИнформационнойБазы.ТекущийПользователь().Роли Цикл
Результат.Добавить(Роль.Имя);
КонецЦикла;
Возврат СтрСоединить(Результат, ", ");
КонецФункции
Типичные ошибки и безопасный код
Эти ошибки регулярно всплывают при проверке чужих доработок.
1. Права определяют по имени пользователя. Конструкция Если ИмяПользователя() = "Администратор" выглядит просто, но переименование или второй администратор её ломают. Кроме того, имя — не секрет. Проверяйте права через ПравоДоступа или роли.
2. Привилегированный режим включают без нужды. Под УстановитьПривилегированныйРежим(Истина) код игнорирует права и RLS. Включайте его только на конкретную операцию и выключайте сразу после:
УстановитьПривилегированныйРежим(Истина);
Значение = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка, "Ответственный");
УстановитьПривилегированныйРежим(Ложь);
Проверить, включён ли режим, можно функцией ПривилегированныйРежим(). Привилегированный режим не меняет пользователя: ИмяПользователя() возвращает то же имя.
3. Данные пользователя таскают с сервера при каждом действии. Каждый вызов &НаСервере из клиентской команды — обращение по сети. Получите ссылку и нужные флаги один раз в ПриСозданииНаСервере, сохраните в реквизиты формы и используйте на клиенте.
4. Текущего пользователя кешируют в общем модуле с повторным использованием на весь сеанс без учёта внешних пользователей. Если в базе есть внешние пользователи, кеш вернёт исключение при первом же их входе. Используйте Пользователи.АвторизованныйПользователь() или проверку Пользователи.ЭтоСеансВнешнегоПользователя().
5. Ответственного подставляют при каждой записи. Код Объект.Ответственный = Пользователи.ТекущийПользователь() в ПередЗаписью перезапишет автора, как только документ откроет и сохранит коллега. Заполняйте реквизит только для нового объекта: проверяйте ЭтоНовый() или пустое значение поля.
6. Пустая база без пользователей. Пока в Конфигураторе не создан ни один пользователь, ИмяПользователя() возвращает пустую строку, а проверки прав пропускают всё. Создайте хотя бы одного пользователя с полными правами, прежде чем тестировать ограничения.
Как узнать текущего пользователя без программирования?
Администрирование → Активные пользователи. В режиме 1С:Предприятие в типовых конфигурациях откройте раздел Администрирование и найдите ссылку «Активные пользователи» — там список текущих сеансов с именами и компьютерами.Можно ли получить текущего пользователя в правилах RLS?
ТекущийПользователь заполняется при входе, а шаблоны ограничений обращаются к нему как к &ТекущийПользователь.Почему ИмяПользователя() и ПолноеИмяПользователя() возвращают разное?
Как получить пользователя, который создал документ?
Работает ли Пользователи.ТекущийПользователь() в нетиповой конфигурации?
ПользователиИнформационнойБазы.ТекущийПользователь() и свой справочник с реквизитом-идентификатором.