Как программно проверить право на изменение конкретного объекта в 1С с учетом RLS

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

Разработка в системе 1С часто сталкивает нас с необходимостью тонкой настройки прав доступа. Одной из самых нетривиальных задач является проверка права доступа «Изменение» не просто к типу метаданных (например, ко всем документам «Реализация товаров и услуг»), а к конкретному экземпляру объекта, на который наложены ограничения RLS (Row-Level Security).

Стандартная функция ПравоДоступа("Изменение", Метаданные.Документы.РеализацияТоваровУслуг) в данном случае бессильна, так как она возвращает общую информацию о правах пользователя на уровне всей таблицы, игнорируя условия RLS. В этой статье мы подробно разберем, как обойти это ограничение, проанализируем архитектурные сложности и рассмотрим несколько рабочих способов решения проблемы.

Почему стандартный метод не работает?

Прежде всего, давайте выясним причину. Механизм RLS в 1С реализован на уровне СУБД. Когда мы пытаемся прочитать данные, платформа автоматически добавляет условие WHERE к SQL-запросу. Однако проверка прав на запись (изменение) происходит непосредственно в момент фиксации транзакции записи. До этого момента объект находится в оперативной памяти, и платформа не может заранее сказать, позволит ли СУБД обновить соответствующую строку в таблице, так как состояние объекта может измениться в процессе выполнения кода модуля объекта или подписок на события.

Способ №1. Метод попытки записи в транзакции

Самый простой и «честный» с точки зрения платформы способ — это попытаться записать объект и посмотреть, возникнет ли ошибка доступа. Чтобы не вносить реальных изменений в базу данных, мы используем механизм транзакций. Разберем этот алгоритм по шагам:

  1. Открываем транзакцию.
  2. Блокируем объект для записи.
  3. Пытаемся вызвать метод Записать().
  4. Если запись прошла успешно — право есть.
  5. В любом случае отменяем транзакцию, чтобы изменения не зафиксировались.

Рассмотрим пример кода:


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

Важные нюансы данного метода:

Способ №2. Использование возможностей Библиотеки стандартных подсистем (БСП)

Если ваша конфигурация разработана на базе БСП (что справедливо для большинства современных решений, таких как ERP, УТ 11, БП 3.0), мы можем воспользоваться встроенными инструментами. В БСП существует программный интерфейс, предназначенный именно для таких целей.

Проанализируем работу с модулем УправлениеДоступом. В нем присутствует метод, позволяющий проверить доступность объекта:


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

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

Способ №3. Использование метода «ПроверитьДоступ» (Платформа 8.3.15+)

В современных версиях платформы (8.3.15 и выше) появился метод ПроверитьДоступ(). Мы можем использовать его для проверки конкретных прав. Выясним, как это работает на практике:


// Проверка права доступа для текущего пользователя
ПараметрыПроверки = Новый Структура("Ссылка", СсылкаНаОбъект);
Если ПроверитьДоступ("Изменение", СсылкаНаОбъект) Тогда
    // Право на изменение есть
КонецЕсли;

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

Способ №4. Эмуляция условий RLS через запрос

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

Посмотрим на пример реализации такого запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗРЕШЕННЫЕ
    |   Т.Ссылка КАК Ссылка
    |ИЗ
    |   Документ.РеализацияТоваровУслуг КАК Т
    |ГДЕ
    |   Т.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", НужнаяСсылка);
РезультатЗапроса = Запрос.Выполнить();

Если РезультатЗапроса.Пустой() Тогда
    // Либо объекта нет, либо RLS запрещает даже чтение.
Иначе
    // Объект доступен на чтение. 
КонецЕсли;

Важное ограничение: Этот метод проверяет только право «Чтение». В 1С возможна ситуация, когда пользователь видит документ (Чтение), но не может его менять (Изменение). Чтобы проверить право на изменение этим методом, вам придется вручную продублировать логику RLS в секции ГДЕ, что делает код трудноподдерживаемым при изменении ролей.

Способ №5. Проверка через Схему компоновки данных (СКД)

Этот метод считается экспертным. Мы можем программно выполнить СКД, в которой источником данных будет наш объект. При выполнении компоновки платформа автоматически применяет все ограничения RLS. Если после применения настроек и выполнения запроса в рамках СКД результат пустой — доступа нет.

Рассмотрим, почему это эффективно. СКД работает в контексте текущего пользователя и максимально полно интегрирована с механизмом прав доступа платформы. Это позволяет избежать «грязных» записей в базу данных, как в случае с транзакциями.

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

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

  1. Если версия платформы 8.3.15+ — всегда используйте встроенный метод ПроверитьДоступ(). Это максимально быстро и безопасно.
  2. Если вы работаете в типовой конфигурации на БСП — используйте функции общего модуля УправлениеДоступом. Это обеспечит совместимость с будущими обновлениями.
  3. Если нужно 100% подтверждение на запись (и другие методы недоступны) — используйте транзакцию с последующим откатом (ОтменитьТранзакцию()), но помните о рисках блокировок и сбитой нумерации.
  4. Избегайте жесткого кодирования условий RLS в запросах, так как при любом изменении прав в конфигураторе ваш программный код перестанет работать корректно.

Мы разобрали основные подходы к решению задачи проверки прав доступа на уровне объектов. Правильный выбор метода позволит вам создавать надежные и безопасные решения, которые будут корректно работать даже в условиях сложных настроек безопасности 1С.

← На главную