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