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