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