Почему возникает ошибка «Отказ в доступе на Чтение» при перепроведении документов с RLS в 1С:УПП и как её решить

Программист 1С v8.3 (Обычные формы) Управленческий учет IT и автоматизация бизнеса
← На главную

При настройке прав доступа в конфигурации «Управление производственным предприятием» (УПП) разработчики часто сталкиваются с неочевидным поведением платформы «1С:Предприятие 8». Одна из таких классических проблем — невозможность перепровести документ при настроенном ограничении доступа на уровне записей (RLS) на чтение регистра накопления. При этом пользователь может без проблем создавать, записывать, проводить и даже распроводить документ, но при попытке его обычного перепроведения система выдает ошибку:

Доступ. Отказ в доступе Регистр накопления. Движения денежных средств Действие: Чтение

В этой статье мы подробно разберем, почему возникает эта ошибка при очистке движений, проанализируем внутренние механизмы работы платформы с СУБД под RLS и рассмотрим четыре практических способа решения проблемы — от быстрого «костыля» до системных и безопасных архитектурных подходов.


Выясняем причину: почему при изменении или удалении требуется право на «Чтение»?

На первый взгляд логика платформы кажется парадоксальной: пользователь пытается перезаписать или очистить движения (то есть совершает действие «Изменение» или «Удаление»), а система жалуется на отсутствие прав на «Чтение». Почему так происходит?

Рассмотрим этот механизм на уровне СУБД и транзакций 1С:

  1. Неявный запрос к старым данным: Когда выполняется метод ДокументОбъект.Движения[ИмяРегистра].Очистить(), коллекция движений в оперативной памяти помечается как модифицированная и пустая. Во время записи документа платформа пытается физически удалить старые строки из таблицы регистра в базе данных. Для этого СУБД должна сопоставить удаляемые строки с текущим набором. При включенном RLS платформа накладывает условия ограничения на SQL-запрос. Чтобы проверить, имеет ли право пользователь удалить конкретные записи, система сначала пытается неявно «прочитать» существующие строки в базе данных. Если правила RLS запрещают пользователю читать хотя бы одну из существующих строк этого документа в регистре (например, из-за изменения настроек прав или если документ ранее был проведен под другой организацией), СУБД блокирует операцию, возвращая ошибку доступа на чтение.
  2. Разница между отменой проведения и перепроведением: Почему же тогда работает отмена проведения (распроведение)? Дело в том, что в типовых конфигурациях отмена проведения чаще всего происходит в привилегированном режиме на сервере без контроля прав (через специализированные процедуры, такие как ПолныеПрава.ЗаписатьНаборЗаписейНаСервере). А вот при стандартном перепроведении очистка движений запускается непосредственно в транзакции проведения под учетной записью текущего пользователя.
  3. Роль выборочной очистки регистров: В коде проведения документов УПП используется типовая функция ОбщегоНазначения.УдалитьДвиженияРегистратора(). В ней присутствует параметр ВыборочноОчищатьРегистры = Истина. При таком режиме очистка выполняется непосредственно через обращение к коллекции в памяти сеанса пользователя: Движения[ИмяРегистра].Очистить(). Именно эта строка в непривилегированном контексте вызывает проверку RLS и приводит к ошибке.

Способ 1. Решение через «ДополнительныеСвойства» (Вариант автора темы)

Рассмотрим решение, к которому пришел автор темы на форуме. Этот способ заключается в передаче флага-признака из модуля документа в общий модуль ОбщегоНазначения для принудительного вызова удаления движений в привилегированном режиме.

Разберем реализацию этого метода по шагам.

Шаг 1. В модуле объекта проблемного документа перед вызовом процедуры очистки движений добавим специальный признак в структуру ДополнительныеСвойства:


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

Если мУдалятьДвижения Тогда 
    ОбщегоНазначения.УдалитьДвиженияРегистратора(ЭтотОбъект, Отказ, Истина, РежимПроведения); 
КонецЕсли;

Шаг 2. Перейдем в общий модуль ОбщегоНазначения и найдем процедуру УдалитьДвиженияРегистратора. Изменим логику проверки условий. Нам нужно сделать так, чтобы при наличии нашего флага очистка выполнялась через привилегированный общий модуль:


// Было:
// Если УдалятьДвижения Тогда

// Стало:
Если УдалятьДвижения Или ДокументОбъект.ДополнительныеСвойства.Свойство("УдалитьПривилегированно") Тогда 
    // Удаление движений происходит без контроля доступа в привилегированном режиме
    ПолныеПрава.ЗаписатьНаборЗаписейНаСервере(ИмяРегистра, ДокументОбъект.Ссылка,, ТипРегистра);
Иначе
    // Стандартная очистка в памяти
    ДокументОбъект.Движения[ИмяРегистра].Очистить();
КонецЕсли;

Преимущества метода: Решает проблему точечно для конкретного документа, сохраняя стандартную логику выборочной очистки для остальных объектов.

Недостатки: Требует изменения типового общего модуля ОбщегоНазначения, что может вызвать трудности и конфликты при последующих обновлениях конфигурации 1С:УПП.


Способ 2. Использование привилегированного режима в модуле документа (Рекомендуемый)

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

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


Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    
    // Включаем привилегированный режим для обхода RLS на чтение/запись регистров
    УстановитьПривилегированныйРежим(Истина);
    
    // Выполняем стандартную очистку движений
    Если мУдалятьДвижения Тогда 
        ОбщегоНазначения.УдалитьДвиженияРегистратора(ЭтотОбъект, Отказ, Истина, РежимПроведения); 
    КонецЕсли;
    
    // ... Выполняем алгоритмы проведения документа (запросы, расчеты, формирование движений) ...
    
    // Отключаем привилегированный режим, возвращаясь к правам текущего пользователя
    УстановитьПривилегированныйРежим(Ложь);
    
КонецПроцедуры

Важное примечание: Если алгоритмы проведения содержат проверки прав текущего пользователя или специфические ограничения, убедитесь, что включение привилегированного режима на время проведения не нарушит бизнес-логику вашей системы.


Способ 3. Отключение выборочной очистки регистров

Если нет необходимости выполнять именно выборочное удаление движений (когда очищаются только измененные коллекции, чтобы снизить нагрузку на СУБД), мы можем передать в процедуру УдалитьДвиженияРегистратора третий параметр со значением Ложь:


// Третий параметр "ВыборочноОчищатьРегистры" устанавливаем в Ложь
ОбщегоНазначения.УдалитьДвиженияРегистратора(ЭтотОбъект, Отказ, Ложь, РежимПроведения);

При передаче значения Ложь процедура очистки не будет использовать метод Очистить() в памяти сеанса пользователя. Вместо этого система сразу же обратится к методу ПолныеПрава.ЗаписатьНаборЗаписейНаСервере(), который запишет пустые наборы записей по всем регистрам в привилегированном режиме, успешно обходя любые ограничения RLS на чтение регистра.

Минусы метода: Полная очистка всех регистров документа перед проведением вместо выборочной может создавать дополнительную нагрузку на сервер СУБД и приводить к избыточным блокировкам таблиц, если документ формирует движения по очень большому числу регистров.


Способ 4. Симметричная настройка шаблонов RLS в ролях

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

Для устранения ошибки необходимо настроить права доступа таким образом, чтобы пользователь всегда имел беспрепятственный доступ на «Чтение» тех записей регистра накопления, регистратором которых является документ, к которому у этого пользователя есть права на «Изменение».

Рассмотрим пример настройки текста ограничения (RLS) для регистра накопления:


// Пример шаблона RLS на Чтение для регистра накопления
ГДЕ Регистратор В 
    (ВЫБРАТЬ Ссылка ИЗ Документ.ПлатежноеПоручениеИсходящее ГДЕ Организация = &ПараметрСеанса_Организация)

При такой настройке, если пользователь имеет доступ к самому документу-регистратору, платформа успешно разрешит неявное чтение его движений при очистке регистра, и ошибка доступа возникать не будет.


Резюме

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

← На главную