Как провести документ в привилегированном режиме, если у пользователя нет прав на регистр?

Программист 1С v8.3 (Обычные формы)
← На главную

При разработке конфигураций на платформе 1С часто возникает задача: позволить пользователю провести документ, который должен внести записи в защищенный регистр (например, регистр накопления с финансовыми результатами или остатками), к которому у рядового сотрудника нет прямого доступа на запись или изменение. В обычных формах и клиент-серверном варианте работы эта задача имеет свои специфические сложности, которые мы подробно разберем в данной статье.

Разбор основной проблемы: Почему не срабатывает привилегированный режим?

Рассмотрим ситуацию: программист создал привилегированный модуль и вызывает его из процедуры ОбработкаПроведения. Однако, несмотря на наличие модуля, система выдает ошибку «Нарушение прав доступа» еще до того, как управление доходит до точки останова в коде проведения. Проанализируем, почему это происходит.

В клиент-серверном варианте для документов с обычными формами флаги метаданных «Привилегированный режим при проведении» и «Привилегированный режим при отмене проведения» часто не дают ожидаемого эффекта. Основная причина кроется в механизме очистки движений, который срабатывает автоматически при перепроведении документа. Выясним причину этого поведения платформы.

Влияние свойства «Удаление движений» на проверку прав

В свойствах любого документа есть важный параметр — «Удаление движений». Посмотрим, как разные значения этого свойства влияют на процесс проведения:

  1. Удалять автоматически: При выборе этого варианта платформа пытается очистить все существующие движения документа по регистрам ДО начала выполнения программного кода в процедуре ОбработкаПроведения. Этот процесс инициируется в контексте прав текущего пользователя. Если у пользователя нет прав на изменение регистра, транзакция прерывается по ошибке доступа, и ваш привилегированный код даже не успевает запуститься.
  2. Удалять автоматически при отмене проведения: В этом режиме платформа не трогает записи при обычном (пере)проведении. Это позволяет управлению «добежать» до процедуры в модуле объекта, откуда вы уже можете вызвать серверный привилегированный модуль.
  3. Не удалять автоматически: В этом случае ответственность за очистку старых движений полностью ложится на разработчика. Если вы забудете программно очистить движения в привилегированном режиме, при каждом перепроведении записи будут дублироваться или наслаиваться.

Решение: Для успешного проведения в привилегированном режиме необходимо установить свойство «Удаление движений» в значение Удалять автоматически при отмене проведения.

Реализация через привилегированный общий модуль

Поскольку в клиент-серверном варианте обычного приложения проведение может инициироваться на стороне клиента, использование метода УстановитьПривилегированныйРежим(Истина) непосредственно в модуле документа может не сработать. Разберем по шагам правильный алгоритм создания механизма проведения:

1. Создайте общий модуль (например, ПроведениеСерверПривилегированный).
2. В свойствах модуля установите флаги: «Сервер» и «Привилегированный».
3. В модуле документа вызовите экспортную процедуру из этого общего модуля.

Рассмотрим пример кода в модуле документа:


Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    
    // Вызываем процедуру проведения в привилегированном модуле
    ПроведениеСерверПривилегированный.ВыполнитьДвиженияДокумента(ЭтотОбъект, Отказ);
    
КонецПроцедуры

Проблема передачи мутабельных значений

При попытке передать ДокументОбъект напрямую в процедуру серверного модуля в клиент-серверном варианте, вы часто можете столкнуться с ошибкой «Ошибка передачи мутабельного значения». Это происходит потому, что объект документа в обычном приложении может содержать ссылки на клиентские элементы (формы, контексты), которые невозможно сериализовать и передать на сервер.

Проанализируем, как правильно передать данные для проведения:

  1. Передача по ссылке: Вместо самого объекта передавайте Ссылка. Внутри серверного модуля получайте объект заново через Ссылка.ПолучитьОбъект(). Однако помните, что это приведет к повторному считыванию данных из базы, и если в объекте были не записанные изменения, они будут потеряны.
  2. Передача через структуру: Соберите все необходимые данные (табличные части, реквизиты шапки) в Структура или ТаблицаЗначений. Эти типы данных отлично сериализуются.

Рассмотрим правильный пример реализации в привилегированном модуле с получением объекта:


Процедура ВыполнитьДвиженияДокумента(ДокументСсылка, Отказ) Экспорт
    
    // Получаем объект документа на стороне сервера
    ДокОбъект = ДокументСсылка.ПолучитьОбъект();
    
    // Очищаем движения вручную, если это необходимо
    ДокОбъект.Движения.ВашРегистрНакопления.Записывать = Истина;
    ДокОбъект.Движения.ВашРегистрНакопления.Очистить();
    
    // Формируем новые движения
    НоваяЗапись = ДокОбъект.Движения.ВашРегистрНакопления.Добавить();
    НоваяЗапись.Период = ДокОбъект.Дата;
    НоваяЗапись.Сумма = ДокОбъект.СуммаДокумента;
    // ... заполнение остальных полей
    
    // Записываем движения
    ДокОбъект.Движения.Записать();
    
КонецПроцедуры

Использование фоновых заданий для сложных задач

Если логика проведения крайне ресурсоемкая или требует взаимодействия с множеством различных объектов, на которые у пользователя нет прав, можно рассмотреть вариант выполнения проведения через фоновое задание. Рассмотрим этот метод подробнее.

Фоновые задания всегда выполняются на сервере и под правами, которые по умолчанию игнорируют ограничения текущего сеанса пользователя (если используется системный контекст). Вы запускаете задание, передавая ему ссылку на документ, и задание выполняет все необходимые расчеты и записи в регистры.

Однако у этого метода есть и минусы: пользователь не получит мгновенную обратную связь об ошибках проведения (например, о нехватке остатков) в привычном окне сообщений, если не реализовать механизм мониторинга состояния фонового задания.

Безопасность и RLS (Record Level Security)

Важно помнить, что даже в привилегированном режиме запросы могут возвращать пустые результаты, если включен механизм RLS (ограничение доступа на уровне записей) и в запросе не используется ключевое слово РАЗРЕШЕННЫЕ. Хотя привилегированный режим обычно отключает проверку прав, в некоторых специфических версиях платформы или при использовании сложных конструкций Автоматизированного режима блокировок, нюансы с RLS могут проявляться.

Проанализируем ситуацию с правами «только на запись». Если политика компании позволяет, можно дать пользователю роль с правом «Изменение» на регистр, но без права «Чтение». В этом случае пользователь сможет записывать движения через документ, но не сможет просмотреть содержимое регистра через консоль запросов или стандартные отчеты. Однако это «слабая» защита, так как хитрый пользователь с доступом к внешним обработкам все равно может попытаться считать данные программно.

Резюме и рекомендации

Подводя итог, для реализации проведения «без прав» в обычном приложении 1С 8.3:

Следуя этим правилам, вы обеспечите надежную работу системы и безопасность данных, сохраняя при этом удобство работы пользователей.

← На главную