Часто возникает задача: предоставить пользователю с ограниченными правами возможность выполнить специфическую операцию, требующую полного доступа, но только в рамках одной конкретной обработки. Например, разрешить менеджеру изменять дату проведенного документа, не давая ему при этом полные права на всю систему. Простой запуск сеанса под администратором или выдача пользователю роли с полными правами — это грубые и небезопасные решения.
Давайте разберем, как грамотно и безопасно решить эту задачу на примере использования обработки «Универсальный отбор и обработка объектов» и ее функциональности «Произвольный алгоритм».
Проанализируем несколько подходов, от самых прямолинейных и рискованных до архитектурно верных и безопасных.
Платформа 1С предоставляет механизм временного отключения проверки прав — привилегированный режим. Код, выполняемый в этом режиме, исполняется на сервере с полными правами, игнорируя любые ограничения текущего пользователя. Включить его можно методом УстановитьПривилегированныйРежим(Истина).
В контексте поля «Произвольный алгоритм» пользователь может написать следующий код:
// Включаем режим, где все можно
УстановитьПривилегированныйРежим(Истина);
// Выполняем действия, требующие полных прав.
// Например, изменяем дату объекта и проводим его.
Объект = ТекущийОбъект.ПолучитьОбъект();
Объект.Дата = '20230115';
Объект.Записать(РежимЗаписиДокумента.Проведение);
// ОБЯЗАТЕЛЬНО выключаем привилегированный режим
УстановитьПривилегированныйРежим(Ложь);
В чем заключается критическая уязвимость этого подхода?
Предоставляя пользователю возможность использовать УстановитьПривилегированныйРежим() в поле для произвольного кода, вы, по сути, даете ему полные права на всю информационную базу. Он не ограничен только изменением даты. Внутри этого блока он может написать любой код: удалить все документы, изменить константы, добавить себе административные роли или даже выполнить код, который наносит вред данным. Вы никак не контролируете, что именно будет выполнено в этом блоке.
Важный технический момент: количество вызовов УстановитьПривилегированныйРежим(Ложь) должно строго соответствовать количеству вызовов УстановитьПривилегированныйРежим(Истина). Нарушение этого баланса приведет к возникновению исключительной ситуации.
Этот метод можно рассматривать только как временное решение при отладке, но никогда — как постоянное решение для работы пользователей.
Встречается и такой, еще более опасный подход — программное добавление пользователю административной роли прямо в коде. Выглядеть это может так:
// ЭТОТ КОД ЯВЛЯЕТСЯ КРАЙНЕ ОПАСНЫМ ПРИМЕРОМ!
ПользовательИБ = ИнформационнаяБаза.НайтиПоИмени(ИмяПользователя());
Если ПользовательИБ <> Неопределено Тогда
ПользовательИБОбъект = ПользовательИБ.ПолучитьОбъект();
НужнаяРоль = Метаданные.Роли.ПолныеПрава;
ПользовательИБОбъект.Роли.Добавить(НужнаяРоль);
ПользовательИБОбъект.Записать();
КонецЕсли;
// ... здесь код, требующий прав ...
Этот код не просто дает временные права на выполнение участка кода. Он модифицирует объект пользователя в базе данных, наделяя его новыми ролями. Если не предусмотреть код, который эти права отбирает, пользователь получит их навсегда. Это огромная дыра в безопасности, которую нельзя допускать.
Это рекомендованный и единственно верный способ решения нашей задачи. Суть его в том, чтобы инкапсулировать (спрятать) весь опасный код, требующий полных прав, в специальный серверный общий модуль.
Разберем по шагам, как это реализовать:
Создание привилегированного общего модуля.
В конфигураторе создайте новый общий модуль, например, с именем РаботаСДокументамиПривилегированный. В его свойствах необходимо установить следующие флаги:
Разработка экспортной процедуры.
Внутри созданного модуля напишем экспортную процедуру, которая будет выполнять нашу задачу — изменение даты документа. Важно, что именно здесь, под полным контролем разработчика, мы можем и должны реализовать все необходимые проверки.
// Содержимое общего модуля "РаботаСДокументамиПривилегированный"
Процедура ИзменитьДатуДокумента(СсылкаНаДокумент, НоваяДата) Экспорт
// Шаг 1. Проверяем входные параметры и бизнес-логику.
// Это наш "фильтр безопасности". Пользователь не сможет обойти эти проверки.
Если ТипЗнч(СсылкаНаДокумент) <> Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
ВызватьИсключение "Изменять дату можно только у документов реализации!";
КонецЕсли;
Если НоваяДата > ТекущаяДата() Тогда
ВызватьИсключение "Нельзя устанавливать будущую дату!";
КонецЕсли;
// Шаг 2. Выполняем действие, требующее прав.
ОбъектДокумента = СсылкаНаДокумент.ПолучитьОбъект();
ОбъектДокумента.Дата = НоваяДата;
// Используем конструкцию Попытка-Исключение для корректной обработки ошибок записи
Попытка
ОбъектДокумента.Записать(РежимЗаписиДокумента.Проведение);
Исключение
// Передаем текст ошибки на уровень пользователя
ВызватьИсключение ОписаниеОшибки();
КонецПопытки;
КонецПроцедуры
Вызов процедуры из обработки.
Теперь в поле «Произвольный алгоритм» пользователь пишет не опасный код, а всего лишь одну строку — вызов нашей безопасной процедуры.
// Код в поле "Произвольный алгоритм"
НоваяДатаДляДокумента = Дата(2023, 10, 20);
РаботаСДокументамиПривилегированный.ИзменитьДатуДокумента(ТекущийОбъект, НоваяДатаДляДокумента);
Преимущества этого подхода очевидны:
Таким образом, мы решаем исходную задачу — даем пользователю нужный инструмент, но делаем это контролируемо и без ущерба для безопасности всей системы. Это и есть признак профессионального подхода к разработке в 1С.