В практике разработки на платформе 1С:Предприятие часто возникает задача: выполнить действие от имени системы, на которое у текущего пользователя нет прав. Типичный пример — проведение документа пользователем, имеющим права только на просмотр. Для этих целей существует привилегированный режим. Однако новички часто сталкиваются с ситуацией, когда использование команды УстановитьПривилегированныйРежим(Истина) не дает ожидаемого результата и система выдает ошибку "Нарушение прав доступа". Рассмотрим подробно, почему это происходит и как правильно реализовать данный механизм.
Привилегированный режим предназначен для временного отключения проверки прав доступа (включая RLS) на уровне сервера или в файловом варианте работы. Проанализируем основные причины, по которым код может "игнорировать" установку этого режима:
УстановитьПривилегированныйРежим() работает исключительно на стороне сервера (или в толстом клиенте в файловом варианте). Если вы вызываете его в процедуре &НаКлиенте управляемого приложения, платформа просто проигнорирует команду, не сообщая об ошибке.Для того чтобы привилегированный режим заработал в управляемых формах, необходимо гарантировать, что вызов метода Записать(РежимЗаписиДокумента.Проведение) происходит внутри серверной процедуры. Разберем пример реализации в модуле формы или команды:
&НаКлиенте
Процедура ВыполнитьПроведение(Команда)
ПровестиДокументНаСервере(Объект.Ссылка);
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ПровестиДокументНаСервере(СсылкаНаДокумент)
УстановитьПривилегированныйРежим(Истина);
// Получаем объект документа заново в привилегированном режиме
ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
Если ДокументОбъект <> Неопределено Тогда
Попытка
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Исключение
ЗаписьЖурналаРегистрации("Ошибка проведения", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
ВызватьИсключение;
КонецПопытки;
КонецЕсли;
УстановитьПривилегированныйРежим(Ложь);
КонецПроцедуры
Обратите внимание: внутри процедуры мы сначала устанавливаем режим, а затем получаем объект по ссылке. Это критически важно, так как если объект был передан с клиента (где права ограничены), его состояние может содержать флаги ограничений прав, которые не сбросятся автоматически.
Если вы разрабатываете внешнюю обработку, вы наверняка столкнетесь с тем, что УстановитьПривилегированныйРежим(Истина) внутри нее не срабатывает. Выясним причину: по умолчанию внешние обработки открываются в безопасном режиме. В этом режиме использование привилегированного режима запрещено платформой.
Чтобы обойти это ограничение, у вас есть два пути:
А. Встроить обработку в конфигурацию. После того как обработка станет частью дерева объектов метаданных, она перестанет считаться "внешней" и на нее перестанут распространяться ограничения безопасного режима (если они не заданы явно).
Б. Программное открытие без безопасного режима. Если вам необходимо использовать именно внешнюю обработку, используйте метод менеджера Создать() с параметром БезопасныйРежим = Ложь. Рассмотрим, как это выглядит в коде:
// Пример программного открытия внешней обработки без безопасного режима
ПутьКФайлу = "C:\MyReports\SuperProcess.epf";
Обработка = ВнешниеОбработки.Создать(ПутьКФайлу, Ложь); // Второй параметр - БезопасныйРежим
Обработка.ВыполнитьПроведениеДокументов();
Важно: Для выполнения этого кода у пользователя должны быть административные права или право на использование внешних обработок без ограничений.
Наиболее архитектурно правильный способ решения задачи — вынос логики проведения в общий модуль. Рассмотрим по шагам, как это сделать:
ПроведениеДокументовСервер).УстановитьПривилегированныйРежим().Пример кода в таком модуле:
// В привилегированном общем модуле
Процедура ПровестиДокументПрограммно(ДокументСсылка) Экспорт
Объект = ДокументСсылка.ПолучитьОбъект();
Объект.Записать(РежимЗаписиДокумента.Проведение);
КонецПроцедуры
Теперь вы можете вызвать эту процедуру из любого места (включая внешние обработки или формы), и она успешно проведет документ, даже если у текущего пользователя права только на чтение. Это самый надежный способ, исключающий ошибки контекста.
В обычном приложении (толстый клиент) код модулей форм выполняется на клиенте. Однако если база работает в клиент-серверном варианте, вызов УстановитьПривилегированныйРежим(Истина) в модуле формы на стороне клиента не сработает. Выходом здесь также является использование Привилегированных общих модулей, которые гарантированно выполняются на сервере в обход прав пользователя.
Проанализируем, почему иногда кажется, что режим не работает, хотя код написан верно:
Подводя итог: для успешного проведения документа под ограниченными правами всегда стремитесь перенести код в серверный привилегированный общий модуль. Это гарантирует стабильную работу независимо от того, запущена ли обработка как внешняя или встроена в конфигурацию.