В процессе разработки часто возникает задача ограничить видимость данных для конкретного пользователя. В конфигурации 1С:Бухгалтерия предприятия 3.0 (БП 3.0) штатные механизмы групп доступа для справочника Контрагенты отсутствуют, в отличие от Управление торговлей 11. Рассмотрим подробно, как реализовать ограничение доступа по папкам (иерархии) через механизм расширений, проанализируем типичные ошибки и выберем оптимальный метод реализации.
Разберем типичную ситуацию: разработчик заимствует роль в расширение, снимает в ней права на чтение справочника и назначает эту роль пользователю. Однако пользователь все равно видит все записи. Выясним причину этого поведения. В платформе 1С реализован принцип аддитивности (суммирования) прав. Если у пользователя назначено несколько ролей, и хотя бы одна из них (например, типовая роль ЧтениеКонтрагентов или Бухгалтер) разрешает доступ к объекту, то никакие другие «ограничивающие» роли в расширении этот доступ не закроют.
Проанализируем шаги для правильной настройки, которые помогут совершить переход от администратора к минимально необходимым правам:
Контрагенты.Это наиболее простой способ, который часто выбирают для быстрой реализации. Суть заключается в том, чтобы при открытии формы списка справочника принудительно устанавливать отбор по родителю. Рассмотрим, как это сделать в расширении формы списка.
Добавим в расширение форму списка справочника Контрагенты и перехватим событие ПриСозданииНаСервере. Пропишем следующий код:
&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
// Проверяем, нужно ли ограничивать данного пользователя
Если ИмяПользователя() = "МенеджерПоПродажам" Тогда
// Находим нужную папку (в реальной задаче лучше использовать параметры сеанса или доп. реквизиты)
НужнаяГруппа = Справочники.Контрагенты.НайтиПоНаименованию("НашиКлиенты");
Если Не НужнаяГруппа.Пустая() Тогда
// Устанавливаем фиксированный отбор в динамическом списке
ЭлементОтбора = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Родитель");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВИерархии;
ЭлементОтбора.ПравоеЗначение = НужнаяГруппа;
ЭлементОтбора.Использование = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важный нюанс: Этот метод защищает только «от честных людей». Если пользователь воспользуется консолью запросов или универсальным отчетом, он увидит все данные.
Механизм RLS позволяет ограничить доступ на уровне самой платформы, независимо от того, через какую форму или отчет пользователь запрашивает данные. С версии платформы 8.3.10 расширения поддерживают создание ролей с шаблонами ограничений.
Разберем алгоритм настройки RLS для ограничения по иерархии:
Контрагенты в расширение.Расш1_ЧтениеКонтрагентовСГруппировкой.Справочник.Контрагенты в поле «Чтение» прописываем условие ГДЕ.Пример текста ограничения (RLS):
ГДЕ (ЭтоГруппа = ИСТИНА)
ИЛИ (Родитель В ИЕРАРХИИ (&ПараметрСеанса_РазрешеннаяГруппаКонтрагентов))
Проанализируем это условие: Первая часть (ЭтоГруппа = ИСТИНА) необходима для того, чтобы пользователь видел дерево папок. Если закрыть доступ ко всем папкам, кроме целевой, пользователь может не увидеть иерархию вообще. Вторая часть ограничивает доступ непосредственно к элементам и вложенным папкам выбранной группы.
Использование фиксированных GUID или наименований прямо в тексте RLS считается плохой практикой. Правильнее использовать Параметры сеанса. Вы можете создать свой параметр сеанса в расширении и инициализировать его при старте системы (в модуле сеанса расширения), указав там ссылку на разрешенную папку.
Рассмотрим пример инициализации параметра сеанса в расширении:
// В модуле сеанса расширения
Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
Если ПараметрыСеанса.ТекущийПользователь.Наименование = "Менеджер" Тогда
ПараметрыСеанса.Расш1_ДоступнаяГруппаКонтрагентов = Справочники.Контрагенты.НайтиПоРеквизиту("Код", "00000123");
КонецЕсли;
КонецПроцедуры
Поскольку Бухгалтерия предприятия 3.0 базируется на БСП, рекомендуется использовать стандартные шаблоны доступа. Даже если в типовой конфигурации БП нет вида доступа «Группы доступа контрагентов», механизм управления доступом можно расширить.
Посмотрим на преимущества использования шаблона #ПоЗначениям:
Важно помнить, что включение RLS для справочника Контрагенты — это серьезная нагрузка на базу данных. Проанализируем последствия:
Справочник Контрагенты используется практически во всех первичных документах (Платежные поручения, Реализации, Поступления). Когда пользователь с RLS открывает журнал документов, система вынуждена для каждой строки проверять, имеет ли пользователь право видеть контрагента, указанного в этом документе. Это приводит к значительному усложнению SQL-запросов и может вызвать замедление работы интерфейса («фризы») при больших объемах данных.
Совет: Если стоит задача только скрыть «чужих» клиентов в списке, но при этом пользователь должен видеть документы по ним (или работать в общих журналах), лучше использовать программные фильтры в формах (Вариант 1) в сочетании с запретом на использование внешних обработок.
Если вы ограничили чтение по папке, необходимо обеспечить и корректную запись. Выясним, что произойдет, если пользователь создаст нового контрагента в «запрещенной» папке: объект запишется в базу, но тут же исчезнет из видимости пользователя, так как RLS перестанет его пропускать.
Чтобы этого избежать, добавим проверку в расширение модуля объекта справочника:
&НаСервере
Процедура Расш1_ПередЗаписью(Отказ)
// Если это новый контрагент и у пользователя есть ограничения
Если ЭтоНовый() И ПользовательИмеетОграничения() Тогда
// Принудительно устанавливаем правильного родителя
Если Родитель <> Справочники.Контрагенты.НайтиПоНаименованию("РазрешеннаяПапка") Тогда
Родитель = Справочники.Контрагенты.НайтиПоНаименованию("РазрешеннаяПапка");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Подводя итог, отметим: для жесткого и безопасного разделения данных в БП 3.0 следует использовать RLS в расширении с опорой на параметры сеанса. Для легкого косметического разделения достаточно фиксированных отборов в динамических списках форм.