РольДоступна() или ПравоДоступа() — что и когда правильно использовать в 1С?

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

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

В чем принципиальная разница между РольДоступна() и ПравоДоступа()?

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

Рассмотрим простой пример. Предположим, нам нужно ограничить доступ к редактированию справочника «Контрагенты». Мы можем написать код двумя способами.

Способ первый (не рекомендуется):


Если РольДоступна("АдминистраторСправочникаКонтрагентов") Или РольДоступна("ПолныеПрава") Тогда
    // Разрешаем редактирование
КонецЕсли;

Способ второй (правильный):


Если ПравоДоступа("Редактирование", Метаданные.Справочники.Контрагенты) Тогда
    // Разрешаем редактирование
КонецЕсли;

Почему второй вариант предпочтительнее? Проанализируем ситуацию: если завтра архитекторы базы данных решат разделить роль «АдминистраторСправочникаКонтрагентов» на две новые роли («РедактированиеЮрЛиц» и «РедактированиеФизЛиц»), то при использовании первого способа нам придется бегать по всему коду конфигурации, искать вызовы РольДоступна() и переписывать условия. Во втором случае код продолжит работать без изменений, поскольку право «Редактирование» на объект метаданных у пользователя останется, независимо от того, какими новыми ролями оно обеспечено. Это значительно повышает устойчивость системы к рефакторингу.

Стандарты разработки фирмы «1С»

Официальные стандарты разработки «1С» четко разграничивают области применения этих методов. Сформулируем основные правила:

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

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


Если РольДоступна("РазрешитьПроведениеБезКонтроляОстатков") Или ПривилегированныйРежим() Тогда
    // Выполняем проведение по специальному алгоритму
КонецЕсли;

Подводные камни РольДоступна() в современных конфигурациях на БСП

Если вы работаете в конфигурации, созданной на базе Библиотеки стандартных подсистем (БСП) — например, ERP, КА, УТ, ЗУП — стандартный метод платформы РольДоступна() может преподнести неприятный сюрприз.

В целях оптимизации производительности в современных базах «1С» пользователям с административными правами (роль «Полные права» или «Администратор системы») физически назначаются только эти корневые роли. Все остальные профильные роли (например, «Добавление и изменение номенклатуры») у них в профилях безопасности не отмечаются. Платформа понимает, что у администратора и так есть все права.

Но если вы напишете код:

Если РольДоступна("ДобавлениеИзменениеНоменклатуры") Тогда ...

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


// Правильная проверка роли с использованием механизмов БСП
Если Пользователи.РолиДоступны("ДобавлениеИзменениеНоменклатуры") Тогда
    // Этот код отработает корректно и для обычного пользователя, и для администратора
КонецЕсли;

Функции БСП под капотом автоматически проверяют, обладает ли текущий пользователь полными правами или работает ли система в привилегированном режиме, избавляя вас от необходимости писать громоздкие конструкции вида Или РольДоступна("ПолныеПрава").

Ограничение контекста исполнения: Клиент против Сервера

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

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

Разберем этот паттерн на примере кода:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем право на сервере и записываем результат в созданный реквизит формы (Тип: Булево)
    ДоступноРедактированиеЦен = ПравоДоступа("Редактирование", Метаданные.РегистрыСведений.ЦеныНоменклатуры);
    
КонецПроцедуры

&НаКлиенте
Процедура ИзменитьЦену(Команда)
    
    // На клиенте мы просто анализируем сохраненное значение реквизита формы
    Если Не ДоступноРедактированиеЦен Тогда
        ПоказатьПредупреждение(, "У вас нет прав на изменение цен номенклатуры!");
        Возврат;
    КонецЕсли;
    
    // Логика открытия формы изменения цен...
КонецПроцедуры

Проблема «запрещающих» ролей

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

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

Если реализовать запрет через код вида:


Если РольДоступна("ЗапретРедактированияСреднегоЗаработка") Тогда
    Отказ = Истина;
КонецЕсли;

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

Почему не рекомендуется использовать ролевую настройку видимости элементов формы?

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

  1. Разрушение коллекции элементов на клиенте. Если элементу формы жестко задана видимость по ролям, и у текущего пользователя этой роли нет, платформа физически удаляет данный элемент из коллекции Элементы на клиенте. Если в коде модуля формы вы попытаетесь обратиться к нему программно (например, Элементы.ГруппаФинансы.Доступность = Ложь;), программа аварийно завершится с ошибкой «Поле объекта не обнаружено».
  2. Сложность поддержки и аудита. Программный код модуля формы всегда находится перед глазами разработчика. Если же видимость элементов настроена галочками в свойствах сотен элементов конфигуратора, то при обновлении системы, рефакторинге или слиянии ролей найти причину, почему у пользователя «поехала» форма или пропала кнопка, становится крайне трудоемкой задачей.

Проанализируем правильный подход. Управлять видимостью и доступностью элементов формы нужно программно в модуле формы, используя результаты проверки прав доступа:


&НаСервере
Процедура УстановитьВидимостьЭлементовНаСервере()
    
    // Проверяем право доступа к ключевым данным
    ДоступныФинансовыеДанные = ПравоДоступа("Чтение", Метаданные.РегистрыНакопления.ВыручкаИПродажи);
    
    // Программно управляем элементами формы
    Элементы.ГруппаПродажиИФинансы.Видимость = ДоступныФинансовыеДанные;
    Элементы.СуммаДокумента.Доступность = ДоступныФинансовыеДанные;
    
КонецПроцедуры

Резюме

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

← На главную