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