6.2.6.1. Ограничения
Ограничения (Constraints) можно наложить на различные действия с экземплярами сущностей. В отличие от разрешений, которые накладываются на класс сущностей, ограничения накладываются на конкретные экземпляры, не соответствующие заданным условиям. Ограничения можно накладывать на чтение, создание, модификацию и удаление сущностей. Кроме того, можно задать специальные ограничения, не привязанные к этим четырем действиям.
Пользователь получает список ограничений от всех групп начиная со своей и вверх по иерархии. Тем самым реализуется принцип: чем ниже пользователь в иерархии групп, тем больше у него ограничений. |
Следует отметить, что все ограничения проверяются при операциях с данными, осуществляемых клиентом через стандартный DataManager. В случае несоответствия проверяемой сущности условиям ограничений при создании, модификации или удалении, выбрасывается исключение RowLevelSecurityException
.
Существует несколько типов проверки ограничений: проверка в базе данных, проверка в памяти, проверка в базе данных и памяти.
-
Для ограничений с проверкой в базе данных условия задаются с помощью фрагментов выражений на языке JPQL. Эти фрагменты подставляются в каждый запрос, выбирающий экземпляры данной сущности. Таким образом, сущности, не соответствующие условиям ограничения, отфильтровываются на уровне базы данных. Ограничение с проверкой в базе данных можно задать только на чтение сущностей.
-
Для ограничений с проверкой в памяти условия задаются с помощью выражений на языке Groovy. Эти выражения выполняются для каждой сущности проверяемого графа объектов, и если какая-либо сущность не соответствует условиям - она отфильтровывается из графа объектов.
-
Ограничения с проверкой в базе данных и памяти являются комбинацией первых двух вариантов.
Для создания ограничения в экране Access Groups выберите группу, на которую нужно наложить ограничение, перейдите на вкладку Constraints и нажмите Create:
Далее выберите сущность в выпадающем списке Entity Name, тип операции в выпадающем списке Operation Type, и тип проверки в выпадающем списке Check Type. В зависимости от выбранного тип проверки вам нужно будет задать JPQL условия в полях Join Clause и Where Clause и/или Groovy условие в поле Groovy Script. Кроме того вы можете воспользоваться мастером созданий ограничений доступа (Constraint Wizard). Мастер позволяет визуально задавать Groovy и JPQL условия. Если вы выбрали тип операции "Специальные операции", появляется обязательное поле Код, где нужно указать строку, по которой будет идентифицироваться данное ограничение.
Редактор JPQL в полях Join Clause и Where Clause поддерживает автодополнение имен сущностей и их атрибутов. Для вызова автодополнения нажмите Ctrl+Space. Если вызов произведен после точки, будет выведен список атрибутов сущности, соответствующей контексту, иначе - список всех сущностей модели данных. |
Правила формирования ограничения:
-
В качестве алиаса извлекаемой сущности необходимо использовать строку
{E}
. При выполнении запросов она будет заменена на реальный алиас, заданный в запросе. -
В параметрах JPQL можно использовать следующие предопределенные константы:
-
session$userLogin
− имя учетной записи текущего пользователя (в случае замещения − имя учетной записи замещаемого пользователя). -
session$userId
− ID текущего пользователя (в случае замещения − ID замещаемого пользователя). -
session$userGroupId
− ID группы текущего пользователя (в случае замещения − ID группы замещаемого пользователя). -
session$XYZ
− произвольный атрибут текущей пользовательской сессии, где XYZ − имя атрибута.
-
-
Содержимое поля Where Clause добавляется в выражение
where
запроса по условиюand
(И). Само словоwhere
писать не нужно, оно будет добавлено автоматически, даже если исходный запрос его не содержал. -
Содержимое поля Join Clause добавляется в выражение
from
запроса. Оно должно начинаться с запятой или словjoin
илиleft join
.
Простейший пример ограничения приведен на рисунке выше: пользователи с данным ограничением будут видеть только те экземпляры сущности ref$Car
, у которых поле VIN начинается с '00'.
Ещё один классический пример: некая сущность связана с сущностью User
в отношении many-to-many, и необходимо, чтобы пользователю были доступны только те экземпляры сущности, в которых есть ссылка непосредственно на него. В этом случае можно использовать оператор member of
в поле Where Clause:
(select u from sec$User u where u.id = :session$userId) member of {E}.users
Для ограничений с проверкой в памяти в Groovy скрипт передается переменная userSession
типа UserSession
. Ее можно использовать для получения атрибутов текущей пользовательской сессии, например:
{E}.createdBy == userSession.user.login
Разработчик может проверить условия ограничений для конкретной сущности с помощью методов интерфейса Security
:
-
isPermitted(Entity, ConstraintOperationType)
- для проверки ограничений по типу операции. -
isPermitted(Entity, String)
- для проверки ограничений по коду.
Кроме того, существует возможность связать любое действие, унаследованное от класса ItemTrackingAction
, c проверкой ограничений. Для этого в XML-элементе action
следует задать атрибут constraintOperationType
, либо использовать метод setConstraintOperationType()
в контроллере экрана.
Пример:
<table>
...
<actions>
<action id="create"/>
<action id="edit" constraintOperationType="update"/>
<action id="remove" constraintOperationType="delete"/>
</actions>
</table>
При нарушении ограничения пользователю показывается уведомление. Заголовок и текст уведомления для каждого ограничения можно переопределить прямо в приложении. Для этого необходимо выбрать ограничение на вкладке Constraints экрана Access Groups, нажать на кнопку Localization и в появившемся окне задать свой заголовок и текст сообщения. |