Переход на новую версию платформы 1С или изменение режима совместимости конфигурации с 8.2 на 8.3 часто сопровождается неожиданными ошибками в коде, который годами работал стабильно. Одной из самых распространенных проблем является внезапный отказ встроенной функции РольДоступна(). В этой статье мы подробно разберем, почему возникает ошибка «Недопустимое значение параметра», рассмотрим изменения в логике платформы и научимся писать отказоустойчивый код для проверки прав доступа.
Разберем ситуацию, с которой сталкиваются многие разработчики: после обновления режима совместимости до версии 8.3 привычный вызов РольДоступна("ИмяРоли") начинает вызывать исключительную ситуацию (падение программы), если указанной роли не существует в дереве метаданных. Важно понимать: в режиме совместимости 8.2 платформа вела себя более лояльно. Если вы допускали опечатку в имени роли или обращались к роли, которая была удалена, функция просто возвращала значение Ложь, и выполнение кода продолжалось.
Начиная с версии 8.3.3, логика была намеренно ужесточена. Теперь система считает обращение к несуществующему объекту метаданных критической ошибкой программирования. Это сделано для того, чтобы разработчик мог сразу обнаружить опечатку или логическую ошибку, а не гадать, почему у пользователя «внезапно» пропали права из-за лишнего пробела в строке кода. Проанализируем типичный пример ошибки:
// В режиме совместимости 8.2 это работало (возвращало Ложь)
// В режиме 8.3 это вызовет ошибку "Недопустимое значение параметра"
Если НЕ РольДоступна("КоммерческийДепартаментТолькоПросмотр") Тогда
// Логика ограничения прав
КонецЕсли;
Первым делом нам необходимо убедиться, что роль с указанным именем действительно существует в конфигурации. Часто путают Имя роли и ее Синоним. Функция РольДоступна() всегда ожидает именно внутреннее имя объекта (Name), которое задано в конфигураторе. Также проверьте наличие невидимых символов, таких как неразрывные пробелы или латинские буквы, похожие на кириллические.
Если вы уверены, что имя написано верно, но ошибка сохраняется, выясним причину с помощью отладчика. Попробуем вычислить выражение Метаданные.Роли.Найти("ИмяРоли"). Если результат равен Неопределено, значит, такой роли в системе нет. Как показывает практика (и обсуждение на форумах), иногда роль может присутствовать в интерфейсе, но отсутствовать в общем списке ролей конфигурации.
Чтобы ваш код не «падал» при отсутствии роли (например, если вы пишете универсальную обработку, которая должна работать в разных базах), рассмотрим способ проверки через коллекцию метаданных. Мы можем сначала проверить, существует ли роль, и только потом вызывать проверку доступности. Разберем, как это реализовать:
ИмяРоли = "КоммерческийДепартаментТолькоПросмотр";
Если Метаданные.Роли.Найти(ИмяРоли) <> Неопределено Тогда
Если РольДоступна(ИмяРоли) Тогда
// Роль есть в конфигурации и она назначена пользователю
КонецЕсли;
Иначе
// Роли с таким именем вообще не существует в этой базе
КонецЕсли;
Такой подход гарантирует, что система не вызовет исключение, даже если роль будет случайно удалена в будущем или конфигурация будет запущена с другими наборами прав.
Если ваша конфигурация построена на базе БСП (что актуально для большинства современных решений, таких как УТ 11, ERP, БП 3.0), настоятельно рекомендуем отказаться от использования стандартной функции РольДоступна(). Вместо нее следует использовать программный интерфейс общего модуля УправлениеДоступом. Рассмотрим преимущества функции УправлениеДоступом.ЕстьРоль():
Истина, если у пользователя есть роль «ПолныеПрава» или он является Администратором системы. Вам не нужно писать длинные конструкции с оператором ИЛИ.Пример использования БСП:
Если УправлениеДоступом.ЕстьРоль("КоммерческийДепартаментТолькоПросмотр") Тогда
// Доступ разрешен
КонецЕсли;
Проанализируем еще одну важную деталь. В примере из темы форума вызов проверки прав происходил в процедуре ОбновлениеОтображения(). Внимание: это крайне неэффективно!
Процедура ОбновлениеОтображения() (и аналогичные ей в управляемых формах, такие как ПриВыводеСтроки()) вызывается системой очень часто — при каждом движении мыши, нажатии клавиш или изменении фокуса. Несмотря на то, что платформа кеширует список ролей пользователя, постоянный вызов функции проверки прав создает лишнюю нагрузку на клиентский поток.
Разберем правильный алгоритм оптимизации:
Булево), например, ЭтоТолькоПросмотр.ПриСозданииНаСервере или ПриОткрытии).Пример оптимизированного кода:
// В модуле формы
Перем ЭтоТолькоПросмотр;
Процедура ПриОткрытии()
ЭтоТолькоПросмотр = РольДоступна("КоммерческийДепартаментТолькоПросмотр");
КонецПроцедуры
Процедура ОбновлениеОтображения()
Если ЭтоТолькоПросмотр Тогда
// Быстро меняем доступность элементов формы
ЭлементыФормы.КнопкаЗаписать.Доступность = Ложь;
КонецЕсли;
КонецПроцедуры
Иногда возникает ситуация, когда роль в конфигураторе точно есть, имя написано без ошибок, но 1С все равно выдает исключение. Проанализируем причину — часто это связано с так называемым «динамическим обновлением» конфигурации базы данных. Когда изменения вносятся без выгона пользователей, локальный кэш метаданных на компьютере клиента может «поплыть».
Если вы столкнулись с необъяснимым поведением РольДоступна(), выполните следующие действия:
%AppData%\1C\1Cv8).Подводя итог, можно сказать, что поведение РольДоступна() на платформе 8.3 требует от разработчика большей дисциплины. Используйте проверку через Метаданные.Роли.Найти() для универсального кода, функции БСП для типовых конфигураций и всегда кэшируйте результат проверки в переменных формы для обеспечения максимального быстродействия интерфейса.