В процессе разработки или аудита безопасности в системе 1С:Предприятие часто возникает задача программно определить, какие роли обладают специфическими «глобальными» правами, такими как «Администрирование», «Журнал регистрации» или «Интерактивное открытие внешних обработок». На первый взгляд кажется, что для этого достаточно простого вызова одной функции, однако на практике разработчики сталкиваются с тем, что система возвращает неожиданные результаты или вовсе выдает ошибку.
В этой статье мы подробно разберем, как работает механизм проверки прав, почему стандартные методы могут вводить в заблуждение и какими способами можно действительно «заглянуть» внутрь конкретной роли.
Основной инструмент разработчика для проверки полномочий — это функция ПравоДоступа(). Давайте проанализируем её синтаксис:
ПравоДоступа(<Право>, <Объект>, <Пользователь>, <Параметры>)
Многие начинающие разработчики совершают типичную ошибку: пытаются в качестве второго параметра (Объект) передать саму роль из метаданных. Рассмотрим некорректный пример:
// ОШИБОЧНЫЙ ПОДХОД
Для Каждого ТекРоль Из Метаданные.Роли Цикл
Если ПравоДоступа("Администрирование", ТекРоль) Тогда
// Этот код не будет работать так, как ожидается
КонецЕсли;
КонецЦикла;
Выясним причину ошибки: функция ПравоДоступа() проверяет наличие права на объект. Если вы передаете в неё объект метаданных Роль, система пытается проверить, есть ли у текущего пользователя право манипулировать самой ролью (как объектом конфигурации), а не наличие галочки «Администрирование» внутри этой роли. Более того, право «Администрирование» не относится к объекту «Роль».
Такие права, как «Администрирование», «Журнал регистрации» или «Вывод», называются правами на конфигурацию. Они не привязаны к справочникам или документам, они действуют на всю информационную базу в целом. Для их проверки в качестве объекта необходимо указывать корень метаданных.
Рассмотрим правильный пример проверки глобального права для текущего пользователя:
// ПРАВИЛЬНЫЙ ПОДХОД ДЛЯ ГЛОБАЛЬНЫХ ПРАВ
Если ПравоДоступа("Администрирование", Метаданные) Тогда
Сообщить("У вас есть права администратора");
КонецЕсли;
Однако здесь мы сталкиваемся с главным ограничением: метод ПравоДоступа() возвращает результат для совокупности всех ролей пользователя. Если у пользователя назначено 20 ролей, и хотя бы в одной из них есть искомое право, функция вернет Истина. Она не позволяет изолированно проверить одну конкретную роль, если она не является единственной у пользователя.
Проанализируем еще один важный нюанс, упомянутый в документации и на форумах. Если ваш код выполняется в привилегированном режиме (например, в серверном модуле с соответствующей галочкой или внутри конструкции УстановитьПривилегированныйРежим(Истина)), функция ПравоДоступа() всегда будет возвращать Истина.
Это происходит потому, что привилегированный режим создан для обхода проверок прав доступа. Если вам нужно выполнить проверку именно в таком модуле, необходимо временно отключить этот режим:
УстановитьПривилегированныйРежим(Ложь);
Доступно = ПравоДоступа("Администрирование", Метаданные);
УстановитьПривилегированныйРежим(Истина);
Если задача стоит именно так: «Найти все роли в конфигурации, где включено право Администрирование», то стандартный метод ПравоДоступа() нам не поможет. В платформе 1С нет прямого метода метаданных вроде Роль.СодержитПраво("Администрирование").
Рассмотрим два основных способа решения этой задачи:
Если ваша конфигурация построена на базе БСП (что верно для большинства современных решений, таких как ERP, УТ 11, БП 3.0), задача упрощается. БСП хранит информацию о правах ролей в специальных регистрах сведений для ускорения работы системы — есть готовый аналитический отчет по правам доступа в конфигурациях на БСП.
Посмотрим на пример запроса к регистру ПраваРолей (название может незначительно отличаться в разных версиях БСП):
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПраваРолей.Роль
|ИЗ
| РегистрСведений.ПраваРолей КАК ПраваРолей
|ГДЕ
| ПраваРолей.ИмяПрава = &ИмяПрава
| И ПраваРолей.ОбъектМетаданных = &Объект";
Запрос.УстановитьПараметр("ИмяПрава", "Администрирование");
// Для глобальных прав в БСП часто используется пустая ссылка или специальное значение
Запрос.УстановитьПараметр("Объект", "Конфигурация");
РезультатЗапроса = Запрос.Выполнить();
Важно: Данные в этот регистр попадают при обновлении информационной базы. Это самый быстрый и правильный способ анализа прав в типовых конфигурациях — для этого подойдёт отчет для детального анализа прав и ролей на базе БСП.
Для конфигураций, где БСП не используется, или для целей внешнего аудита, используется метод анализа файлов метаданных. Каждая роль при выгрузке конфигурации в XML-файлы представляет собой текстовый файл, где права описаны в явном виде.
Процесс выглядит так:
Конфигурация -> Выгрузить конфигурацию в файлы....Roles.<name>Administration</name> и проверяем значение связанного тега <value>true</value>.Хотя этот метод нельзя назвать «быстрым программным доступом в рантайме», он является единственным абсолютно точным способом узнать настройки роли без привязки к конкретному пользователю или сеансу.
Подведем итоги нашего анализа:
ПравоДоступа("ИмяПрава", Метаданные).ПравоДоступа(), если хотите проверить внутренние разрешения этой роли.Истина.Понимание того, что право доступа всегда привязано к объекту (даже если этот объект — вся Конфигурация), поможет вам избежать ошибок при проектировании систем безопасности и разграничения прав доступа.