6.2.5. Роли

Роль объединяет набор разрешений, которые могут быть предоставлены пользователю.

Пользователь может иметь несколько ролей. При этом он получает логическую сумму (ИЛИ) прав на некоторый объект от всех ролей, которые у него есть. Например, если пользователю назначены роли A и B, роль A не дает разрешений на X, роль B разрешает X, то в итоге X будет разрешен.

Роль может давать разрешения на конкретные целевые объекты, а также на целые категории объектов: экраны, операции над сущностями, атрибуты сущностей, специфические разрешения. Например, можно легко дать разрешение Read на все сущности и разрешение View на все их атрибуты.

Разрешения на компоненты экранов являются исключением из правил, описанных выше: они могут быть указаны только на конкретный компонент, и если ни одна роль не определяет разрешения на некоторый компонент, то этот компонент полностью доступен пользователю.

Роль может иметь признак "по умолчанию", что означает, что такая роль будет автоматически назначаться вновь создаваемым пользователям. Это позволяет выдавать некоторый набор разрешений всем пользователям по умолчанию.

Определение ролей во время разработки

Рекомендуемый способ определения роли - создать класс, расширяющий AnnotatedRoleDefinition, переопределить методы, возвращающие разрешения различных типов, и добавить им аннотации, указывающие, какие разрешения дает данная роль. Класс должен находиться в модуле core. Например, роль дающая разрешения на сущность Customer и ее экраны списка и редактирования может выглядеть следующим образом:

@Role(name = "Customers Full Access")
public class CustomersFullAccessRole extends AnnotatedRoleDefinition {

    @EntityAccess(entityClass = Customer.class,
            operations = {EntityOp.CREATE, EntityOp.READ, EntityOp.UPDATE, EntityOp.DELETE})
    @Override
    public EntityPermissionsContainer entityPermissions() {
        return super.entityPermissions();
    }

    @EntityAttributeAccess(entityClass = Customer.class, modify = "*")
    @Override
    public EntityAttributePermissionsContainer entityAttributePermissions() {
        return super.entityAttributePermissions();
    }

    @ScreenAccess(screenIds = {"application-demo", "demo_Customer.browse", "demo_Customer.edit"})
    @Override
    public ScreenPermissionsContainer screenPermissions() {
        return super.screenPermissions();
    }
}

Аннотации могут быть указаны несколько раз. Например, следующая роль дает доступ только на чтение ко всем сущностям и их атрибутам, позволяет модифицировать атрибуты grade and comments сущности Customer, а также позволяет создавать и изменять сущность Order и ее атрибуты:

@Role(name = "Order Management")
public class OrderManagementRole extends AnnotatedRoleDefinition {

    @EntityAccess(entityName = "*", operations = {EntityOp.READ})
    @EntityAccess(entityClass = Order.class, operations = {EntityOp.CREATE, EntityOp.UPDATE})
    @Override
    public EntityPermissionsContainer entityPermissions() {
        return super.entityPermissions();
    }

    @EntityAttributeAccess(entityName = "*", view = "*")
    @EntityAttributeAccess(entityClass = Customer.class, modify = {"grade", "comments"})
    @EntityAttributeAccess(entityClass = Order.class, modify = "*")
    @Override
    public EntityAttributePermissionsContainer entityAttributePermissions() {
        return super.entityAttributePermissions();
    }
}

Определять роли во время разработки можно только если свойство приложения cuba.security.rolesPolicyVersion установлено в 2, что является значением по умолчанию для проектов, созданных на версии CUBA 7.2 или новее. Если ваш проект мигрирует с предыдущей версии CUBA, см. раздел Предыдущая реализация ролей и разрешений.

Определение ролей во время работы приложения

Фреймворк содержит UI, который позволяет создавать роли в работающем приложении, см. Administration > Roles. Роли, созданные таким образом, можно изменить или удалить. Роли, заданные при разработке приложения, доступны только на чтение.

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

  • Вкладка Screens - разрешения на экраны системы. Дерево в левой части вкладки отражает структуру главного меню системы. Последним элементом дерева является Other screens, внутри которого сосредоточены экраны, не включенные в главное меню (например, экраны редактирования сущностей).

    Флажок Allow all screens разрешает все экраны сразу. Он эквивалентен аннотации @ScreenAccess(screenIds = "*").

  • Вкладка Entities - разрешения на операции с сущностями. При переходе на данную вкладку изначально включен флажок Assigned only, поэтому в таблице отображаются только сущности, для которых в данной роли уже есть явные разрешения. Поэтому для новой роли таблица пуста. Для установки разрешений снимите флажок Assigned only и нажмите Apply. Список сущностей можно фильтровать, вводя в поле Entity любую часть имени сущности и нажимая Apply. Установив флажок System level, можно выбрать системную сущность, помеченную аннотацией @SystemLevel. По умолчанию такие сущности не показываются в таблице.

    Панель Allow all entities предназначена для разрешения операций над всеми сущностями. Ее флажки эквивалентны аннотации @EntityAccess(entityName = "*", …​).

  • Вкладка Attributes - разрешения на атрибуты сущностей. В таблице сущностей в колонке Permissions отображается список атрибутов, для которых явно указаны разрешения. Управление списком сущностей аналогично описанному для вкладки Entities.

    Панель Allow all attributes предназначена для разрешения просмотра или модификации всех атрибутов всех сущностей. Если необходимо разрешить все атрибуты конкретной сущности, отметьте флажок "*" внизу панели Permissions для этой сущности. То же самое можно сделать используя символ "*" в атрибутах entityName и view/modify аннотации @EntityAttributeAccess.

  • Вкладка Specific - разрешения на именованную функциональность. Имена объектов, на которые могут быть назначены специфические разрешения, определяются в конфигурационном файле permissions.xml проекта.

    Флажок Allow all specific permissions является эквивалентом аннотации @SpecificAccess(permissions = "*").

  • Вкладка UI - разрешения на UI-компоненты экранов. Для создания ограничения выберите нужный экран в выпадающем списке Screen, задайте путь к компоненту в поле Component, и нажмите Add. При формировании пути, следуйте правилам, описанным в разделе Разрешения. Для отображения структуры экрана нажмите кнопку Components tree, выберите компонент и выберите Copy id to path в контекстном меню.

Области действия (security scopes)

Области действия позволяют назначать одному пользователю различные наборы ролей (и тем самым различные разрешения) в зависимости от клиентской технологии, которую он использует для доступа к приложению. Область действия указывается в атрибуте securityScope аннотации @Role, или в поле Security scope экрана редактирования роли, если роль создается во время работы приложения.

Ядро фреймворка содержит единственного клиента - Generic UI, поэтому все роли по умолчанию имеют область действия GENERIC_UI. Все пользователи, входящие в систему через UI приложения получат набор ролей с этим значением области действия.

Аддон REST API определяет свою собственную область действия - REST, поэтому если вы добавите аддон к проекту, вам необходимо сконфигурировать отдельный набор ролей для пользователей, входящих в систему через REST API. Если этого не сделать, пользователи не смогут входить через REST, так как у них не будет разрешения cuba.restApi.enabled.

System roles

Фреймворк определяет две предустановленные роли для области действия GENERIC_UI:

  • system-minimal - содержит минимальный набор разрешений, необходимый пользователям для работы с Generic UI. Данная роль задается классом MinimalRoleDefinition. Она дает специфическое разрешение cuba.gui.loginToClient, а также разрешения на некоторый системные сущности и экраны. У роли system-minimal установлен атрибут "по умолчанию", поэтому она автоматически назначается новым пользователям.

  • system-full-access - дает все разрешения на все объекты, тем самым может использоваться для создания администраторов, имеющих полные права на систему. Встроенный пользователь admin по умолчанию имеет эту роль.

Определение доступа к пунктам главного меню

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

  • Для ролей, определенных во время разработки, используется аннотация @ScreenAccess, например:

    @ScreenAccess(screenIds = {"application-demo", "demo_Customer.browse", "demo_Customer.edit"})

    В список идентификаторов, помимо идентификаторов экранов, следует добавить идентификаторы пунктов меню верхнего уровня (например, screenIds = {"application-demo"}).

  • Для ролей, определенных во время работы приложения

    На вкладке Screens экрана редактирования роли помимо разрешенных экранов следует разрешить все пункты меню вверх по иерархии. В противном случае экраны не будут показаны пользователю.