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

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

При разработке систем разграничения прав доступа на уровне записей (RLS — Record Level Security) программисты часто сталкиваются с парадоксальной ситуацией: пользователь имеет право изменять документ, но как только он меняет в нем ключевой реквизит (например, Исполнитель), система выдает ошибку "У пользователя недостаточно прав на исполнение операции над базой данных". В этой статье мы подробно разберем, почему это происходит и какими способами можно обойти это ограничение, сохранив при этом безопасность данных.

Почему возникает ошибка при записи документа с RLS?

Проанализируем механику работы платформы 1С. Когда мы настраиваем RLS на право Чтение, мы ограничиваем выборку данных из базы. Однако в момент интерактивной записи документа в управляемых формах происходит не только обновление записи в таблице (SQL UPDATE), но и последующее перечитывание данных для обновления формы и проверки целостности.

Если в правиле RLS прописано условие ГДЕ Исполнитель = &ТекущийПользователь, то алгоритм выглядит так:

  1. Пользователь открывает «свой» документ (чтение разрешено).
  2. Пользователь меняет реквизит Исполнитель на другого человека.
  3. Нажимает кнопку «Записать».
  4. Платформа успешно записывает данные в БД.
  5. Сразу после записи платформа пытается прочитать обновленный документ, чтобы вернуть его в форму.
  6. RLS блокирует чтение, так как Исполнитель теперь другой.
  7. Транзакция откатывается, и пользователь видит ошибку доступа.

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

Способ 1. Использование привилегированного режима

Это наиболее корректный метод с точки зрения архитектуры 1С. Суть заключается в том, чтобы выполнить запись объекта в контексте, где проверки RLS игнорируются. Для этого мы будем использовать Привилегированный модуль или метод УстановитьПривилегированныйРежим().

Разберем реализацию через модуль объекта. Мы можем перехватить процесс записи и временно отключить проверку прав. Рассмотрим пример кода в модуле документа:


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

Важно помнить, что УстановитьПривилегированныйРежим(Истина) работает только на стороне сервера. В управляемом приложении это гарантирует, что запись в БД пройдет без учета ограничений RLS текущего пользователя.

Способ 2. Разделение прав на «Чтение» и «Просмотр»

Выясним разницу между этими правами. В настройках роли 1С право Чтение отвечает за программный доступ к данным, а Просмотр — за видимость в списках и формах.

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

Однако этот метод имеет минус: если пользователь программно захочет перебрать все документы через запрос, RLS его не остановит. Поэтому данный метод подходит только для учебных баз или систем с некритичными данными.

Способ 3. Логическое разделение на «Автора» и «Исполнителя»

Проанализируем ситуацию с точки зрения бизнес-логики. Часто задача должна быть доступна не только тому, кто ее делает, но и тому, кто ее поставил. Добавим в документ реквизит Автор (типа СправочникСсылка.Пользователи).

Теперь изменим текст RLS в роли:


ГДЕ Исполнитель = &ТекущийПользователь 
   ИЛИ Автор = &ТекущийПользователь

В этом случае, когда пользователь (будучи автором) передает задачу другому исполнителю, он не теряет права на чтение этого документа, так как условие Автор = &ТекущийПользователь продолжает выполняться. Это самый надежный и логичный способ для систем документооборота и CRM.

Способ 4. Временная подмена параметров сеанса

Рассмотрим более "хитрый" способ, который упоминался на форумах. Мы можем временно изменить параметр сеанса, на который опирается RLS. Допустим, наш RLS выглядит так: ГДЕ Исполнитель = &ТекущийИсполнитель.

В форме документа при записи мы можем реализовать следующую логику:

  1. В событии ПередЗаписьюНаСервере запоминаем старое значение параметра сеанса.
  2. Устанавливаем в параметр сеанса &ТекущийИсполнитель значение "Нового исполнителя".
  3. После успешной записи (в событии ПослеЗаписиНаСервере) возвращаем параметру сеанса значение текущего пользователя.

Внимание: Этот метод крайне опасен в многопользовательской среде. Параметры сеанса глобальны для всех окон пользователя. Если во время записи документа у пользователя открыт другой список задач, он может на мгновение "мигнуть" чужими данными. Также это приводит к сбросу кэша RLS и снижению производительности.

Способ 5. Передача управления привилегированному модулю

Если нам нужно, чтобы пользователь гарантированно "отдал" документ и больше его не видел (даже если он автор), лучше реализовать кнопку "Передать задачу".

Посмотрим на алгоритм:

  1. Создаем серверный модуль и устанавливаем у него свойство "Привилегированный".
  2. В этом модуле пишем процедуру:

Процедура ПередатьЗадачуДругому(СсылкаНаДокумент, НовыйИсполнитель) Экспорт
    ОбъектДокумента = СсылкаНаДокумент.ПолучитьОбъект();
    ОбъектДокумента.Исполнитель = НовыйИсполнитель;
    ОбъектДокумента.Записать(); 
КонецПроцедуры

Так как модуль привилегированный, вызов Записать() внутри него проигнорирует любые настройки RLS. Для пользователя это будет выглядеть так: он нажал кнопку, документ закрылся и исчез из его списка. Это наиболее чистое решение с точки зрения кода.

Выводы и рекомендации

Мы рассмотрели различные подходы к решению проблемы RLS при смене ответственного. Выбор метода зависит от ваших целей:

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

← На главную