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