Security and Permissions
EntityModule provides base security by integrating with the AllowableAction
model of SpringSecurityModule
.
Allowable actions define which actions an end user can perform on an item or a type.
These actions are by default specified in two aspects:
-
The allowable actions specified on the
EntityConfiguration
-
The allowable actions specified on a view
Allowable actions for an EntityConfiguration
Actions specified on an entity configuration specify which actions a user may perform on an entity type or instance. These actions can be fixed, for example no user can delete books via the default interface, as well as depend on custom rules, for example based on the roles of the current user.
The actions on an EntityConfiguration
are separated on two levels:
-
global actions: actions that are present for an entity type.
-
instance actions: actions that are present based on a specific instance for an entity type.
These can be configured by specifying the allowableActionsBuilder
when customizing the EntityConfiguration
.
Default allowable actions are specified on each configuration which confirm that any requested action is present. |
configuration.withType( Book.class )
.allowableActionsBuilder( new EntityConfigurationAllowableActionsBuilder()
{
@Override
public AllowableActions getAllowableActions( EntityConfiguration<?> entityConfiguration ) { (1)
return FixedEntityAllowableActionsBuilder.DEFAULT_ALLOWABLE_ACTIONS; (2)
}
@Override
public <V> AllowableActions getAllowableActions( EntityConfiguration<V> entityConfiguration, V entity ) { (3)
return new AllowableActionSet( AllowableAction.READ.getId(), AllowableAction.UPDATE.getId() ); (4)
}
} )
1 | Configuring the global actions for the Book entity. |
2 | All actions are allowed.
FixedEntityAllowableActionsBuilder.DEFAULT_ALLOWABLE_ACTIONS always acknowledges that the requested action is present. |
3 | Configuring the actions for the Book instance. |
4 | The actions are configured based on a custom implementation.
In this case each instance has the AllowableAction.READ and AllowableAction.UPDATE action. |
private final CurrentSecurityPrincipalProxy currentSecurityPrincipalProxy;
configuration.withType( Book.class )
.allowableActionsBuilder( new EntityConfigurationAllowableActionsBuilder()
{
@Override
public AllowableActions getAllowableActions( EntityConfiguration<?> entityConfiguration ) {
AllowableActionSet allowableActions = new AllowableActionSet();
if( currentSecurityPrincipalProxy.hasAuthority( "ROLE_ADMIN" ){ (1)
allowableActions.add( AllowableAction.CREATE );
}
allowableActions.add( AllowableAction.READ );
return allowableActions;
}
@Override
public <V> AllowableActions getAllowableActions( EntityConfiguration<V> entityConfiguration, V entity ) {
AllowableActionSet allowableActions = new AllowableActionSet();
if( currentSecurityPrincipalProxy.hasAuthority( "ROLE_ADMIN" ) ) { (2)
allowableActions.add( AllowableAction.UPDATE );
allowableActions.add( AllowableAction.DELETE );
}
allowableActions.add( AllowableAction.READ );
return allowableActions;
}
} )
1 | Only administrators can create new books. |
2 | Only administrators can modify or delete books. |
Actions specified on the configuration can be used by other components of the application, such as the various views provided by EntityModule .
|
Securing views
Actions for default views
The action registered on a view specifies which action must be present for a view to be accessible by a user. For each of the default views, a required action is configured.
View name | Required action | Level |
---|---|---|
|
global |
|
|
global |
|
|
instance |
|
|
instance |
|
|
instance |
If the current user does not have access to the action required for the view, then he will not have access to the page itself.
When the default views are rendered, these actions are also checked when links to different views are provided.
This means that, for example, whilst rendering the list view, each instance is checked for the presence of the AllowableAction.UPDATE
and AllowableAction.DELETE
action before rendering the buttons to the corresponding pages.
Each of the default views is linked via the list view. These links depend on the presence of the required action, except for detail views:
This can be overridden by setting the |
Configuring a list view
By default a list view is configured to be accessible if the global AllowableAction.READ
action is present.
If a user does not have access to the other actions, the list view will still be available, but links to the other views will not be provided on the list view.
This means that even though the user may not have AllowableAction.READ
access for a specific instance, he can still see the data presented in the list view itself.
By configuring the showOnlyItemsWithAction
on a list view, the individual entries of the list can also be filtered based on the given action.
configuration.withType( Book.class )
.listView( lvb -> lvb.showOnlyItemsWithAction( AllowableAction.READ ) ); (1)
1 | Only book items for which the current principal has the instance action AllowableAction.READ will be visible in the list view. |
Configuring custom views
The default views all have an action configured to access the view. When creating custom views, they can be secured by providing an access validator or specifying a required action.
configuration.withType( Book.class )
.formView( "custom-view", EntityViewCustomizers.basicSettings() (1)
.adminMenu( "/custom-view" )
.accessValidator( ( viewFactory, viewContext ) -> viewContext.getAllowableActions().contains( AllowableAction.ADMINISTER ) ) (2)
)
1 | A custom view is configured with basic view settings.
EntityViewCustomizers provides base consumers that support common scenario’s, such as adding an admin menu for the current view. |
2 | An access validator is specified that checks whether the AllowableAction.ADMINISTER is available. |
In previous example, a menu item was immediately registered for our custom view. Both the view and the menu item were secured via the specified access validator.
In the following example, we’ll create an equal configuration by specifying the required action for the view. The sole difference between the two examples is that the latter will not create a menu item.
configuration.withType( Book.class )
.formView( "custom-view", fvb -> fvb.requiredAllowableAction( AllowableAction.ADMINISTER ) ) (1)
1 | A custom view is configured, secured with the AllowableAction.ADMINISTER action. |
When the access to the view is checked, one of the following scenario’s applies:
-
An instance is present in the current view context, as such the instance will be checked for the required action.
-
No instance is present in the current view context, as such the current
EntityConfiguration
will be checked for the required action.