9. Контроль доступа к данным
До сих пор вы входили в приложение как администратор и имели полный контроль над данными и пользовательским интерфейсом. В этой заключительной главе вы настроите ограниченный доступ к приложению для HR-менеджеров и сотрудников.
Ресурсная роль для сотрудников
Создание ресурсной роли
В окне инструментов Jmix нажмите New () → Resource Role:

В диалоговом окне New Resource Role введите Employee
в поле Role name и выберите UI
в раскрывающемся списке Security scope:

Нажмите на кнопку OK.
Studio создаст и откроет аннотированный интерфейс:
package com.company.onboarding.security;
import io.jmix.security.role.annotation.ResourceRole;
@ResourceRole(name = "Employee", code = "employee", scope = "UI")
public interface EmployeeRole {
}
Роль с областью UI применяется к пользователям только тогда, когда они входят в систему через пользовательский интерфейс. Если тот же пользователь входит в систему через REST API, роль не применяется. Рекомендуется создать другой набор ролей для API, обычно с меньшим количеством разрешений.
|
Перейдите на вкладку User Interface, чтобы определить права доступа к экранам. Выберите MyOnboardingView
в дереве меню и установите справа флажки Allow:

После этого перейдите на вкладку Entities и выберите следующие разрешения:

Сотруднику необходимы операции на чтение сущностей Step
, User
и UserStep
, чтобы просматривать их в пользовательском интерфейсе, и операции на обновление сущностей User
и UserStep
, чтобы отметить выполненные шаги.
Вернитесь на вкладку Text. Вы увидите, что Studio сгенерировала несколько методов с аннотациями, соответствующими предоставленным разрешениям:
@ResourceRole(name = "Employee", code = "employee", scope = "UI")
public interface EmployeeRole {
@MenuPolicy(menuIds = "MyOnboardingView")
@ViewPolicy(viewIds = "MyOnboardingView")
void screens();
@EntityAttributePolicy(entityClass = User.class,
attributes = "*",
action = EntityAttributePolicyAction.VIEW)
@EntityPolicy(entityClass = User.class,
actions = {EntityPolicyAction.READ, EntityPolicyAction.UPDATE})
void user();
@EntityAttributePolicy(entityClass = UserStep.class,
attributes = "*",
action = EntityAttributePolicyAction.VIEW)
@EntityPolicy(entityClass = UserStep.class,
actions = {EntityPolicyAction.READ, EntityPolicyAction.UPDATE})
void userStep();
@EntityAttributePolicy(entityClass = Step.class,
attributes = "*",
action = EntityAttributePolicyAction.VIEW)
@EntityPolicy(entityClass = Step.class,
actions = EntityPolicyAction.READ)
void step();
}
Нажмите Ctrl/Cmd+S и переключитесь на запущенное приложение. Откройте экран Security → Resource roles. Вы увидите новую роль в списке:

Назначение роли
Теперь давайте назначим роль пользователю. Откройте экран списка пользователей и создайте нового пользователя bob
. Выберите пользователя и нажмите кнопку Role assignments:

На экране Role assignments нажмите кнопку Add на панели Resource permissions.
В диалоговом окне Select resource roles выберите роли Employee
и UI: minimal access
:

Нажмите кнопку Select. Выбранные роли будут показаны на панели Resource permissions:

Нажмите кнопку OK, чтобы сохранить назначения ролей.
Роль UI: minimal access требуется для входа в пользовательский интерфейс приложения. Вы можете найти ее в своем проекте и исследовать содержимое роли.
|
Выйдите из системы с помощью кнопки рядом с текущим именем пользователя:

Войдите в систему как bob
. В меню вы увидите только экран My onboarding
:

Ресурсная роль для HR-менеджера
В окне инструментов Jmix нажмите New () → Role.
В диалоговом окне New Role введите HR Manager
в поле Role name, установите в Role code значение hr-manager
и выберите UI
в раскрывающемся списке Security scope:

Нажмите на кнопку OK.
Studio создаст и откроет аннотированный интерфейс, определяющий роль:
package com.company.onboarding.security;
import io.jmix.security.role.annotation.ResourceRole;
@ResourceRole(name = "HR Manager", code = "hr-manager", scope = "UI")
public interface HRManagerRole {
}
Перейдите на вкладку User Interface и разрешите экраны User.list
и User.detail
(вы можете использовать поле поиска сверху для фильтрации дерева):

Перейдите на вкладку Entities и предоставьте разрешение на чтение Department
и Step
, а также все разрешения User
и UserStep
:

Вернитесь на вкладку Text и просмотрите аннотации, созданные Studio:
@ResourceRole(name = "HR Manager", code = "hr-manager", scope = "UI")
public interface HRManagerRole {
@MenuPolicy(menuIds = "User.list")
@ViewPolicy(viewIds = {"User.detail", "User.list"})
void screens();
@EntityAttributePolicy(entityClass = Department.class,
attributes = "*",
action = EntityAttributePolicyAction.VIEW)
@EntityPolicy(entityClass = Department.class,
actions = EntityPolicyAction.READ)
void department();
@EntityAttributePolicy(entityClass = Step.class,
attributes = "*",
action = EntityAttributePolicyAction.VIEW)
@EntityPolicy(entityClass = Step.class,
actions = EntityPolicyAction.READ)
void step();
@EntityAttributePolicy(entityClass = User.class,
attributes = "*",
action = EntityAttributePolicyAction.MODIFY)
@EntityPolicy(entityClass = User.class,
actions = EntityPolicyAction.ALL)
void user();
@EntityAttributePolicy(entityClass = UserStep.class,
attributes = "*",
action = EntityAttributePolicyAction.MODIFY)
@EntityPolicy(entityClass = UserStep.class,
actions = EntityPolicyAction.ALL)
void userStep();
}
Нажмите Ctrl/Cmd+S и переключитесь на запущенное приложение. Войдите в систему как администратор. Откройте экран Security → Resource roles и убедитесь, что новая роль HR Manager
есть в списке.
Создайте нового пользователя, например, alice
.
Назначьте пользователю alice
роли HR Manager
и UI: minimal access
, как вы это делали в предыдущем разделе.
Войдите в систему как alice
. Вы увидите экран Users
и сможете управлять пользователями и их шагами по онбордингу:

Роль уровня строк для HR-менеджеров
В настоящее время HR-менеджеры могут создавать пользователей, назначать пользователю любой отдел и просматривать пользователей всех отделов.
В этом разделе вы создадите роль на уровне строк (row-level role), которая ограничивает доступ HR-менеджера к отделам и другим пользователям. Они смогут видеть и назначать только свой собственный отдел (тот, в котором они указаны в атрибуте hrManager
).
В окне инструментов Jmix нажмите New () → Row-level Role:

В открывшемся диалоговом окне New Row-level Role введите:
-
Role name:
HR manager’s departments and users
-
Role code:
hr-manager-rl
-
Class:
com.company.onboarding.security.HrManagerRlRole

Нажмите OK.
Studio создаст и откроет аннотированный интерфейс:
package com.company.onboarding.security;
import io.jmix.security.role.annotation.RowLevelRole;
@RowLevelRole(name = "HR manager's departments and users",
code = "hr-manager-rl")
public interface HrManagerRlRole {
}
Кликните Add Policy → JPQL Policy в верхней панели действий:

В диалоге Add JPQL Policy введите:
-
Entity:
Department
-
Where clause:
{E}.hrManager.id = :current_user_id

Нажмите OK.
Кликните Add Policy → JPQL Policy снова и введите:
-
Entity:
User
-
Where clause:
{E}.department.hrManager.id = :current_user_id
Нажмите OK.
Интерфейс HrManagerRlRole
будет содержать следующий код:
package com.company.onboarding.security;
import com.company.onboarding.entity.Department;
import com.company.onboarding.entity.User;
import io.jmix.security.role.annotation.JpqlRowLevelPolicy;
import io.jmix.security.role.annotation.RowLevelRole;
@RowLevelRole( (1)
name = "HR manager's departments and users",
code = "hr-manager-rl")
public interface HrManagerRlRole {
@JpqlRowLevelPolicy( (2)
entityClass = Department.class, (3)
where = "{E}.hrManager.id = :current_user_id") (4)
void department();
@JpqlRowLevelPolicy(
entityClass = User.class,
where = "{E}.department.hrManager.id = :current_user_id")
void user();
}
1 | Аннотация @RowLevelRole указывает, что интерфейс определяет роль на уровне строки. |
2 | @JpqlRowLevelPolicy определяет политику, которая будет применяться на уровне базы данных при чтении объекта. |
3 | Класс сущности, для которого применяется политика. |
4 | Раздел where , который должен быть добавлен для каждого оператора JPQL select для этой сущности. {E} используется вместо псевдонима сущности в запросе. :current_user_id - это предопределенный параметр, устанавливаемый фреймворком для идентификатора текущего вошедшего в систему пользователя. |
Нажмите Ctrl/Cmd+S и переключитесь на запущенное приложение. Войдите в систему как администратор. Откройте экран Security → Row-level roles и убедитесь, что в списке есть новая роль HR manager’s departments and users
.
Откройте экран Role assignments для alice
и добавьте роль в таблицу Row-level constraints:

Нажмите на кнопку OK, чтобы сохранить назначение роли.
Назначьте alice
HR-менеджером для отдела:

Войдите в систему как alice
.
На экране списка пользователей вы увидите только пользователей ее отдела:

И alice
может назначить пользователю только этот отдел:

Резюме
В этом разделе вы создали роли сотрудников и HR-менеджеров, чтобы ограничить доступ к приложению для разных групп пользователей.
Вы узнали, что:
-
Ресурсная роль предоставляет пользователям разрешения на открытие экранов и работу с определенными объектами.
-
Роль уровня строки, напротив, ограничивает способность пользователя просматривать определенные экземпляры для сущности, разрешенной ресурсной ролью.
-
Роли назначаются пользователям во время выполнения с помощью экрана Role assignment, доступного на экране
User.detail
. -
Сгенерированная в новом проекте роль
UI: minimal access
необходима пользователю для входа в пользовательский интерфейс приложения.