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