В крупных и средних компаниях часто возникает задача разграничения прав доступа к финансовым документам. Типичный сценарий: руководство требует, чтобы сотрудники одного отдела (например, отдела продаж) не видели документы «Заявка на расходование денежных средств», созданные сотрудниками другого отдела (например, бухгалтерии или ИТ). Это необходимо для соблюдения конфиденциальности, в частности, для сокрытия информации о бюджетах на заработную плату, премиях или иных чувствительных расходах.
В конфигурации 1С:Управление производственным предприятием (УПП) ред. 1.3 эту задачу можно решить несколькими способами. В данной статье мы подробно разберем, как настроить такое разграничение прав, проанализируем популярное на форумах решение, выявим его критические недостатки и предложим наиболее оптимальные и безопасные с точки зрения производительности варианты.
Каждый пользователь информационной базы должен видеть только те заявки на расходование средств, которые созданы сотрудниками из его «группы» (отдела). В метаданных документа ДокументСсылка.ЗаявкаНаРасходованиеЧерныхСредств (или в типовом ЗаявкаНаРасходованиеДенежных Средств) присутствует реквизит Ответственный, который ссылается на справочник СправочникСсылка.Пользователи.
Нам необходимо настроить механизм RLS (Record Level Security — ограничение доступа на уровне записей) для роли пользователя таким образом, чтобы система сравнивала группу текущего авторизованного пользователя и группу пользователя, указанного в реквизите Ответственный документа.
На форумах часто предлагают быстрое решение: сгруппировать пользователей по папкам в справочнике Пользователи (например, создать папки «Отдел продаж», «Бухгалтерия») и написать RLS-запрос, который проверяет родителя текущего пользователя.
В самом простом виде этот запрос выглядит следующим образом:
ГДЕ Ответственный.Родитель В (ВЫБРАТЬ Родитель ИЗ Справочник.Пользователи ГДЕ Ссылка = &ТекущийПользователь)
Давайте подробно проанализируем эту конструкцию и выясним, почему её не рекомендуется использовать в реальных рабочих базах данных.
Критические недостатки данного подхода:
Пользователи может содержать многоуровневую структуру. Если внутри папки отдела появится хотя бы одна подпапка (например, в папке «Бухгалтерия» появится подпапка «Расчетчики»), то вышеуказанный запрос перестанет работать для пользователей из этой подпапки, так как их непосредственный Родитель уже не совпадет с родителем коллег уровнем выше.В ИЕРАРХИИ. Запрос принимает следующий вид:
ГДЕ Ответственный В ИЕРАРХИИ (ВЫБРАТЬ Родитель ИЗ Справочник.Пользователи ГДЕ Ссылка = &ТекущийПользователь)
В ИЕРАРХИИ в шаблонах ограничений RLS приводит к тому, что СУБД (например, MS SQL Server) генерирует крайне сложные рекурсивные запросы. На таблицах документов с сотнями тысяч записей это вызовет колоссальные задержки при открытии динамических списков, зависание интерфейса и частые взаимоблокировки базы данных (Lock Escalation).Для обхода ограничений иерархии справочника пользователей в 1С существует стандартный справочник ГруппыПользователей. Один пользователь может одновременно состоять в неограниченном количестве групп. Это дает необходимую гибкость.
Рассмотрим, как написать оптимальный с точки зрения производительности RLS-запрос для ограничения чтения документов по группам пользователей. Наша задача — разрешить чтение документа только в том случае, если автор (Ответственный) состоит хотя бы в одной общей группе с текущим пользователем.
Разберем по шагам создание шаблона RLS для права «Чтение» у документа ЗаявкаНаРасходованиеДенежныхСредств:
ОграничениеДоступаЗаявкиПоГруппам).ЗаявкаНаРасходованиеДенежныхСредств.
ГДЕ Ответственный В
(ВЫБРАТЬ ТабСостав.Пользователь
ИЗ Справочник.ГруппыПользователей.Пользователи КАК ТабСостав
ГДЕ ТабСостав.Ссылка В
(ВЫБРАТЬ ТабГруппы.Ссылка
ИЗ Справочник.ГруппыПользователей.Пользователи КАК ТабГруппы
ГДЕ ТабГруппы.Пользователь = &ТекущийПользователь))
Почему этот запрос работает быстро?
В отличие от тяжелых иерархических запросов с В ИЕРАРХИИ, этот запрос работает по плоским табличным частям Пользователи справочника ГруппыПользователей. СУБД легко оптимизирует подобные запросы с использованием индексов, что исключает появление «зависаний» при открытии журналов документов.
Прежде чем приступать к написанию собственного RLS-кода и изменению конфигурации, проанализируем возможности типового функционала УПП. В конфигурации реализован мощный универсальный механизм разграничения прав доступа на уровне записей.
У документа Заявка на расходование денежных средств есть обязательный реквизит Подразделение (или ПодразделениеОрганизации). В большинстве организаций структура групп пользователей полностью совпадает со структурой подразделений компании.
Выясним, как настроить ограничение доступа по подразделениям без доработки конфигурации:
При такой настройке платформа автоматически будет фильтровать документы «Заявка на расходование денежных средств» по реквизиту Подразделение. Пользователи увидят только те документы, подразделение которых входит в список их разрешенных объектов доступа. Это наиболее надежный метод, не требующий снятия конфигурации с поддержки.
Если вы приняли решение использовать программное ограничение через RLS (Решение #1), обязательно учитывайте следующие важные архитектурные особенности платформы «1С:Предприятие»:
1. Принцип объединения прав (логическое ИЛИ)
Если у пользователя в профиле есть хотя бы одна роль, дающая доступ к чтению документа ЗаявкаНаРасходованиеДенежныхСредств БЕЗ ограничений (например, типовая роль Бухгалтер или МенеджерПоПродажам), то ваш кастомный RLS-запрос работать не будет! Платформа суммирует права по принципу «Разрешено все, что разрешено хотя бы одной ролью». Чтобы ограничение сработало, вам необходимо внедрить разработанный RLS-запрос во все роли пользователя, дающие право чтения этого документа, либо забрать у пользователя лишние роли.
2. Обязательное индексирование полей
Поле, по которому происходит фильтрация в RLS (в нашем случае реквизит Ответственный), должно быть обязательно проиндексировано. Откройте свойства документа в конфигураторе, найдите реквизит Ответственный и убедитесь, что свойство Индексировать установлено в значение Индексировать или Индексировать с доп. упорядочиванием. Если этого не сделать, при росте базы данных производительность системы резко снизится.
3. Влияние на проведение и запись документов
Ограничение RLS влияет не только на интерактивное отображение документов в списках, но и на работу программного кода. Если при проведении другого связанного документа (например, ПлатежноеПоручениеИсходящее) система попытается программно прочитать данные ограниченной заявки, у пользователя возникнет ошибка «Недостаточно прав для работы с базой данных». Обязательно протестируйте всю цепочку документооборота под тестовым пользователем с ограниченными правами перед запуском системы в промышленную эксплуатацию.