ПриЗаполненииОграниченияДоступа — экспортная процедура модуля менеджера, в которой для универсального (производительного) ограничения доступа БСП описывается, какие записи объекта пользователь может читать и изменять. Текст пишется на собственном языке подсистемы «Управление доступом»: блоки РазрешитьЧтениеИзменение, РазрешитьЧтение, РазрешитьИзменениеЕслиРазрешеноЧтение, функции ЗначениеРазрешено, ЧтениеОбъектаРазрешено и другие. Без этой процедуры объект в производительном режиме на уровне записей не ограничивается.

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

Где живёт ограничение

Чтобы ограничение работало, нужно три вещи:

  1. Объект зарегистрирован в УправлениеДоступомПереопределяемый.ПриЗаполненииСписковСОграничениемДоступа.
  2. В модуле менеджера объекта есть процедура ПриЗаполненииОграниченияДоступа(Ограничение) Экспорт, в которой заполняется Ограничение.Текст (и при необходимости Ограничение.ТекстДляВнешнихПользователей).
  3. В ролях, дающих права на объект, стоят шаблоны ограничения БСП.
1С
// Модуль менеджера документа ЗаказПоставщику
Процедура ПриЗаполненииОграниченияДоступа(Ограничение) Экспорт

	Ограничение.Текст =
	"РазрешитьЧтениеИзменение
	|ГДЕ
	|	ЗначениеРазрешено(Организация)
	|	И ЗначениеРазрешено(Контрагент)";

КонецПроцедуры

Значения, по которым ограничивается доступ (организации, контрагенты, склады), называются значениями доступа. Их типы должны входить в определяемый тип ЗначениеДоступа и соответствовать видам доступа, описанным в конфигурации.

Синтаксис: блоки текста ограничения

Если чтение и изменение ограничиваются одинаково:

1С
"ПрисоединитьДополнительныеТаблицы
|ЭтотСписок КАК <Псевдоним>
|ЛЕВОЕ СОЕДИНЕНИЕ <Таблица> КАК <Псевдоним>
|	ПО <Простое условие>
|;
|РазрешитьЧтениеИзменение
|ГДЕ
|	<Условие>"

Если различаются:

1С
"РазрешитьЧтение
|ГДЕ
|	<Условие чтения>
|;
|РазрешитьИзменениеЕслиРазрешеноЧтение
|ГДЕ
|	<Дополнительное условие изменения>"
БлокНазначение
ПрисоединитьДополнительныеТаблицыНеобязательный. Только левые соединения; соединять можно и с основной таблицей (ЭтотСписок), и между присоединёнными
РазрешитьЧтениеИзменениеОдно условие на чтение и изменение
РазрешитьЧтениеУсловие только на чтение
РазрешитьИзменениеЕслиРазрешеноЧтениеДополнительное условие на изменение: проверяется только для записей, которые уже можно читать

Блоки разделяются точкой с запятой. Условия строятся из функций проверки, сравнений, И, ИЛИ, НЕ и конструкции ВЫБОР КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ.

Функции проверки

ЗначениеРазрешено

Основная функция. Ищет значение реквизита среди разрешённых в группах доступа пользователя, профили которых дают нужное право на список.

  • В блоках чтения (РазрешитьЧтение, РазрешитьЧтениеИзменение) проверяются группы с правом «Чтение».
  • В блоках изменения (РазрешитьЧтениеИзменение, РазрешитьИзменениеЕслиРазрешеноЧтение) — группы с правом «Изменение». Право «Добавление» на уровне записей приравнено к изменению.
  • Для значений, которые не являются значениями доступа, результат — Истина. Для Null и Неопределено — Ложь, если не уточнено иначе.

Если вид доступа отключён функциональной опцией или не используется в профиле группы, значение считается «Отключено». По умолчанию это даёт Истину; уточнение Отключено КАК Ложь меняет поведение — это нужно при объединении проверок через ИЛИ.

ЧтениеОбъектаРазрешено и ИзменениеОбъектаРазрешено

Проверяют право на объект, на который указывает реквизит, — то есть делают права одного объекта зависимыми от прав другого: файл от владельца, строку журнала от документа, запись регистра от регистратора. Для объектов, не зарегистрированных в списках с ограничением доступа, результат всегда Истина.

Разница с ЗначениеРазрешено(Организация) принципиальная. ЗначениеРазрешено проверяет, разрешена ли организация в группах доступа с правами на текущий список. ЧтениеОбъектаРазрешено(Организация) проверяет, разрешено ли пользователю читать саму запись справочника организаций — права наследуются.

ИзменениеОбъектаРазрешено допустима только в блоке РазрешитьИзменениеЕслиРазрешеноЧтение. В одном блоке функции этой пары используются один раз.

ЧтениеСпискаРазрешено и ИзменениеСпискаРазрешено

Проверяют право на список в целом по ролям, а не на конкретный объект. Пример — журнал документов: пользователь должен видеть только строки тех типов документов, на которые у него есть права. ИзменениеСпискаРазрешено — тоже только в блоке изменения.

ЭтоАвторизованныйПользователь

Работает как отбор «Реквизит = текущий пользователь», без учёта вида доступа «Пользователи». Для всех остальных значений — Ложь.

Вспомогательные функции

  • ЕстьNull(<Реквизит>, <Замена>);
  • Выразить(<Реквизит> КАК <Таблица>) — приведение типа, в том числе вложенное;
  • ПравоДоступа(<Право>, <Таблица>) — проверка права на объект метаданных;
  • РольДоступна(<Имя роли>);
  • ТипЗначения(<Реквизит>) = Тип(<Таблица>);
  • сравнения с предопределёнными значениями: =, <>, В (…), ЕСТЬ NULL.

Уточнения проверяемых типов и сравнения

Внутри функций проверки можно ограничить проверяемые типы составного реквизита:

  • ТОЛЬКО Справочник.Склады или ТОЛЬКО (Справочник.А, Справочник.Б) — значения остальных типов запрещены, если не уточнено иначе;
  • КРОМЕ Справочник.Проекты или КРОМЕ (…).

И уточнить результат для особых значений:

УточнениеСмысл
ПустаяСсылка КАК Истина/ЛожьКак трактовать пустую ссылку
Неопределено КАК Истина/ЛожьПустое значение составного типа
Null КАК Истина/ЛожьНет строки соединения или пустая табличная часть
Отключено КАК Истина/ЛожьВид доступа отключён (только для ЗначениеРазрешено)
<Таблица> КАК Истина/ЛожьЗначения указанного типа без проверки

Табличные части: ДляВсехСтрок и ДляОднойИзСтрок

ПриЗаполненииОграниченияДоступа: документ связан со значениями доступа в шапке и табличной части
ПриЗаполненииОграниченияДоступа: документ связан со значениями доступа в шапке и табличной части

Если реквизит взят из табличной части или присоединённой таблицы, значений много. Результаты строк объединяются:

  • ДляОднойИзСтрок(<Условие>) — по ИЛИ, достаточно одной строки. Это поведение по умолчанию;
  • ДляВсехСтрок(<Условие>) — по И, должны пройти все строки.

Модификатор оборачивает условие целиком, поэтому важно, что именно внутри: условие по паре реквизитов в одной строке или два независимых условия.

Двенадцать типовых ограничений

1. Организация и контрагент в шапке — оба разрешены.

1С
"РазрешитьЧтениеИзменение
|ГДЕ
|	ЗначениеРазрешено(Организация)
|	И ЗначениеРазрешено(Контрагент)"

2. Организация в шапке, контрагенты в табличной части — достаточно одного разрешённого.

1С
"РазрешитьЧтениеИзменение
|ГДЕ
|	ЗначениеРазрешено(Организация)
|	И ЗначениеРазрешено(Поставщики.Контрагент)"

При пустой табличной части проверка вернёт Ложь (там Null) — документ будет недоступен.

3. То же, но документ с пустой табличной частью доступен.

1С
"РазрешитьЧтениеИзменение
|ГДЕ
|	ЗначениеРазрешено(Организация)
|	И ЗначениеРазрешено(Поставщики.Контрагент, Null КАК Истина)"

4. Должны быть разрешены все контрагенты табличной части.

1С
"РазрешитьЧтениеИзменение
|ГДЕ
|	ЗначениеРазрешено(Организация)
|	И ДляВсехСтрок(ЗначениеРазрешено(Поставщики.Контрагент))"

5. Организация и контрагент в табличной части — достаточно одной строки, где разрешены оба.

1С
"РазрешитьЧтениеИзменение
|ГДЕ
|	ЗначениеРазрешено(Поставщики.Организация)
|	И ЗначениеРазрешено(Поставщики.Контрагент)"

6. Во всех строках разрешены и организация, и контрагент.

1С
"РазрешитьЧтениеИзменение
|ГДЕ
|	ДляВсехСтрок(
|		ЗначениеРазрешено(Поставщики.Организация)
|		И ЗначениеРазрешено(Поставщики.Контрагент))"

7. Хотя бы одна организация и хотя бы один контрагент, не обязательно в одной строке.

1С
"РазрешитьЧтениеИзменение
|ГДЕ
|	ДляОднойИзСтрок(ЗначениеРазрешено(Поставщики.Организация))
|	И ДляОднойИзСтрок(ЗначениеРазрешено(Поставщики.Контрагент))"

8. Составной реквизит — проверять только склады.

1С
"РазрешитьЧтениеИзменение
|ГДЕ
|	ЗначениеРазрешено(Отправитель ТОЛЬКО Справочник.Склады)"

Помните: с ТОЛЬКО значения других типов будут запрещены. Если отправителем может быть и организация, добавьте уточнение Справочник.Организации КАК Истина или используйте КРОМЕ.

9. Права присоединённого файла наследуются от владельца.

Наследование прав: присоединённые файлы получают доступ от объекта-владельца
Наследование прав: присоединённые файлы получают доступ от объекта-владельца
1С
"РазрешитьЧтение
|ГДЕ
|	ЧтениеОбъектаРазрешено(ВладелецФайла)
|;
|РазрешитьИзменениеЕслиРазрешеноЧтение
|ГДЕ
|	ИзменениеОбъектаРазрешено(ВладелецФайла)"

10. Журнал документов — по праву чтения самого документа.

1С
"РазрешитьЧтениеИзменение
|ГДЕ
|	ЧтениеОбъектаРазрешено(Ссылка)"

11. Организация ИЛИ контрагент, и при отключении одного вида доступа работает второй.

1С
"РазрешитьЧтениеИзменение
|ГДЕ
|	ЗначениеРазрешено(Организация, Отключено КАК Ложь)
|	ИЛИ ЗначениеРазрешено(Контрагент, Отключено КАК Ложь)"

Без Отключено КАК Ложь отключённый вид доступа дал бы Истину, и через ИЛИ открылся бы весь список.

12. Чтение по организации, её головной организации и обособленным подразделениям; изменение — только по организации в шапке.

1С
"ПрисоединитьДополнительныеТаблицы
|ЭтотСписок КАК ЭтотСписок
|ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Организации КАК Владельцы
|	ПО Владельцы.Ссылка = ЭтотСписок.Владелец
|ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Организации КАК Подразделения
|	ПО Подразделения.ГоловнаяОрганизация = Владельцы.Ссылка
|;
|РазрешитьЧтение
|ГДЕ
|	ЗначениеРазрешено(Владелец)
|	ИЛИ ЗначениеРазрешено(Владельцы.ГоловнаяОрганизация, ПустаяСсылка КАК Ложь)
|	ИЛИ ЗначениеРазрешено(Подразделения.Ссылка, Null КАК Ложь)
|;
|РазрешитьИзменениеЕслиРазрешеноЧтение
|ГДЕ
|	ЗначениеРазрешено(Владелец)"

Типичные ошибки

  • Объект не зарегистрирован в списках с ограничением. Процедура в менеджере есть, но не вызывается, а ЧтениеОбъектаРазрешено по этому объекту возвращает Истину.
  • Путаница ИЛИ и Отключено. Объединение через ИЛИ без Отключено КАК Ложь открывает доступ при отключении любого вида доступа.
  • ТОЛЬКО без уточнений. Значения других типов составного реквизита оказываются запрещены — документы «пропадают».
  • ИзменениеОбъектаРазрешено в блоке чтения. Функции изменения допустимы только в РазрешитьИзменениеЕслиРазрешеноЧтение.
  • Тяжёлые присоединения. Каждое соединение увеличивает объём ключей доступа и время их обновления. Если ограничение тормозит, сначала проверьте, нужны ли все присоединённые таблицы.
  • Забыли про внешних пользователей. Если в конфигурации есть внешние пользователи, для них задаётся отдельный текст.
Сформулируйте правило словами («видит документы своих организаций, если хотя бы один контрагент разрешён») и только потом переводите его на язык ограничений. Большинство ошибок в RLS — это неточно понятое требование, а не синтаксис.

Подробная спецификация языка есть в документации к БСП на ИТС; при обновлении библиотеки сверяйтесь с ней. Если ограничения доступа уже работают, но список документов открывается долго, это задача для аудита производительности; проверку и исправление чужих ограничений делаю в рамках аудита 1С и доработки 1С.

Итог

  • ПриЗаполненииОграниченияДоступа в модуле менеджера задаёт текст ограничения; объект ещё нужно зарегистрировать в ПриЗаполненииСписковСОграничениемДоступа.
  • Блоки: РазрешитьЧтениеИзменение или пара РазрешитьЧтение + РазрешитьИзменениеЕслиРазрешеноЧтение, при необходимости с ПрисоединитьДополнительныеТаблицы.
  • ЗначениеРазрешено проверяет значение в группах доступа, ЧтениеОбъектаРазрешено наследует права другого объекта.
  • Для табличных частей используйте ДляВсехСтрок и ДляОднойИзСтрок, для особых значений — уточнения Null, ПустаяСсылка, Отключено.