При разработке внешних обработок для загрузки и проведения документов разработчики нередко сталкиваются с ситуацией: под пользователем с полными правами загрузка отрабатывает корректно, но стоит запустить ту же обработку пользователю с ограниченными правами, как система выдает ошибку вида:
Ошибка при вызове метода контекста (Записать)
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
по причине:
Не удалось провести: "Поступление наличных"!
При этом интерактивно, вручную через типовой интерфейс программы, документ под этим же пользователем создается и проводится абсолютно без проблем. Разберем по шагам, почему возникает эта ошибка, как работает безопасный режим и какими способами можно настроить корректное проведение документов.
Проанализируем детальный текст ошибки из системного журнала регистрации или контекста отладки. Зачастую в стеке вызовов при попытке записи документа появляется следующее исключение:
{ОбщийМодуль.ОбменДаннымиСобытия.Модуль(1233)}: Ошибка выполнения правил регистрации объектов для плана обмена ОбменЗарплата3Бухгалтерия3.
Описание ошибки:
{ОбщийМодуль.ОбменДаннымиВызовСервера.Модуль(644)}: Ошибка при получении значения атрибута контекста (ПравилаРегистрацииОбъектов)
Возврат ПараметрыСеанса.ПравилаРегистрацииОбъектов;
по причине:
Нарушение прав доступа!
Рассмотрим, какая цепочка событий приводит к нарушению прав доступа:
ПараметрыСеанса.ПравилаРегистрацииОбъектов.УстановитьПривилегированныйРежим(Истина) в модуле внешней обработки не дает результата: функция ПривилегированныйРежим() продолжает возвращать Ложь.Главная причина блокировки: согласно правилам безопасности платформы 1С:Предприятие, любой программный код, выполняющийся в безопасном режиме, лишен возможности повышать привилегии. Вызов метода УстановитьПривилегированныйРежим(Истина) в безопасном режиме платформой полностью игнорируется. Кроме того, если внешняя обработка запущена в безопасном режиме, свойство метаданных документа «Привилегированный режим при проведении» также подавляется.
Выясним, почему безопасный режим остается активным, даже если в функции СведенияОВнешнейОбработке() указана строка ПараметрыРегистрации.БезопасныйРежим = Ложь;:
Посмотрим на пример правильного оформления внешней обработки по стандартам БСП. Если обработка подключается через справочник «Дополнительные отчеты и обработки», в модуле объекта внешней обработки необходимо явно запросить требуемые разрешения в функции СведенияОВнешнейОбработке().
Рассмотрим фрагмент кода регистрации:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка();
ПараметрыРегистрации.Версия = "1.0";
ПараметрыРегистрации.БезопасныйРежим = Ложь;
// Запрашиваем разрешение на использование привилегированного режима
Разрешение = РаботаВБезопасномРежиме.РазрешениеНаИспользованиеПривилегированногоРежима(
НСтр("ru = 'Для проведения документов и регистрации изменений в планах обмена'")
);
ПараметрыРегистрации.Разрешения.Добавить(Разрешение);
// Добавление команд обработки
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = НСтр("ru = 'Загрузка документов из XML'");
НоваяКоманда.Идентификатор = "ЗагрузитьДокументы";
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы();
НоваяКоманда.ПоказыватьОповещение = Истина;
Возврат ПараметрыРегистрации;
КонецФункции
После внесения изменений выполним следующие шаги:
УстановитьПривилегированныйРежим(Истина) при вызове команд через интерфейс конфигурации.Если внешняя обработка вызывается программно из другой процедуры или формы, проанализируем синтаксис метода ВнешниеОбработки.Создать(). Второй параметр этого метода напрямую управляет безопасным режимом:
ВнешняяОбработкаОбъект = ВнешниеОбработки.Создать(ПолноеИмяФайла, Ложь);
ВнешняяОбработкаОбъект.ОбработатьДанные(ДокументОбъект);
Передавая Ложь вторым параметром, мы отключаем безопасный режим для создаваемого экземпляра обработки, что позволит коду внутри нее повышать привилегии при записи объектов.
Если регламент предприятия исключает работу с дополнительными обработками или требуется регулярное интерактивное открытие файла пользователями без админ-прав, перенесем логику в расширение конфигурации (файл с расширением .cfe):
Код, выполняемый в контексте расширения с отключенным безопасным режимом, обладает теми же правами, что и код основной конфигурации, и команда УстановитьПривилегированныйРежим(Истина) будет отрабатывать штатно.
Если конфигурация снята с полной поддержки и допускает внесение изменений, рассмотрим наиболее надежный архитектурный вариант — делегирование записи документа конфигурации:
Привилегированный.
Процедура ЗаписатьДокументВПривилегированномРежиме(ДокументОбъект) Экспорт
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
КонецПроцедуры
ДокументОбъект.Записать(...) вызываем созданную процедуру привилегированного общего модуля. Так как модуль является привилегированным изначально, обращение к ПараметрыСеанса.ПравилаРегистрацииОбъектов пройдет без ошибки прав доступа даже при вызове из безопасного контекста.