Введение в подсистему ACL¶
В данном разделе представлена основная информация о работе подсистемы ACL, её настройках и возможностях.
ACL (access control list) в TESSA - это механизм, который для объектов системы (карточек) производит расчёт доступа на чтение, записывая полученный результат в специальную таблицу (ACL), а также своевременно обновляет результат при изменении объектов системы.
ACL используется для манипуляции со сложными расчётами доступа на чтение карточки в фоновом режиме, тем самым улучшая производительность системы для проверки доступа на чтение как одной карточки, так и множества карточек, а также упрощая настройку представлений системы, которые должны отображать только те данные, которые пользователь должен видеть, в соответствии с его правами.
Note
Подсистема ACL является платным модулем лицензии, а также входит в состав лицензии Enterprise. Если лицензия на модуль ACL отсутствует, то расчёт ACL не будет запускаться по расписанию, при запуске расчёта через API будет сгенерирована ошибка, а при открытии карточки “Правило расчёта ACL”, будет отображаться предупреждение:
Для настройки расчётов доступа к карточкам, а также для определения моментов для перерасчёта доступа в системе используются правила расчёта ACL.
Правило расчёта ACL¶
Это объект системы, с помощью которого система производит расчёт ACL для карточек, а также определяет в какие моменты записи ACL для карточек должны быть перерасчитаны.
Правила расчёта ACL в TESSA могут быть реализованы различными способами:
- С помощью карточки типа “Правило расчёта ACL”.
- Программно путём реализации методов правила кодом на языке C#.
Первый способ рекомендован для использования в ситуациях, когда это возможно, т.к. проще в настройке и отладке.
Второй способ позволяет использовать все возможности языка программирования C# для достижения необходимо результата, но требует опыта разработки и понимания концепции.
Для карточек правил расчёта ACL могут быть разработаны расширения, которые подключаются в поле карточки Расширения. Данные расширения могут иметь интерфейс UI, описанный типом карточки Диалог, могут фильтровать или дополнять список обрабатываемых карточек при расчёте ACL и модифицировать полученный правилом расчёта ACL результат.
Карточка “Правило расчёта ACL”¶
Данный тип карточки используется для настройки правил расчёта ACL в системе.
Основная вкладка¶
Пример основной вкладки карточки для правила расчёта ACL “Автор”:
Пример основной вкладки карточки для правила расчёта ACL, использующей умные роли:
Данная карточка имеет следующие настройки:
-
Название - название правила расчёта ACL.
-
Описание - описание правила расчёта ACL.
-
Отключить правило расчёта ACL - флаг определяет, должно ли данное правило быть отключено. По отключённым правилам записи ACL для карточек не рассчитываются, а рассчитанные будут удалены.
-
Использовать умные роли - флаг определяет, каким образом работает данное правило - рассчитывает роли для ACL напрямую, или использует для этого умные роли. Влияет на то, какие настройки доступны.
-
Типы - определяет список типов карточек и типов документов, для которых данное правило должно применяться. Наравне с одиночными значениями для выбора доступны группы ссылок с типами “Тип карточки” и “Тип документа”.
-
Запрос SQL для получения ролей (доступно, если не используются умные роли) - запрос к базе данных, который должен возвращать набор ролей, записываемых в ACL. Может работать как в режиме выборки по одной карточке, так и в режиме выборки по нескольким карточкам. Для того, чтобы запрос работал в режиме выборки по нескольким карточкам, в нём должны использоваться особые плейсхолдеры, которые позволяют задействовать запрос для получения списка ролей для нескольких карточек сразу.
Список плейсхолдеров:
-
#with_id(<text>)
- используется для получения идентификатора карточки в режиме выборки по нескольким карточкам, заменяется на<text>
. Не используется в режиме выборки по одной карточке. -
#when_id(<text>)
- используется для сравнения идентификатора карточки в режиме выборки по нескольким карточкам, заменяется на<text> in <список_идентификаторов_карточек>
. В режиме выборки по одной карточке заменяется на<text> = @CardID
. -
#order_by_id(<text>)
- используется для сортировки результата по идентификатору карточки в режиме выборки по нескольким карточкам, заменяется наORDER BY <text>
. Не используется в режиме выборки по одной карточке.
Note
Пример запроса с реализованной выборкой по множеству карточек, когда в качестве роли для ACL выступает сотрудник в поле “Автор документа”:
SELECT [AuthorID] #with_id([ID]) FROM [DocumentCommonInfo] WITH(NOLOCK) WHERE #when_id([ID]) AND [AuthorID] is not NULL #order_by_id([ID])
-
-
Генератор умных ролей (доступно, если используются умные роли) - генератор умных ролей, умные роли которого используются в качестве записей для ACL.
-
Запрос SQL для получения владельцев умных ролей по карточке (доступно, если используются умные роли) - запрос к базе данных, который должен возвращать набор владельцев умных ролей, созданных указанным генератором умных ролей. Полученные по данным владельцам умные роли записываются в ACL. Может работать как в режиме выборки по одной карточке, так и в режиме выборки по нескольким карточкам. Для того, чтобы запрос работал в режиме выборки по нескольким карточкам, в нём должны использоваться особые плейсхолдеры, которые позволяют задействовать запрос для получения списка ролей для нескольких карточек сразу.
Список плейсхолдеров:
-
#with_id(<text>)
- используется для получения идентификатора карточки в режиме выборки по нескольким карточкам, заменяется на, <text>
. Не используется в режиме выборки по одной карточке. -
#when_id(<text>)
- используется для сравнения идентификатора карточки в режиме выборки по нескольким карточкам, заменяется на<text> in <список_идентификаторов_карточек>
. В режиме выборки по одной карточке заменяется на<text> = @CardID
. -
#order_by_id(<text>)
- используется для сортировки результата по идентификатору карточки в режиме выборки по нескольким карточкам, заменяется наORDER BY <text>
. Не используется в режиме выборки по одной карточке.
Note
Пример запроса с реализованной выборкой по множеству карточек, когда в качестве идентификатора владельца умной роли используется идентификатор подразделения:
SELECT [DepartmentID] #with_id([ID]) FROM [DocumentCommonInfo] WITH(NOLOCK) WHERE #when_id([ID]) AND [DepartmentID] is not NULL #order_by_id([ID])
-
-
Запрос SQL для получения карточек по владельцу умной роли (доступно, если используются умные роли) - запрос к базе данных, который должен возвращать набор карточек по идентификатору владельца умной роли.
Запрос имеет следующие параметры:
@CardID
- идентификатор карточки, запустившей выполнение триггера.
Данный запрос поддерживает плейсхолдеры, описанные в пункте Плейсхолдеры запросов для получения карточек.
-
Расширения - список расширений, подключенных к правилу расчёта ACL. Настройки включенных расширений добавляются в блок “Расширения”.
Расширения позволяют дополнительно фильтровать список обрабатываемых правилом карточек или модифицировать результат расчёта ACL.
-
Запрос SQL для получения обновляемых карточек по умолчанию - запрос к базе данных, который используется для определения списка карточек для обновления ACL при срабатывании триггера, если в настройках триггера не задан аналогичный запрос.
Запрос имеет следующие параметры:
@CardID
- идентификатор карточки, запустившей выполнение триггера.
Данный запрос поддерживает плейсхолдеры, описанные в пункте Плейсхолдеры запросов для получения карточек.
-
Таблица “Триггеры” - таблица с настройками триггеров, при срабатывании которых система производит перерасчёт ACL для определённого набора карточек. Проверка триггеров производится системой при изменении карточек.
Каждый триггер имеет следующие настройки:
-
Название - название триггера.
-
Использовать типы правила - флаг определяет, что данный триггер должен выполняться для типов карточек и типов документов, указанных в поле Типы в основных настройках правила расчёта ACL. При установке данного флага поле Типы триггера скрывается.
-
Типы - типы карточек и типы документов, для которых проверка данного триггера выполняется. Скрывается, если установлен флаг Использовать типы правила. Наравне с одиночными значениями для выбора доступны группы ссылок с типами “Тип карточки” и “Тип документа”.
-
Обновлять асинхронно - флаг определяет, что при срабатывании триггера обновление ACL должно производиться асинхронно с использованием Chronos.
-
Обновлять ACL только проверяемой карточки - флаг определяет, что при срабатывании триггера перерасчёт ACL должен быть выполнен только для карточки, запустившей проверку триггера. При установке флага поле Запрос SQL для получения обновляемых карточек недоступно.
-
Запрос SQL для получения обновляемых карточек - запрос к базе данных, который используется для определения списка карточек для обновления ACL при срабатывании триггера. Если запрос не задан, то используется запрос из поля Запрос SQL для получения обновляемых карточек по умолчанию. Если там запрос также не задан, то ACL перерасчитывается для всех карточек с типом карточки или типом документа, указанным в поле Типы основной вкладки.
Запрос имеет следующие параметры:
@CardID
- идентификатор карточки, запустившей выполнение триггера.
Данный запрос поддерживает плейсхолдеры, описанные в пункте Плейсхолдеры запросов для получения карточек.
-
Проверять условия через оператор “И” - флаг определяет, что для срабатывания триггера необходимо, чтобы каждое условие из списка было выполнено. Иначе достаточно выполнения хотя бы одного условия.
-
Список условий - набор условий, которые проверяются при проверке триггера. Если одно или все условия, в зависимости от настроек триггера, выполнены, то система производит запуск перерасчёта ACL для набора карточек, определённого данным триггером. Про подсистему условий можно прочитать в разделе Типы условий.
-
Вкладка “Валидация”¶
Пример вкладки “Валидация:
На данной вкладке можно произвести валидацию одного или всех правил расчёта ACL с помощью соответствующих кнопок.
В блоке “Ошибки” отображаются ошибки, которые возникали при расчёте ACL для данного правила. Ошибки записываются в виде карточек с типом “Ошибка”, при удалении карточек также будут удалены строки из таблицы. При двойном нажатии на строку в представлении откроется карточка ошибки.
Ошибки записываются только при установке флага Включить логирование ошибок. В противном случае ошибки записываются только в серверный лог при расчёте на сервере (синхронно) и в лог Chronos при расчёте в плагине (асинхронно).
Плейсхолдеры запросов для получения карточек¶
При определении списка карточек, которые должны обрабатываться правилом расчёта ACL, система должна проверить для каждой карточки её тип и другие атрибуты, проверяемые добавленными расширениями правила расчёта ACL. Например, при добавлении расширения Проверка состояния система должна дополнительно проверить состояние документа.
Чтобы оптимизировать определение списка карточек, обрабатываемых правилом расчёта ACL, в тексте запросов для получения идентификаторов карточек добавлена поддержка плейсхолдеров, которые внедряют требуемые проверки в текст запроса.
Note
Данные плейсхолдеры не являются обязательными для применения, но они полезны для оптимизации работы подсистемы ACL, особенно когда запрос для получения идентификаторов карточек может вернуть большое число записей.
Система поддерживает следующие плейсхолдеры, которые можно использовать в запросах для получения списка карточек:
-
#when_id(<text>)
- плейсхолдер для фильтрации по идентификатору карточки, инициировавшей выполнение запроса. Идентификтаор карточки определяется параметром@CardID
запроса.В тексте запроса заменяется на
<text> = @CardID
. -
#rule_result
- плейсхолдер для добавления в запрос набора колонок, запрашиваемых правилом расчёта ACL и расширениями правила расчёта ACL. Подставляемое значение всегда начинается с запятой как продолжение списка колонок.Например, при добавлении правилом расчёта ACL в вывод запроса типа карточки из таблицы
Instances
указанный плейсхолдер заменяется на, [Instances].[TypeID]
.Important
Для корректной работы плейсхолдера требуется наличие плейсхолдера
#rule_join(<text>)
в тексте запроса. -
#rule_join(<text>)
- плейсхолдер для добавления в запрос конструкций присоединения таблиц и подзапросов, запрашиваемых правилом расчёта ACL и расширениями правила расчёта ACL, где<text>
определяет имя колонки, к которой идёт присоединение таблицы или подзапроса.Например, при добавлении правилом расчёта ACL таблицы
Instances
для фильтрации по типу карточки плейсхолдер заменяется наINNER JOIN [Instances] WITH(NOLOCK) ON [Instances].[ID] = <text>
. -
#rule_filter
- плейсхолдер для добавления в запрос дополнительных условий фильтрации, добавляемых правилом расчёта ACL и расширениями правила расчёта ACL.Условия добавляются с конструкцией
AND
в начале для присоединения их к уже существующим условиям фильтрации запроса. Если в запросе нет иных условий фильтрации, то перед плейсхолдером следует добавить всегда выполняющееся условие.Например, при добавлении правилом расчёта ACL фильтрации по типу карточки плейсхолдер заменяется на
AND [Instances].[TypeID] IN (<список типов карточек>)
.Important
Для корректной работы плейсхолдера требуется наличие плейсхолдера
#rule_join(<text>)
в тексте запроса.
Note
Пример запроса с использованием плейсхолдеров, когда в качестве идентификатора владельца умной роли используется идентификатор подразделения:
SELECT [dci].[ID] #rule_result
FROM [DocumentCommonInfo] [dci] WITH(NOLOCK)
#rule_join([dci].[ID])
WHERE #when_id([dci].[DepartmentID]) #rule_filter
В результате модификации запроса правилом расчёта ACL с настроенным типом “Договор” и расширением “По состоянию” с настроенными состояниями “Проект” и “Зарегистрирован” запрос будет выглядеть следующим образом:
SELECT [dci].[ID], [AclGenerationRuleData].[TypeID] AS [.TypeID], COALESCE([KrDocStatesAclExtension].[StateID], 0)
FROM [DocumentCommonInfo] [dci] WITH(NOLOCK)
INNER JOIN [Instances] AS [AclGenerationRuleData] WITH (NOLOCK) ON [dci].[ID] = [AclGenerationRuleData].[ID]
LEFT JOIN [KrApprovalCommonInfo] [KrDocStatesAclExtension] WITH(NOLOCK)
ON [KrDocStatesAclExtension].[MainCardID] = [dci].[ID]
WHERE [dci].[DepartmentID] = @CardID
AND [AclGenerationRuleData].[TypeID] IN ('335f86a1-d009-012c-8b45-1f43c2382c2d')
AND COALESCE([KrDocStatesAclExtension].[StateID], 0) IN (0, 6)
Расширение карточки “Правило расчёта ACL”¶
Данные расширения реализуются программно.
Чтобы создать расширение нужно:
-
Создать объект с типом
AclGenerationRuleExtensionDescriptor
, который содержит настройки расширения. Данный объект описания может быть реализован в статическом классе или зарегистрирован в контейнере зависимостей с уникальным именем. В данном объекте указывается идентификатор диалога, настройки которого подставляются в карточку “Правило расчёта ACL” в блок “Расширения”. -
Реализовать класс с интерфейсом
IAclGenerationRuleExtension
. Для удобства разработки в качестве основы можно использовать базовый классAclGenerationRuleExtensionBase
. Данный класс должен через свойствоDescriptor
возвращать объект, описанный в пункте 1. Класс необходимо зарегистрировать с помощьюIAclGenerationRuleExtensionResolver
, указав в качестве ключа идентификатор объекта, созданного в пункте 1.
Программное правило расчёта ACL¶
Чтобы создать программное правило расчёта ACL нужно:
-
Реализовать класс с интерфейсом
IAclGenerationRule
. Для удобства разработки в качестве основы можно использовать базовый классAclGenerationRuleBase
. В нём содержится логика получения ролей по карточкам. -
Реализовать класс с интерфейсом
IAclGenerationRuleProvider
и зарегистрировать его в контейнере зависимостей с уникальным именем. Данный объект должен вернуть одно или несколько программных правил расчёта ACL, созданных в пункте 1.
Расчёт ACL¶
Система может производить расчёт ACL несколькими способами:
-
Синхронно - расчёт производится в момент непосредственного сохранения объекта, вызвавшего расчёт ACL. Срабатывает, когда изменение затрагивает перерасчёт ACL для небольшого количества карточек при срабатывании триггера.
-
Асинхронно - расчёт производится в плагине Chronos’а, который выполняет логику расчёта ACL. При выполнении асинхронного расчёта ACL создаётся операция в таблице операций. Срабатывает, когда изменение затрагивает перерасчёт ACL для большого количества карточек при срабатывании триггера, или если в триггере установлен флаг Обновлять асинхронно.
-
Полный перерасчёт - расчёт производится асинхронно в отдельном плагине, который запускает полный перерасчёт ACL для правила. Данный режим актуален только для карточек правила расчёта ACL (для программных правил его можно реализовать отдельно, при необходимости). Срабатывает при изменении карточки правила расчёта ACL, а также при отключении/включении правила, удалении карточки.
Расчёт ACL может быть запущен следующими способами:
-
При создании/изменении/удалении правила расчёта ACL. В таком случае расчёт запускается в режиме Полный перерасчёт.
-
При срабатывании триггера на создание/изменение/удаление карточки. В таком случае расчёт запускается синхронно и переходит в асинхронный режим автоматически при необходимости.
-
В случае добавления новой умной роли для правил расчёта ACL, которая использует соответствующий генератор умных ролей, будет вызван асинхронный перерасчёт для карточек, возвращаемых запросом Запрос SQL для получения карточек по владельцу умной роли.
-
Через расширения можно самостоятельно запускать перерасчёт одного или нескольких правил ACL для набора карточек или по триггерам. Для этого следует использовать объект
IAclManager
. -
Через тайл “Перерасчитать правило расчёта ACL” на левой панели карточки “Правило расчёта ACL” можно запустить перерасчёт данного правила расчёта. Перерасчёт выполняется синхронно и переходит в асинхронный режим автоматически при необходимости. Тайл доступен администраторам системы.
-
Через тайл “Системные”->”Перерасчитать ACL карточки” на левой панели любой карточки можно запустить перерасчёт ACL для указанной карточки. Перерасчёт выполняется синхронно. Тайл доступен администраторам системы.