При разработке внешних печатных форм, отчетов и обработок часто возникает задача выборочного отображения информации в зависимости от прав текущего пользователя. Например, если у пользователя нет прав на просмотр определенного бизнес-процесса или документа, программа не должна выводить связанные с ним служебные надписи, даты или значения по умолчанию. Попытка реализовать такую проверку вызовом стандартной функции ПравоДоступа нередко приводит к синтаксическим ошибкам компиляции или некорректной логике работы. Разберем типичные ошибки, проанализируем синтаксис функции и рассмотрим наиболее эффективные способы решения этой задачи.
Посмотрим на исходный пример, в котором разработчик попытался проверить право на бизнес-процесс:
Если ПравоДоступа("Чтение", БизнесПроцессы.Исполнение, &ТекущийПользователь,) ТОГДА
ОбластьОставшиесяЗадачиФИОДаты.Параметры.ДатаПлановая = ?(ЗначениеЗаполнено(СтрокаДетальныеЗаписи.ДатаНачала),
Формат(СтрокаДетальныеЗаписи.ДатаНачала, "ДФ=dd.MM.yyyy"),
"Не определено");
КонецЕсли;
При попытке выполнить такой код платформа выдает ошибку синтаксического анализатора «Ожидается выражение». Выясним причину ее возникновения. В данном фрагменте допущены сразу три грубые ошибки:
& в теле метода: амперсанд во встроенном языке 1С используется исключительно для обозначения директив компиляции (например, &НаСервере) либо внутри текста запросов для передачи параметров (например, &ТекущийПользователь). В коде модулей обращение к переменным или функциям через амперсанд недопустимо и вызывает ошибку компиляции.,) воспринимается платформой как пропуск обязательного параметра следующего уровня, которого не существует в сигнатуре функции.БизнесПроцессы.Исполнение является менеджером бизнес-процесса. Функция ПравоДоступа вторым параметром принимает либо объект метаданных (Метаданные.БизнесПроцессы.Исполнение), либо конкретную ссылку на объект информационной базы.Проанализируем работу метода ПравоДоступа подробнее. Согласно синтакс-помощнику, метод имеет следующий синтаксис:
ПравоДоступа(<Право>, <Объект/Метаданные>, <Пользователь/Роль>, <СписокПараметров>)
Важные особенности использования параметров:
"Чтение", "Просмотр", "Добавление", "ИнтерактивноеДобавление").Администрирование), иначе платформа вызовет исключение нарушения прав доступа.Таким образом, для проверки права текущего пользователя на уровне метаданных правильный код выглядит следующим образом:
Если ПравоДоступа("Чтение", Метаданные.БизнесПроцессы.Исполнение) Тогда
ОбластьОставшиесяЗадачиФИОДаты.Параметры.ДатаПлановая = "ЕСТЬ ДОСТУП";
Иначе
ОбластьОставшиесяЗадачиФИОДаты.Параметры.ДатаПлановая = "НЕТ ДОСТУПА";
КонецЕсли;
Если в базе настроено ограничение прав на уровне записей (RLS), права на всю таблицу у пользователя могут быть, но доступ к конкретному бизнес-процессу или задаче может быть закрыт. В этом случае проверка через Метаданные... вернет Истина, а чтение самого объекта приведет к ошибке.
Для проверки доступа к конкретной записи передадим в метод ссылку на эту запись:
Если ПравоДоступа("Чтение", СтрокаДетальныеЗаписи.БизнесПроцесс) Тогда
// Заполняем область данными объекта
ОбластьОставшиесяЗадачиФИОДаты.Параметры.ДатаПлановая = Формат(СтрокаДетальныеЗаписи.ДатаНачала, "ДФ=dd.MM.yyyy");
Иначе
// Доступ ограничен на уровне записи
ОбластьОставшиесяЗадачиФИОДаты.Параметры.ДатаПлановая = "";
КонецЕсли;
Важное предупреждение: вызов функции ПравоДоступа в цикле при обходе строк выборки или таблицы приводит к серьезному снижению производительности, так как платформа на каждой итерации формирует отдельный служебный запрос к СУБД для проверки ограничений RLS. Разберем, как избежать этой проблемы.
Вместо того чтобы вручную проверять права для каждой строки выборки в коде, перенесем контроль прав непосредственно в запрос на выборку данных печатной формы. Конструкция ВЫБРАТЬ РАЗРЕШЕННЫЕ автоматически отсекает данные, на которые у пользователя нет прав по RLS.
Если исходная таблица соединяется через ЛЕВОЕ СОЕДИНЕНИЕ с таблицей бизнес-процессов или задач, то для недоступных пользователю записей все поля присоединенной таблицы вернут значение NULL. Посмотрим, как это обработать в коде:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| втЗадачи.Ссылка КАК ЗадачаСсылка,
| втЗадачи.ДатаНачала КАК ДатаНачала
|ИЗ
| втЗадачи КАК втЗадачи";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Если Выборка.ЗадачаСсылка = NULL Тогда
// У пользователя нет прав на чтение связанного объекта по RLS
ОбластьОставшиесяЗадачиФИОДаты.Параметры.ДатаПлановая = "";
Иначе
// Доступ есть, анализируем заполненность даты
Если ЗначениеЗаполнено(Выборка.ДатаНачала) Тогда
ОбластьОставшиесяЗадачиФИОДаты.Параметры.ДатаПлановая = Формат(Выборка.ДатаНачала, "ДФ=dd.MM.yyyy");
Иначе
ОбластьОставшиесяЗадачиФИОДаты.Параметры.ДатаПлановая = "Не определено";
КонецЕсли;
КонецЕсли;
КонецЦикла;
Такой подход решает проблему производительности за счет выполнения единого запроса к базе данных и исключает необходимость ручного вызова функций проверки прав в цикле.
В конфигурациях, использующих Библиотеку стандартных подсистем (например, «1С:Документооборот», «1С:ERP», «1С:Комплексная автоматизация»), для программной проверки прав рекомендуется использовать методы общего модуля УправлениеДоступом. Они корректно учитывают сложные механизмы политик доступа, рабочие группы и делегирование:
// Проверка права на объект метаданных
Если УправлениеДоступом.ЕстьПраво("Чтение", Метаданные.БизнесПроцессы.Исполнение) Тогда
// Действия при наличии прав
КонецЕсли;
// Проверка права на конкретную ссылку
Если УправлениеДоступом.ЕстьПраво("Чтение", СтрокаДетальныеЗаписи.СсылкаНаОбъект) Тогда
// Действия при наличии доступа к объекту
КонецЕсли;
Для массовой проверки списка ссылок в БСП предусмотрен метод УправлениеДоступом.ТаблицаПравДоступа, который позволяет проверить массив объектов за один пакетный вызов без лишней нагрузки на сервер.