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