Почему РольДоступна() перестала работать при переходе на 8.3 и как это исправить

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

Переход на новую версию платформы 1С или изменение режима совместимости конфигурации с 8.2 на 8.3 часто сопровождается неожиданными ошибками в коде, который годами работал стабильно. Одной из самых распространенных проблем является внезапный отказ встроенной функции РольДоступна(). В этой статье мы подробно разберем, почему возникает ошибка «Недопустимое значение параметра», рассмотрим изменения в логике платформы и научимся писать отказоустойчивый код для проверки прав доступа.

Анализируем причину ошибки: что изменилось в платформе 8.3

Разберем ситуацию, с которой сталкиваются многие разработчики: после обновления режима совместимости до версии 8.3 привычный вызов РольДоступна("ИмяРоли") начинает вызывать исключительную ситуацию (падение программы), если указанной роли не существует в дереве метаданных. Важно понимать: в режиме совместимости 8.2 платформа вела себя более лояльно. Если вы допускали опечатку в имени роли или обращались к роли, которая была удалена, функция просто возвращала значение Ложь, и выполнение кода продолжалось.

Начиная с версии 8.3.3, логика была намеренно ужесточена. Теперь система считает обращение к несуществующему объекту метаданных критической ошибкой программирования. Это сделано для того, чтобы разработчик мог сразу обнаружить опечатку или логическую ошибку, а не гадать, почему у пользователя «внезапно» пропали права из-за лишнего пробела в строке кода. Проанализируем типичный пример ошибки:


// В режиме совместимости 8.2 это работало (возвращало Ложь)
// В режиме 8.3 это вызовет ошибку "Недопустимое значение параметра"
Если НЕ РольДоступна("КоммерческийДепартаментТолькоПросмотр") Тогда 
    // Логика ограничения прав
КонецЕсли;

Шаг 1: Проверка наличия роли в метаданных

Первым делом нам необходимо убедиться, что роль с указанным именем действительно существует в конфигурации. Часто путают Имя роли и ее Синоним. Функция РольДоступна() всегда ожидает именно внутреннее имя объекта (Name), которое задано в конфигураторе. Также проверьте наличие невидимых символов, таких как неразрывные пробелы или латинские буквы, похожие на кириллические.

Если вы уверены, что имя написано верно, но ошибка сохраняется, выясним причину с помощью отладчика. Попробуем вычислить выражение Метаданные.Роли.Найти("ИмяРоли"). Если результат равен Неопределено, значит, такой роли в системе нет. Как показывает практика (и обсуждение на форумах), иногда роль может присутствовать в интерфейсе, но отсутствовать в общем списке ролей конфигурации.

Шаг 2: Внедрение «безопасной» проверки ролей

Чтобы ваш код не «падал» при отсутствии роли (например, если вы пишете универсальную обработку, которая должна работать в разных базах), рассмотрим способ проверки через коллекцию метаданных. Мы можем сначала проверить, существует ли роль, и только потом вызывать проверку доступности. Разберем, как это реализовать:


ИмяРоли = "КоммерческийДепартаментТолькоПросмотр";
Если Метаданные.Роли.Найти(ИмяРоли) <> Неопределено Тогда
    Если РольДоступна(ИмяРоли) Тогда
        // Роль есть в конфигурации и она назначена пользователю
    КонецЕсли;
Иначе
    // Роли с таким именем вообще не существует в этой базе
КонецЕсли;

Такой подход гарантирует, что система не вызовет исключение, даже если роль будет случайно удалена в будущем или конфигурация будет запущена с другими наборами прав.

Шаг 3: Использование функций Библиотеки стандартных подсистем (БСП)

Если ваша конфигурация построена на базе БСП (что актуально для большинства современных решений, таких как УТ 11, ERP, БП 3.0), настоятельно рекомендуем отказаться от использования стандартной функции РольДоступна(). Вместо нее следует использовать программный интерфейс общего модуля УправлениеДоступом. Рассмотрим преимущества функции УправлениеДоступом.ЕстьРоль():

  1. Отказоустойчивость: Она внутри себя уже содержит проверку на существование роли в метаданных и не вызывает исключения.
  2. Полные права: Функция автоматически возвращает Истина, если у пользователя есть роль «ПолныеПрава» или он является Администратором системы. Вам не нужно писать длинные конструкции с оператором ИЛИ.
  3. Профили и группы: Функция корректно отрабатывает сложные механизмы назначения прав через профили групп доступа.

Пример использования БСП:


Если УправлениеДоступом.ЕстьРоль("КоммерческийДепартаментТолькоПросмотр") Тогда
    // Доступ разрешен
КонецЕсли;

Оптимизация производительности: почему нельзя проверять роли «на лету»

Проанализируем еще одну важную деталь. В примере из темы форума вызов проверки прав происходил в процедуре ОбновлениеОтображения(). Внимание: это крайне неэффективно!

Процедура ОбновлениеОтображения() (и аналогичные ей в управляемых формах, такие как ПриВыводеСтроки()) вызывается системой очень часто — при каждом движении мыши, нажатии клавиш или изменении фокуса. Несмотря на то, что платформа кеширует список ролей пользователя, постоянный вызов функции проверки прав создает лишнюю нагрузку на клиентский поток.

Разберем правильный алгоритм оптимизации:

  1. Создайте в форме переменную модуля (или реквизит формы типа Булево), например, ЭтоТолькоПросмотр.
  2. Вычислите значение этой переменной один раз при открытии формы (в процедуре ПриСозданииНаСервере или ПриОткрытии).
  3. В процедурах обновления интерфейса используйте уже готовую переменную вместо вызова функции.

Пример оптимизированного кода:


// В модуле формы
Перем ЭтоТолькоПросмотр;

Процедура ПриОткрытии()
    ЭтоТолькоПросмотр = РольДоступна("КоммерческийДепартаментТолькоПросмотр");
КонецПроцедуры

Процедура ОбновлениеОтображения()
    Если ЭтоТолькоПросмотр Тогда
        // Быстро меняем доступность элементов формы
        ЭлементыФормы.КнопкаЗаписать.Доступность = Ложь;
    КонецЕсли;
КонецПроцедуры

Проблема динамического обновления и кэша

Иногда возникает ситуация, когда роль в конфигураторе точно есть, имя написано без ошибок, но 1С все равно выдает исключение. Проанализируем причину — часто это связано с так называемым «динамическим обновлением» конфигурации базы данных. Когда изменения вносятся без выгона пользователей, локальный кэш метаданных на компьютере клиента может «поплыть».

Если вы столкнулись с необъяснимым поведением РольДоступна(), выполните следующие действия:

  1. Завершите все сеансы пользователей.
  2. Выполните монопольное обновление конфигурации базы данных.
  3. Если проблема сохраняется на конкретном рабочем месте — очистите локальный кэш пользователя (папки %AppData%\1C\1Cv8).

Подводя итог, можно сказать, что поведение РольДоступна() на платформе 8.3 требует от разработчика большей дисциплины. Используйте проверку через Метаданные.Роли.Найти() для универсального кода, функции БСП для типовых конфигураций и всегда кэшируйте результат проверки в переменных формы для обеспечения максимального быстродействия интерфейса.

← На главную