UI Constraints
Дополнение UI Constraints позволяет управлять видимостью и доступностью компонентов пользовательского интерфейса с помощью декларативных политик, определенных в ресурсных ролях.
Например, кнопку можно сделать неактивной, таблицу данных скрыть и так далее.
Любой UI-компонент или действие может управляться через UI Constraints, даже если компонент не связан с моделью данных и не зависит от операций с сущностями и политик атрибутов сущности. Единственное условие — у компонента должен быть ID.
Данная функциональность избавляет от необходимости писать код для анализа ролей пользователя или конкретных разрешений и управления состоянием компонентов в экранах приложения. Она также позволяет точно настраивать управление доступом во время выполнения, редактируя роли в экранах Security → Resource roles.
Установка
|
Это дополнение требует Enterprise подписки. Если у вас нет подписки, см. раздел Enterprise Trial, чтобы узнать, как получить пробную версию. |
Для автоматической установки через Jmix Marketplace следуйте инструкциям в разделе Дополнения.
Для ручной установки выполните следующие шаги.
-
Настройте доступ к премиум-репозиторию.
-
Добавьте премиум-репозиторий в свой
build.gradle:repositories { // ... maven { url = 'https://nexus.jmix.io/repository/premium' credentials { username = rootProject['premiumRepoUser'] password = rootProject['premiumRepoPass'] } } } -
Добавьте учетные данные премиум-репозитория в
~/.gradle/gradle.properties:premiumRepoUser=123456123456 premiumRepoPass=abcdefabcdefПолучите учетные данные репозитория из вашего лицензионного ключа: первая часть ключа перед тире – это имя пользователя репозитория, часть после тире – пароль. Например, если ваш ключ выглядит как
123456-abcdef abcdef, имя пользователя –123456, а пароль –abcdef abcdef.
-
-
Добавьте зависимости в
build.gradle:implementation 'io.jmix.uiconstraints:jmix-uiconstraints-starter'
Использование
Дополнение UI Constraints предоставляет UI component policies (политики компонентов UI), которые можно указать в ресурсных ролях как на этапе разработки с использованием аннотированных Java-интерфейсов, так и во время выполнения через экраны управления ролями.
Аннотация @UiComponentPolicy, используемая в Java-интерфейсах, описана ниже.
Редактор ролей времени выполнения доступен через основной пункт меню Security → Resource roles. После включения дополнения UI Constraints в проект, выпадающий список политик будет содержать элемент UI component policy:
Редактор политик компонентов UI позволяет указать целевой экран, выбрать существующие компоненты из выпадающего списка и задать действие политики и эффект:
В отличие от политик сущностей и атрибутов сущностей, политика компонентов UI является «запрещающей», то есть она может сделать компонент интерфейса или действие только менее видимыми или доступными, чем они были до применения политики. Например, если атрибут сущности виден благодаря политике атрибута сущности, политика компонента UI может сделать соответствующий компонент интерфейса невидимым, если указано действие VISIBLE с эффектом DENY. Дополнительная информация об эффектах приведена ниже.
Политики компонентов UI применяются в конце процесса открытия экрана, после отправки ReadyEvent. К этому моменту инициализация экрана завершена и другие политики применены.
Политики также применяются к содержимому ленивой вкладки при ее первом выборе. Для других компонентов, созданных после открытия экрана, применяйте политики программно.
Проверка политик UI-компонентов
Используйте UiComponentPolicyContext с бином AccessManager, чтобы проверить, разрешают ли политики UI-компонентов текущего пользователя отображать или редактировать компонент или действие. Передайте ID экрана и путь компонента в том же формате, что и атрибут componentIds, например emailField, addressFragment.streetField или userGrid.edit.
Следующий пример проверяет, разрешают ли политики отображать и редактировать emailField на экране Customer.detail:
@Autowired
private AccessManager accessManager;
private boolean isEmailFieldEditable() {
UiComponentPolicyContext context =
new UiComponentPolicyContext("Customer.detail", "emailField");
accessManager.applyRegisteredConstraints(context);
return context.isVisiblePermitted() && context.isEnabledPermitted();
}
После вызова applyRegisteredConstraints() используйте isVisiblePermitted() и isEnabledPermitted() для получения разрешений. Изначально оба метода возвращают true; доступ к компоненту, не упомянутому ни в одной политике, разрешен, если другое зарегистрированное ограничение не запрещает его.
Контекст проверяет разрешения политик, а не текущее состояние компонента или разрешения на его атрибут сущности. Результат, разрешающий доступ, не делает компонент видимым или доступным для редактирования, если он был скрыт, отключен или переведен в режим только для чтения по другой причине.
Встроенное ограничение UiComponentPolicyConstraint проверяет действующие политики текущего пользователя. UiComponentPolicyApplier использует тот же контекст при их применении. Приложение может зарегистрировать AccessConstraint<UiComponentPolicyContext>, чтобы дополнительно ограничить доступ с помощью setVisibleDenied() или setEnabledDenied(). Случаи отказа в доступе при проверках регистрируются с помощью AccessLogger.
Применение политик к динамическому содержимому
Для компонентов, созданных после открытия экрана, инжектируйте UiComponentPolicyApplier и вызовите applyUiComponentPolicies(view, content) после добавления содержимого на экран. Это применит политики экрана к компоненту и его дочерним компонентам. Компоненты и действия должны иметь ID, соответствующие их путям в политиках.
@Autowired
private UiComponentPolicyApplier uiComponentPolicyApplier;
private void addRuntimeContent(Component content) {
getContent().add(content);
uiComponentPolicyApplier.applyUiComponentPolicies(this, content);
}
Метод applyUiComponentPolicies(content) с одним аргументом находит экран, которому принадлежит компонент, через дерево компонентов. Если найти экран не удается, политики не применяются.
Для содержимого, добавленного на вкладку tabSheet, используйте метод applyUiComponentPolicies(view, content) с двумя аргументами. JmixTabSheet хранит в дереве компонентов содержимое только выбранной вкладки и присоединяет его перед отправкой ответа клиенту, поэтому метод с одним аргументом не может надежно найти там экран, которому принадлежит компонент.
Выбор вкладки
По умолчанию дополнение применяет политики к содержимому вкладки при ее выборе. Это относится и к компонентам и действиям в <tab lazy="true">, содержимое которой создается только в этот момент. Для применения политик к ленивым вкладкам не требуется писать код приложения.
Каждый компонент содержимого обрабатывается один раз. При повторном выборе той же вкладки политики не применяются заново поверх изменений, внесенных приложением в ее компоненты. Содержимое, переданное в applyUiComponentPolicies(), также помечается как обработанное для механизма выбора вкладок.
Если политика скрывает выбранную вкладку, во время работы пользователя с экраном может быть выбрана другая вкладка.
Чтобы отключить автоматическое применение политик при выборе вкладки, установите jmix.uiconstraints.apply-policies-on-tab-selection в false. В этом случае политики не будут автоматически применяться к содержимому, созданному после открытия экрана, включая содержимое ленивых вкладок.
Аннотация UiComponentPolicy
Аннотация @UiComponentPolicy позволяет определять политики компонентов UI в интерфейсах ресурсных ролей на этапе разработки.
Пример:
package com.company.demo.security;
import com.company.demo.view.customer.CustomerDetailView;
import com.company.demo.view.customer.CustomerListView;
import io.jmix.security.role.annotation.ResourceRole;
import io.jmix.uiconstraints.annotation.UiComponentPolicy;
import io.jmix.uiconstraints.annotation.UiComponentPolicyAction;
import io.jmix.uiconstraints.annotation.UiComponentPolicyEffect;
@ResourceRole(name = "EmployeeRole", code = EmployeeRole.CODE, scope = "UI")
public interface EmployeeRole {
String CODE = "employee-role";
@UiComponentPolicy(
viewClass = CustomerListView.class,
componentIds = {"customersDataGrid.importCustomersAction"},
action = UiComponentPolicyAction.ENABLED,
effect = UiComponentPolicyEffect.DENY
)
@UiComponentPolicy(
viewClass = CustomerDetailView.class,
componentIds = {"commentsPane"},
action = UiComponentPolicyAction.VISIBLE,
effect = UiComponentPolicyEffect.DENY
)
void customers();
}
Атрибуты аннотации @UiComponentPolicy описаны ниже.
viewClass и viewId
Политика компонента UI определяется для компонентов внутри экрана. Экран может быть указан либо атрибутом viewClass, либо атрибутом viewId.
componentIds
Каждая аннотация @UiComponentPolicy может определять политики для одного или нескольких компонентов экрана. Их идентификаторы должны быть перечислены в атрибуте componentIds. Политика может применяться к компонентам следующих типов:
-
Визуальный компонент (
textField,button,vbox,divи др.) на данном экране. Например:firstNameField,importButton. -
Действие, принадлежащее данному экрану. Например:
save. -
Действие, принадлежащее компоненту экрана. Например:
userGrid.edit. -
Компонент или действие, находящееся внутри фрагмента. Например:
addressFragment.cityField.
action
Политика компонента UI поддерживает два типа действий:
-
VISIBLE— управляет видимостью компонента. -
ENABLED— управляет доступностью компонента. Если компонент поддерживает состояние только для чтения, он будет установлен в состояние «только для чтения». В противном случае компонент будет отключен (disabled).
effect
Атрибут effect может иметь два значения: ALLOW и DENY.
По умолчанию, если политики компонентов UI не применены, все UI-компоненты на экране имеют свое начальное состояние видимости и доступности. Компоненты, связанные с данными, видимы и доступны, если существует соответствующая политика атрибута сущности.
Если в политике компонента интерфейса указан эффект DENY, это скрывает или отключает UI-компонент или действие. Это стандартный случай использования политики компонента UI.
Эффект ALLOW можно использовать, если требуется переопределить эффект другой политики компонента UI, примененной к тому же компоненту другой ролью. Например, если пользователю уже назначена роль А, и эта роль запрещает доступ к определенному компоненту интерфейса, использование роли B с эффектом ALLOW восстановит доступ к этому компоненту.
Эффект ALLOW не может сделать компонент видимым или доступным, если он был скрыт или отключен из-за своего начального состояния либо из-за отсутствия разрешающей политики для сущности или атрибута сущности.
|
Свойства приложения
jmix.uiconstraints.apply-policies-on-tab-selection
Начиная с Jmix 3.1
Определяет, применяются ли политики UI-компонентов к содержимому вкладки при ее выборе, включая содержимое, созданное для ленивых вкладок. См. Выбор вкладки.
Значение по умолчанию: true.
Установите значение false, чтобы отключить эту обработку. Политики по-прежнему применяются при открытии экрана, а также могут быть применены программно с помощью UiComponentPolicyApplier.