В процессе разработки и администрирования крупных информационных систем на платформе «1С:Предприятие 8» часто возникает задача точечного контроля прав доступа. Стандартного разделения прав на уровне ролей (например, «чтение всего справочника») бывает недостаточно. Когда в конфигурации включено ограничение доступа на уровне записей (RLS — Row Level Security), перед разработчиком встает сложная задача: как узнать, имеет ли конкретный пользователь доступ к определенному элементу справочника (например, к кассе «№1», конкретному контрагенту или складу)?
В этой статье мы подробно разберем, как решать эту задачу наиболее эффективными и современными методами, используя механизмы платформы и Библиотеки стандартных подсистем (БСП). Мы рассмотрим сценарии проверки прав как для текущего пользователя, так и для любого другого пользователя системы без необходимости входа под его учетной записью.
Представим ситуацию: в системе зарегистрировано несколько десятков пользователей. Нам нужно программно определить, кто из них имеет право просматривать или использовать в отчетах конкретную кассу (элемент справочника Кассы). Проблема усложняется тем, что права на кассу могут определяться не только наличием роли «Кассир», но и настройками групп доступа (RLS), которые динамически ограничивают видимость элементов для каждого пользователя.
Просто проверить наличие роли у пользователя недостаточно, так как RLS накладывает дополнительные фильтры. Нам необходимо решение, которое учитывает и назначенные роли, и правила RLS. В качестве готовой альтернативы программным методам можно использовать инструмент для визуального анализа прав, ролей и ограничений RLS.
Если нам нужно выполнить проверку в контексте сеанса пользователя, который в данный момент работает в программе, задача решается проще всего. В составе БСП есть готовые программные методы общего модуля УправлениеДоступом, разработанные специально для этих целей. Для изучения других возможностей библиотеки может быть полезен справочник по методам БСП с примерами их использования.
Вариант А. Метод ПроверитьЧтениеРазрешено()
Этот метод проверяет, разрешено ли чтение конкретного объекта на уровне СУБД с учетом всех ролей и ограничений RLS текущего пользователя. Если доступа к объекту нет, платформа вызывает исключение. Мы можем перехватить это исключение с помощью конструкции Попытка — Исключение.
Рассмотрим по шагам, как выглядит этот код:
СсылкаНаКассу = Справочники.Кассы.НайтиПоНаименованию("Касса №1");
Если ЗначениеЗаполнено(СсылкаНаКассу) Тогда
Попытка
УправлениеДоступом.ПроверитьЧтениеРазрешено(СсылкаНаКассу);
Сообщить("Доступ к кассе разрешен!");
Исключение
Сообщить("Доступ к кассе ограничен на уровне RLS или ролей.");
КонецПопытки;
КонецЕсли;
Вариант Б. Метод ЕстьРоль() общего модуля УправлениеДоступом
Еще один крайне полезный метод БСП — это функция УправлениеДоступом.ЕстьРоль(). Если передать в нее вторым параметром ссылку на конкретный объект, функция выполнит комплексную проверку. Она определит, назначена ли пользователю роль, дающая право на объект, и разрешен ли доступ к этому объекту в его группе доступа (с учетом ограничений RLS):
ИмяРоли = "ЧтениеКасс"; // Имя роли из конфигуратора
СсылкаНаКассу = Справочники.Кассы.НайтиПоНаименованию("Касса №1");
Если УправлениеДоступом.ЕстьRole(ИмяРоли, СсылкаНаКассу) Тогда
// Действие, если доступ разрешен
КонецЕсли;
Это самый сложный и интересный сценарий. Классический механизм RLS в 1С рассчитывается динамически в момент обращения к базе данных, основываясь на параметрах текущего сеанса. Напрямую запустить запрос под параметрами сеанса другого пользователя платформа не позволяет.
Тем не менее, в современных конфигурациях на БСП (начиная с версии 3.x) реализован так называемый производительный (универсальный) режим RLS. В этом режиме права пользователей рассчитываются системой заранее и кэшируются в специальных служебных таблицах.
Для реализации проверки нам понадобятся следующие объекты системы:
КлючиДоступа — хранит уникальные комбинации настроек прав.КлючиДоступаКОбъектам — связывает конкретный элемент (нашу кассу) с ключом доступа.КлючиДоступаПользователей — связывает конкретного пользователя системы с ключом доступа.Благодаря этим таблицам мы можем мгновенно найти всех пользователей, имеющих доступ к кассе «№1», выполнив один простой и быстрый запрос. Давайте проанализируем пример такого запроса:
Функция ПолучитьПользователейСДоступомКОбъекту(СсылкаНаОбъект) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| КлючиПользователей.Пользователь КАК Пользователь
|ИЗ
| РегистрСведений.КлючиДоступаКОбъектам КАК КлючиОбъектов
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.КлючиДоступаПользователей КАК КлючиПользователей
| ПО КлючиОбъектов.КлючДоступа = КлючиПользователей.КлючДоступа
|ГДЕ
| КлючиОбъектов.Объект = &СсылкаНаОбъект";
Запрос.УстановитьПараметр("СсылкаНаОбъект", СсылкаНаОбъект);
Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Пользователь");
КонецФункции
Этот способ работает практически мгновенно, не требует запуска фоновых заданий от имени других пользователей и может быть выполнен на сервере в любой момент.
Частой ошибкой начинающих разработчиков является использование стандартного метода платформы РольДоступна() или попытка перебора пользователей через метаданные. При работе с БСП это приводит к логическим ошибкам по следующим причинам:
РольДоступна("Кассир") для системного администратора вернет значение Ложь, хотя фактически доступ у него есть.Чтобы избежать подобных ошибок, всегда используйте функции БСП: Пользователи.РолиДоступны() или УправлениеДоступом.ЕстьРоль(), которые корректно обрабатывают права администраторов и активные профили групп доступа.
Для эффективного решения задачи контроля доступа к элементам справочников в 1С используйте встроенные инструменты БСП. Для проверки текущего сеанса отлично подходят методы УправлениеДоступом.ПроверитьЧтениеРазрешено() и УправлениеДоступом.ЕстьРоль(). Если же вам необходимо построить отчет или выгрузить список всех сотрудников, имеющих доступ к конкретному объекту, задействуйте возможности производительного режима RLS и делайте прямой запрос к регистрам ключей доступа.