Top.Mail.Ru
онлайн-митап
19 декабря в 17:00 МСК
Матрица компетенций: как инструмент для развития разработчика

Описание языка запросов для функции «ПриЗаполненииОграниченияДоступа» при работе с производительным методом RLS

Как я и обещал, продолжаю цикл статей по производительному методу RLS. Рассмотрим описание языка запросов, который прописывается в функции «ПриЗаполненииОграниченияДоступа». Без этой экспортной функции, прописанной в модуле менеджера объекта, ограничения доступа просто не будут работать в производительном методе.

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

Начнем с того, как выглядит сам синтаксис.

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

  • Вариант, когда чтение и изменение различаются:
"ПрисоединитьДополнительныеТаблицы
|ЭтотСписок КАК <Псевдоним>
|ЛЕВОЕ СОЕДИНЕНИЕ <Любая таблица> КАК <Псевдоним>
|ПО <Простое условие>
|… <Другие соединения>
|;
|РазрешитьЧтение

|ГДЕ
|        <Условие>
|  И/ИЛИ НЕ <Условие>
|  И/ИЛИ ВЫБОР
|          КОГДА <Условие>
|            ТОГДА <Условие>
|            ИНАЧЕ <Условие>
|         КОНЕЦ
|;
|РазрешитьИзменениеЕслиРазрешеноЧтение
|ГДЕ
|   <Условие> …";
  • Вариант, когда чтение и изменение одинаковые:
"ПрисоединитьДополнительныеТаблицы
|ЭтотСписок КАК <Псевдоним>
|ЛЕВОЕ СОЕДИНЕНИЕ <Любая таблица> КАК <Псевдоним>
|ПО <Простое условие>
|… <Другие соединения>
|;
|РазрешитьЧтениеИзменение

|ГДЕ
|        <Условие>
|  И/ИЛИ НЕ <Условие>
|  И/ИЛИ ВЫБОР
|          КОГДА <Условие>
|            ТОГДА <Условие>
|            ИНАЧЕ <Условие>
|         КОНЕЦ";

Теперь разберем, что же всё это значит. Выше мы видим два вариант кода, но на самом деле первый вариант — это расширение для случая, когда чтение и изменение таблицы объекта для пользователя должны отличаться.

Код состоит из нескольких блоков, в которых прописаны условия отбора доступа. Ниже описаны блоки и условия в них.

Блоки текста условий

  • ПрисоединитьДополнительныеТаблицы — строка подразумевает что будет блок с присоединением других таблиц метаданных. Соединение может быть только левым. Соединение может быть не только с основной таблицей (ЭтотСписок), но и между добавленными таблицами;
  • РазрешитьЧтениеИзменение — строка накладывает одинаковое условие на чтение и изменение объектов;
  • РазрешитьЧтение — строка накладывает ограничение только на чтение. Необходимо применять, когда условия на чтение и изменение различаются;
  • РазрешитьИзменениеЕслиРазрешеноЧтение — строка расширяет ограничение на изменение, т.е. если сработало условие на запрет чтения — объект не доступен, то на изменение уже проверяться не будет. И наоборот, если чтение доступно, то проверяется уже условие этого блока.

Возможные условия:

  1. Общие функции:
  • ЗначениеРазрешено(<Реквизит> [<проверяемые типы>] [, <уточнение сравнения 1> [, <уточнение сравнения 2>] …]);
  • ЧтениеОбъектаРазрешено (<так же, как для функции ЗначениеРазрешено>);
  • ЧтениеСпискаРазрешено (<так же, как для функции ЗначениеРазрешено>);
  • ЭтоАвторизованныйПользователь (<так же, как для функции ЗначениеРазрешено>);
  • Функции можно указать только в разделе РазрешитьИзменениеЕслиРазрешеноЧтение:

2. Функции можно указать только в разделе РазрешитьИзменениеЕслиРазрешеноЧтение:

  • ИзменениеОбъектаРазрешено (<так же, как для функции ЗначениеРазрешено>);
  • ИзменениеСпискаРазрешено (<так же, как для функции ЗначениеРазрешено>);

Проверяемые типы могут быть (значения непроверяемых типов запрещены, если не уточнены отдельно):

  • ТОЛЬКО <Имя таблицы>;
  • ТОЛЬКО (<Имя таблицы 1>, <Имя таблицы 2>, … );
  • КРОМЕ <Имя таблицы>;
  • КРОМЕ (<Имя таблицы 1>, <Имя таблицы 2>, … );

Уточнение сравнения может быть:

  • ПустаяСсылка КАК Ложь/Истина;
  • Неопределено КАК Ложь/Истина;
  • Null КАК Ложь/Истина;
  • Отключено КАК Ложь/Истина (только для функции ЗначениеРазрешено);
  • <Таблица> КАК Ложь/Истина (например, Справочник.Проекты КАК Истина).
  • ЕстьNull(<Реквизит >, <Выражение замены>) — вернет значение первого параметра, в случае, если оно не является NULL, и значение второго выражения, в противном случае. (ЕстьNULL(Владелец, Значение(Справочник.Файлы.ПустаяСсылка)))
  • Выразить (<Реквизит> КАК <Имя таблицы>) — приведение значения к типу (ВЫРАЗИТЬ(ВЫРАЗИТЬ(Владелец КАК Справочник.Файлы).ВладелецФайла КАК Справочник.Организации).Ссылка)
  • ПравоДоступа(<Право>, <Имя таблицы>) — Показывает установку права доступа к объекту метаданных (ПравоДоступа(Редактирование, Справочник.Организации));
  • РольДоступна(<Имя роли>) — Определяет доступность указанной роли (РольДоступна(БазовыеПрава)).

Пример того, как выглядит использование расширенных свойств сравнения в специальных функциях:

  • ЗначениеРазрешено (Владелец ТОЛЬКО Справочник.Организации).
  • ЗначениеРазрешено (Владелец КРОМЕ (Справочник.Проекты, Справочник.Номенклатура), ПустаяСсылка КАК Истина).
  • ЗначениеРазрешено (Владелец, Неопределено КАК Истина).

<Условие> предоставляет следующие стандартные виды сравнения:

  • <Реквизит> Равно | Не равно <предопределенное значение>;
  • <Реквизит> В списке | Не в списке <предопределенное значение 1>, …
  • <Реквизит> ЕСТЬ NULL;
  • ТипЗначения (<Реквизит>) = Тип (<Имя таблицы>).

Пример того, как выглядит использование стандартных видов сравнения:

  • ВидПоставщика = Значение(Перечисления.ВидыПоставщиков.Основной);
  • ВидПоставщика В (Значение(Перечисления.ВидыПоставщиков.Основной), Значение(Перечисления.ВидыПоставщиков.Дополнительный)).

<Условие> также представлено двумя модификаторами, которые указывают способ сложения результатов проверок (столбец результатов), выполненных в условии, если использовался реквизит табличной части или дополнительной таблицы, который может содержать несколько значений (столбец значений):

  • ДляВсехСтрок(<Условие>) — объединить результаты проверок в строках с помощью логического «И».
  • ДляОднойИзСтрок(<Условие>) — объединить результаты проверок в строках с помощью логического «ИЛИ» (это поведение по умолчанию, но есть случаи, когда поведения по умолчанию недостаточно).

Описание работы функций ограничения доступа

Предлагаю определить понятие «Значения доступа». Это реквизиты объекта, по которым мы организовываем отбор, содержащие ссылки на объекты ограничения: организации, контрагенты, склады.

Значения доступа могут быть разного типа и должны быть прописаны в определяемом типе «ЗначениеДоступа».

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

Данную функцию используем как основной способ ограничения доступа.

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

В разделах ограничения права «Чтение», блоки РазрешитьЧтение, РазрешитьЧтениеИзменение, значение реквизита будет проверяться в группах доступа с профилем, который предоставляет право «Чтение» списка. В разделах ограничения права «Изменение», блоки РазрешитьЧтениеИзменение, РазрешитьИзменениеЕслиРазрешеноЧтение, значение будет проверяться в группах доступа с профилем, который предоставляет право «Изменение» списка. Право «Добавление» на уровне записей приравнено праву «Изменение.

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

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

Используем, когда нужно сделать зависимость расчета прав на один объект от наличия прав на другой объект. Например, зависимость присоединенного файла от его владельца, строки журнала документов от документа, записи регистра сведений от регистратора и т.п.

Функция проверяет право на реквизит как на конкретный объект списка по его ссылке. Результат проверки всегда будет «Истина» для объектов, которые не участвуют в ограничении доступа (не указаны в процедуре ПриЗаполненииСписковСОграничениемДоступа общего модуля УправлениеДоступомПереопределяемый).

Следует иметь в виду, что ограничения доступа к документу в виде ЗначениеРазрешено(Организация) и в виде ЧтениеОбъектаРазрешено(Организация) являются разными. В первом случае проверяется разрешено ли значение в группах доступа с правами на документ, а во втором случае проверяется, что группа доступа с правами на документ предоставляет право «Чтение» на проверяемую организацию. Таким образом мы наследуем документу права реквизита «Организация»

Еще стоит учитывать, что в одном блоке можно использовать ЧтениеОбъектаРазрешено или ИзменениеОбъектаРазрешено — только один раз. А при последующем вызове шаблона «ДляОбъекта» необходимо передавать в параметр имя реквизита, пустая строка в параметре будет вызывать ошибку.

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

Используем только тогда, когда нужно сделать проверку без учета наличия ограничения по виду доступа «Пользователи» или «Внешние пользователи».

Функция работает, как отбор вида «Документ.Ответственный = &АвторизованныйПользователь». Для всех значений, кроме авторизованного пользователя результат проверки будет «Ложь».

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

Нужно использовать, когда нужно сделать зависимость права на один объект от права на список другого объекта. Например, журнал документов имеет несколько типов документов, права на разные типы документов предоставляются пользователям не полностью, а по частям. А значит нужно показывать только те строки журнала, которые соответствуют типам документов, на списки которых у пользователя есть права в ролях.

Функции проверяют наличие соответствующего права на список в целом, а не на конкретный объект.

Примеры типовых использований

1 Организация контрагент в шапке документа

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

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

  • Доступна организация
  • Доступен хотя бы один поставщик в ТЧ
Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
|  ЗначениеРазрешено(Организация)
|И ЗначениеРазрешено(Поставщики.Контрагент)";

3. Организация в шапке документа, контрагент в табличной части, достаточно одного разрешенного контрагента (если табличная часть пустая, тогда доступ по контрагенту разрешен)

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

4. Организация в шапке документа, контрагент в табличной части, и требуется, чтобы все контрагенты были разрешены (если табличная часть пустая, тогда доступ по контрагенту запрещен)

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

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

  • Хотя бы в одной строке есть доступная организация и поставщик
Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
|  ЗначениеРазрешено(Поставщики.Организация)
|И ЗначениеРазрешено(Поставщики.Контрагент)";

6. Организация и контрагент в табличной части, при этом требуется, чтобы все пары организации с контрагентом были разрешены

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

7. Организация и контрагент в табличной части, при этом требуется, чтобы одна из организаций и один из контрагентов были разрешены

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

8. Отправитель — измерение составного типа, при этом требуется проверять только ссылки Справочник.Склады

  • Отправитель – реквизит составного типа
  • Проверяем только когда отправитель – это склад
Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
|  ЗначениеРазрешено(Отправитель ТОЛЬКО Справочник.Склады)";

9. Перенос прав от объекта-владельца (например, на присоединенные файлы)

  • Права на файл наследуются от владельца файла
Ограничение.Текст =
"РазрешитьЧтение
|ГДЕ
|    ЧтениеОбъектаРазрешено(ВладелецФайла)
|;
|РазрешитьИзменениеЕслиРазрешеноЧтение
|ГДЕ
|    ИзменениеОбъектаРазрешено(ВладелецФайла)";

10. Ограничение по чтению владельца (например, журнал документов)

  • Журнал документов
  • Ограничение по чтению владельца
Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
|    ЧтениеОбъектаРазрешено(Ссылка)";

11. Организация и контрагент в шапке, при этом достаточно, чтобы было разрешение для одного из них, но при отключении ограничения по организациям, должно остаться ограничение по партнерам, а при отключении ограничения по партнерам должно остаться ограничение по организациям

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

12. Организация в шапке (Владелец), головная организация в справочнике организаций, при этом требуется, чтобы изменение было разрешено, когда разрешена организация в шапке, а чтение было разрешено

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

Тема не простая, не сильно освещенная. Основным источником для меня стал сайт ИТС.

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

Comments

So empty here ... leave a comment!

Добавить комментарий

Sidebar