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