ПравоДоступа, РольДоступна и RLS: как код узнаёт, что разрешено пользователю
Содержание
Права пользователя в 1С 8.3 проверяют программно двумя функциями платформы: ПравоДоступа("Изменение", Метаданные.Документы.РеализацияТоваровУслуг) отвечает, есть ли конкретное право на объект, а РольДоступна("ПолныеПрава") — назначена ли роль. Обе возвращают Булево и по умолчанию проверяют текущего пользователя. Для конкретной записи, закрытой ограничением RLS, этого мало: нужен запрос с РАЗРЕШЕННЫЕ или перехват исключения.
Типичная ситуация: в обработке есть кнопка «Перепровести документы за месяц». Кладовщик нажимает её, через минуту получает Нарушение прав доступа! на сороковом документе, а половина документов уже перепроведена. Проверка прав до начала операции решает эту проблему. Всё ниже — механизмы платформы, они одинаково работают в БП 3.0, ЗУП 3.1, УТ 11 и самописных конфигурациях.
Какой способ проверки прав выбрать
Методов несколько, и каждый отвечает на свой вопрос. Путаница между ними — главный источник ошибок.
| Задача | Чем проверять | Учитывает RLS |
|---|---|---|
| Есть ли у пользователя право на объект метаданных | ПравоДоступа() | Нет |
| Назначена ли текущему пользователю роль | РольДоступна() | Нет |
| Какие роли у другого пользователя | ПользовательИБ.Роли.Содержит() | Нет |
| Администратор ли пользователь | ПравоДоступа("Администрирование", Метаданные) | — |
| Видит ли пользователь конкретную запись | Запрос ВЫБРАТЬ РАЗРЕШЕННЫЕ | Да |
| Остановить код, если права нет | ВыполнитьПроверкуПравДоступа() | Да, при передаче значений полей |
| Отловить отказ при записи | Попытка … Исключение | Да |
💡 Правило выбора простое. Если важно, может ли пользователь в принципе работать с документами вида — ПравоДоступа. Если важно, к чему привязан интерфейс (показать кнопку бухгалтеру, скрыть от менеджера) — РольДоступна. Если важна конкретная запись — запрос или попытка записи.
Как проверить полные права пользователя одной строкой
В 1С нет встроенной функции вида HasFullRight. Английское имя ПравоДоступа — AccessRight, а РольДоступна — IsInRole. «Полные права» проверяют двумя способами, и они не равнозначны.
Через право «Администрирование»
Если ПравоДоступа("Администрирование", Метаданные) Тогда
// пользователь может администрировать информационную базу
КонецЕсли;
Вторым параметром передаётся сам объект Метаданные — корень конфигурации. Право «Администрирование» задаётся на уровне конфигурации и даёт управление пользователями, журналом регистрации, монопольным режимом. Этот способ не зависит от того, как названа роль в конкретной конфигурации.
Через роль ПолныеПрава
Если РольДоступна(Метаданные.Роли.ПолныеПрава) Тогда
// у пользователя роль «Полные права»
КонецЕсли;
Функция принимает и строку "ПолныеПрава", и объект метаданных роли. Объект надёжнее: если роль переименуют или удалят, ошибка всплывёт при проверке модуля, а не у пользователя в работе.
⚠️ Роль ПолныеПрава есть в типовых конфигурациях на БСП, но это не правило платформы. В самописной базе административная роль может называться иначе. Тогда опирайтесь на право «Администрирование».
В конфигурациях на БСП
В типовых решениях вместо прямых вызовов лучше использовать общий модуль Пользователи:
Если Пользователи.ЭтоПолныеПользователи() Тогда
// полноправный пользователь с учётом привилегированного режима
КонецЕсли;
Функция учитывает привилегированный режим и особенности ролей БСП. Поэтому в типовой конфигурации её результат ближе к тому, что видит программа, чем ручная проверка роли.
Проверка конкретного права через ПравоДоступа
Синтаксис функции:
ПравоДоступа(<Право>, <ОбъектМетаданных>, <Роль или ПользовательИБ>, <ИмяСтандартногоРеквизита>)
- 🔑 Право — строка с именем права:
"Чтение","Изменение"и т. д. - 📦 ОбъектМетаданных — например,
Метаданные.Справочники.Номенклатура. - 👤 Роль или пользователь — необязательный. Не указан — проверяется текущий пользователь.
- 🏷 Стандартный реквизит — необязательный, для прав на отдельный стандартный реквизит.
Основные имена прав, которые чаще всего проверяют в коде:
| Право | Для каких объектов | Что означает |
|---|---|---|
Чтение | справочники, документы, регистры | получение данных, в том числе запросом |
Добавление | справочники, документы | создание объекта программно |
Изменение | справочники, документы, регистры | запись изменений |
Удаление | справочники, документы | непосредственное удаление |
Просмотр | справочники, документы, регистры | открытие форм в интерфейсе |
Редактирование | справочники, документы | изменение через форму |
Проведение | документы | проведение программно |
ИнтерактивноеДобавление | справочники, документы | кнопка «Создать» в форме списка |
Использование | отчёты, обработки | запуск отчёта или обработки |
Администрирование | конфигурация | администрирование базы |
Различие «программных» и «интерактивных» прав важно. У пользователя может быть Добавление без ИнтерактивноеДобавление: документ создаётся только кодом обработки, а в форме списка кнопки нет.
Пример: перед массовым перепроведением проверяем все нужные права заранее, а не ждём отказа на середине.
&НаСервереБезКонтекста
Функция ЕстьПраваНаПерепроведение()
МетаДок = Метаданные.Документы.РеализацияТоваровУслуг;
Возврат ПравоДоступа("Проведение", МетаДок)
И ПравоДоступа("Изменение", МетаДок);
КонецФункции
Проверку прав делайте на сервере. На клиенте функция тоже работает, но кнопку можно обойти, а серверную проверку перед записью — нет. Скрытие команды в форме — удобство, а не защита.
Права на объекты метаданных: обход и отчёт
Иногда нужно не проверить одно право, а собрать картину: к каким документам у пользователя есть доступ. Это полезно при разборе обращения «не вижу документ» и при аудите ролей.
Пример ниже обходит все документы конфигурации и выводит те, что пользователь не может читать:
&НаСервере
Процедура ПоказатьЗакрытыеДокументы(ИмяПользователя)
УстановитьПривилегированныйРежим(Истина);
ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователя);
УстановитьПривилегированныйРежим(Ложь);
Если ПользовательИБ = Неопределено Тогда
Сообщить("Пользователь не найден: " + ИмяПользователя);
Возврат;
КонецЕсли;
Для Каждого МетаДок Из Метаданные.Документы Цикл
Если Не ПравоДоступа("Чтение", МетаДок, ПользовательИБ) Тогда
Сообщить("Нет чтения: " + МетаДок.Синоним);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Тот же цикл подходит для Метаданные.Справочники, Метаданные.Отчеты, Метаданные.Обработки. Для отчётов и обработок проверяйте право "Использование".
Проверка от имени роли
Третьим параметром можно передать не пользователя, а роль. Так проверяют саму роль, не привязываясь к людям:
ЕстьПраво = ПравоДоступа("Изменение",
Метаданные.Справочники.Контрагенты,
Метаданные.Роли.ДобавлениеИзменениеКонтрагентов);
Имя роли подставьте своё: в каждой конфигурации набор ролей разный. Такой вызов отвечает на вопрос «даёт ли эта роль право», а не «есть ли право у человека».
💡 Право пользователя — объединение прав всех его ролей. Если хотя бы одна роль даёт Изменение, пользователь его имеет. Запретить право одной ролью при разрешении другой нельзя.
РольДоступна и роли пользователя
РольДоступна() работает только для текущего сеанса. Чтобы узнать роли другого пользователя, читайте коллекцию Роли у объекта ПользовательИнформационнойБазы.
Текущий пользователь
Если РольДоступна("ДобавлениеИзменениеДокументовПоЗарплате") Тогда
Элементы.ФормаПересчитать.Видимость = Истина;
КонецЕсли;
Это типичный сценарий: показать или скрыть элемент формы по роли. Строковое имя роли здесь — для примера, подставьте роль своей конфигурации.
Другой пользователь
УстановитьПривилегированныйРежим(Истина);
ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени("Кладовщик");
Если ПользовательИБ <> Неопределено Тогда
ЕстьАдминРоль = ПользовательИБ.Роли.Содержит(Метаданные.Роли.ПолныеПрава);
КонецЕсли;
УстановитьПривилегированныйРежим(Ложь);
Получение списка пользователей ИБ требует административных прав. Поэтому обычному пользователю такой код без привилегированного режима выдаст ошибку.
Перечень всех ролей пользователя:
Для Каждого Роль Из ПользовательИБ.Роли Цикл
Сообщить(Роль.Имя + " — " + Роль.Синоним);
КонецЦикла;
Когда изменения ролей вступают в силу
Роли сеанса фиксируются при входе. Добавили пользователю роль — РольДоступна() в его открытом сеансе продолжит возвращать старое значение. Права обновятся после перезапуска 1С. Это частая причина обращений «роль дали, а кнопки нет».
Роли в типовых конфигурациях на БСП
В БП 3.0, ЗУП 3.1 и УТ 11 роли назначают не напрямую, а через профили групп доступа. Для проверки в коде БСП есть функция:
Если Пользователи.РолиДоступны("ПолныеПрава") Тогда
// …
КонецЕсли;
Она принимает имена ролей через запятую и учитывает привилегированный режим. В типовых конфигурациях это предпочтительнее голого РольДоступна.
RLS: почему ПравоДоступа говорит «да», а данных не видно
Ограничение доступа на уровне записей (RLS) задаётся в роли условием на право. Например, менеджер читает документы только своих организаций.
ПравоДоступа("Чтение", МетаДок) в этом случае вернёт Истина. Функция отвечает, выдано ли право вообще, а условие ограничения не учитывает. Поэтому для конкретной записи нужны другие приёмы.
Проверка чтения конкретной записи запросом
Ключевое слово РАЗРЕШЕННЫЕ отбрасывает записи, недоступные по RLS:
Функция ЗаписьДоступнаДляЧтения(Ссылка) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1
| Т.Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Т
|ГДЕ
| Т.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Возврат Не Запрос.Выполнить().Пустой();
КонецФункции
Пустой результат — запись закрыта ограничением или её нет. Без слова РАЗРЕШЕННЫЕ запрос к ограниченной таблице завершится ошибкой нарушения прав, если в выборку попадут недоступные записи.
Проверка права на изменение
Запрос отвечает только про чтение. Условие RLS на изменение проверяется при записи. Надёжный способ — попытка записи с перехватом ошибки (следующий раздел).
В конфигурациях на БСП 3.x с подсистемой «Управление доступом» есть готовые функции УправлениеДоступом.ЧтениеРазрешено(Ссылка) и УправлениеДоступом.ИзменениеРазрешено(Ссылка). Они проверяют доступ к объекту с учётом настроек групп доступа.
Привилегированный режим и RLS
УстановитьПривилегированныйРежим(Истина);
// здесь проверки прав и RLS не выполняются
УстановитьПривилегированныйРежим(Ложь);
Внутри привилегированного режима код видит и пишет всё. Текущее состояние возвращает функция ПривилегированныйРежим(). Включайте режим только на сервере и на минимальный участок кода, иначе пользователь через вашу обработку получит доступ к данным, закрытым ролями.
Как обработать ошибку «Нарушение прав доступа»
Если права нет, платформа вызывает исключение с текстом Нарушение прав доступа!. Оставлять его необработанным — плохо: пользователь видит окно ошибки, операция обрывается на середине.
Заранее: ВыполнитьПроверкуПравДоступа
Функция работает как ПравоДоступа, но вместо Ложь сразу вызывает исключение:
ВыполнитьПроверкуПравДоступа("Изменение", Метаданные.Справочники.Номенклатура);
// сюда код дойдёт, только если право есть
Удобно в начале серверной процедуры: одна строка вместо Если … Тогда ВызватьИсключение. Платформа также позволяет передать значения полей, чтобы проверка учла условия RLS для конкретных данных, — детали параметров смотрите в синтакс-помощнике своей версии платформы.
В момент записи: Попытка … Исключение
Попытка
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Исключение
ИнфоОбОшибке = ИнформацияОбОшибке();
ЗаписьЖурналаРегистрации("Перепроведение",
УровеньЖурналаРегистрации.Ошибка,
ДокументОбъект.Метаданные(),
ДокументОбъект.Ссылка,
ПодробноеПредставлениеОшибки(ИнфоОбОшибке));
Сообщить("Не удалось провести " + Строка(ДокументОбъект.Ссылка) + ": "
+ КраткоеПредставлениеОшибки(ИнфоОбОшибке));
КонецПопытки;
Глобальные функции КраткоеПредставлениеОшибки и ПодробноеПредставлениеОшибки есть в платформе с версии 8.3.17. На более ранних используйте ОписаниеОшибки() или модуль БСП ОбработкаОшибок.
⚠️ Не глушите исключение пустым блоком Исключение КонецПопытки. Ошибка прав пропадёт бесследно, пользователь решит, что всё записалось.
Собственный текст отказа
Свою проверку оформляйте понятным сообщением, а не системным текстом:
Если Не ПравоДоступа("Проведение", Метаданные.Документы.ПоступлениеТоваровУслуг) Тогда
ВызватьИсключение "Недостаточно прав для проведения поступлений. Обратитесь к администратору.";
КонецЕсли;
Где искать, кто и когда получил отказ: журнал регистрации, Администрирование → Обслуживание → Журнал регистрации в БП 3.0, отбор по уровню «Ошибка» и пользователю.
РольДоступна() или ПравоДоступа("Просмотр", …) при создании формы на сервере. Помните: это удобство, не защита.ПравоДоступа() или ВыполнитьПроверкуПравДоступа() в начале серверной процедуры.ВЫБРАТЬ РАЗРЕШЕННЫЕ для чтения, попытка записи для изменения. В БСП — УправлениеДоступом.ЧтениеРазрешено.ПользователиИнформационнойБазы.НайтиПоИмени() в привилегированном режиме, затем ПравоДоступа(…, ПользовательИБ) или Роли.Содержит().Частые вопросы
Что вернёт РольДоступна, если в базе нет ни одного пользователя?
Можно ли проверить права на реквизит документа?
ПравоДоступа("Редактирование", Метаданные.Документы.РеализацияТоваровУслуг.Реквизиты.Комментарий). Для стандартных реквизитов вроде Номер или Дата имя указывают четвёртым параметром.Почему у администратора ПравоДоступа возвращает Ложь?
Проведение у справочника или Использование у документа. Сверьте имя права с типом объекта. Ещё одна причина — опечатка в строке права.