ПравоДоступа, РольДоступна и RLS: как код узнаёт, что разрешено пользователю

· 9 мин

Содержание

Права пользователя в 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, отбор по уровню «Ошибка» и пользователю.

Что вам нужно проверить?

Частые вопросы

Что вернёт РольДоступна, если в базе нет ни одного пользователя?
Пустой список пользователей означает, что сеанс работает без ограничений. Такие базы встречаются в разработке. Перед вводом в эксплуатацию заведите хотя бы одного пользователя с административной ролью — иначе проверки прав в коде теряют смысл.
Можно ли проверить права на реквизит документа?
Да. Для реквизита, добавленного разработчиком, передайте его объект метаданных вторым параметром: ПравоДоступа("Редактирование", Метаданные.Документы.РеализацияТоваровУслуг.Реквизиты.Комментарий). Для стандартных реквизитов вроде Номер или Дата имя указывают четвёртым параметром.
Почему у администратора ПравоДоступа возвращает Ложь?
Обычно проверяют право, неприменимое к объекту: Проведение у справочника или Использование у документа. Сверьте имя права с типом объекта. Ещё одна причина — опечатка в строке права.
Учитывает ли ПравоДоступа роли из расширения конфигурации?
Да, если расширение подключено и роль из него назначена пользователю. Права сеанса складываются из ролей основной конфигурации и расширений.
Как проверить права во внешней обработке?
Так же, теми же функциями, в серверной процедуре формы. Для запуска самой обработки нужно право на открытие внешних обработок, его задают в роли на уровне конфигурации.