Разберем одну из самых коварных ошибок, с которой сталкиваются разработчики при написании внешних обработок в системе «1С:Предприятие 8.3». Ситуация выглядит парадоксально: пользователь обладает всеми необходимыми правами, он может вручную открыть документ и провести его без каких-либо предупреждений, однако та же самая операция, инициированная программно из внешней обработки, завершается аварией с сообщением «Нарушение прав доступа!».
Проанализируем технические причины этого поведения и рассмотрим пошаговое руководство по устранению проблемы.
Основная причина кроется в механизме защиты платформы. Когда мы открываем внешнюю обработку через меню «Файл — Открыть», система по умолчанию запускает её в так называемом безопасном режиме. Это специальное состояние окружения, в котором возможности программного кода существенно ограничены ради безопасности данных.
Рассмотрим подробнее, что происходит внутри системы:
УстановитьПривилегированныйРежим(Истина). Это позволяет коду временно игнорировать проверку прав доступа и выполнять записи в защищенные регистры.УстановитьПривилегированныйРежим(Истина) игнорируется платформой. Система делает вид, что режим включен, но фактического повышения прав не происходит.В результате, когда код проведения документа пытается записать движения в «закрытый» для пользователя регистр, платформа выбрасывает исключение «Нарушение прав доступа», так как привилегированный режим не сработал.
Часто разработчики пытаются решить проблему «в лоб», добавляя включение режима непосредственно в обработку:
Процедура ВыполнитьПроведениеНаСервере(СсылкаНаДокумент)
// Попытка включить привилегированный режим во внешней обработке
УстановитьПривилегированныйРежим(Истина);
ОбъектДок = СсылкаНаДокумент.ПолучитьОбъект();
Попытка
ОбъектДок.Записать(РежимЗаписиДокумента.Проведение);
Исключение
Сообщить(ОписаниеОшибки()); // Здесь возникнет "Нарушение прав доступа"
КонецПопытки;
КонецПроцедуры
Как мы уже выяснили, если обработка открыта через Файл — Открыть, этот код не поможет. Чтобы исправить это, нам нужно изменить контекст исполнения обработки.
Это самый правильный и рекомендуемый путь для современных конфигураций на базе БСП (Библиотеки стандартных подсистем). Вместо прямого открытия файла, обработку следует зарегистрировать в системе.
Проанализируем алгоритм действий:
СведенияОВнешнейОбработке().БезопасныйРежим = Ложь.Посмотрим на пример структуры функции регистрации:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка();
ПараметрыРегистрации.Наименование = "Проведение перемещений (безопасный режим выключен)";
// КРИТИЧЕСКИ ВАЖНЫЙ ПАРАМЕТР:
ПараметрыРегистрации.БезопасныйРежим = Ложь;
// Добавление команд...
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = "Выполнить проведение";
НоваяКоманда.Идентификатор = "ПровестиДокументы";
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
Возврат ПараметрыРегистрации;
КонецФункции
Когда вы устанавливаете БезопасныйРежим = Ложь, при запуске обработки система запросит подтверждение администратора. После одобрения код внутри обработки получит право полноценно использовать УстановитьПривилегированныйРежим(Истина), и проведение документа пройдет успешно.
Иногда ошибка возникает не из-за безопасного режима, а из-за тонких настроек прав доступа (RLS — Row Level Security). Проанализируем разницу между интерактивным и программным проведением.
При интерактивном проведении (нажатие кнопки «Провести» в форме) система может передавать в объект документа определенные ДополнительныеСвойства, которые подсказывают модулю проведения, что проверку некоторых ограничений можно пропустить. При программном вызове Записать(РежимЗаписиДокумента.Проведение) этих свойств нет.
Попробуйте добавить в код перед записью следующие параметры (актуально для многих типовых решений):
ОбъектДок = СсылкаНаДокумент.ПолучитьОбъект();
// Указываем системе, что проверка прав при записи не требуется (если код на сервере)
ОбъектДок.ОбменДанными.Загрузка = Истина;
// Или передаем специальные флаги типовых конфигураций
ОбъектДок.ДополнительныеСвойства.Вставить("ЭтоИнтерактивнаяОперация", Истина);
Попытка
ОбъектДок.Записать(РежимЗаписиДокумента.Проведение);
Исключение
// Обработка ошибки
КонецПопытки;
Важное примечание: Использование ОбменДанными.Загрузка = Истина отключает большинство проверок в модуле документа (включая проверку заполнения и собственно алгоритмы проведения в некоторых случаях), поэтому используйте этот метод с осторожностью, только если вам нужно просто «протолкнуть» запись объекта без логических проверок.
Если решение с безопасным режимом не помогает, стоит проверить права пользователя не на сам Документ, а на РегистрНакопления или РегистрБухгалтерии, по которым документ делает движения.
Выясним причину через «Журнал регистрации»:
РегистрСведений.ДанныеОчередиОбновления), к которому не удалось обратиться.Для успешного проведения документа из внешней обработки мы рекомендуем придерживаться следующей стратегии:
УстановитьПривилегированныйРежим(Истина) непосредственно перед вызовом Записать().Соблюдение этих правил позволит вам избежать большинства проблем с правами доступа и обеспечит стабильную работу ваших внешних инструментов в среде 1С.