====== Authorization - Create a new evaluator ======
===== Step 1. create evaluator =====
The most //easiest// way is to copy some existing evaluator and just refactor its name, package, constructor and everything you need. Good for copy is for example [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/security/evaluator/role/RoleGuaranteeEvaluator.java|RoleGuaranteeEvaluator]], this evaluator returns all roles, of which the logged user is the guarantee.
As you can see RoleGuaranteeEvaluator extends [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/security/evaluator/AbstractAuthorizationEvaluator.java|AbstractAuthorizationEvaluator]] and as a generic type there is the class [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/model/entity/IdmRole.java|IdmRole]] (generic type is always entity **not DTO!**) On the next picture you can see that generic type is on FE shown as **Entity type**.
{{ :tutorial:dev:eval01.png? |}}
===== Step 2. two main methods =====
In almost every evaluator is two main methods in which is written almost complete logic. These methods is **getPredicate** and **getPermissions**. Simple description these methods (if you want some betyter description go to [[devel:dev:security:authorization|Authorization policies]]):
==== getPredicate ====
getPredicate is method in which we will **add** access to data. Evaluators only add, never limit the given set. Example: if you have some evaluator that add all identities you will be not able to remove some identities or annul this set. You are able only to extends set.
==== getPermissions ====
In this method you can add or remove **Permissions**. From super class you get empty set.
super.getPermissions(entity, policy);
If you want add all permission that it was set via frontend use this (Object AuthorizationPolicy contains all permission that is set via FE):
permissions.addAll(policy.getPermissions());
Basic permission: CRUD (Create, Read, Udpdate, Delete), Administration (all of CRUD), View in select box (autocomplete). Example of setting permissions via FE:
{{ :tutorial:dev:eval02.png? |}}
===== Add some logic =====
Now we have prepare basic evaluator that not contains logic.
@Component
@Description("Testing evaluator.")
public class TestingEvaluator extends AbstractAuthorizationEvaluator {
@Autowired
public TestingEvaluator() {
}
@Override
public Predicate getPredicate(Root root, CriteriaQuery> query, CriteriaBuilder builder, AuthorizationPolicy policy, BasePermission... permission) {
return null;
}
@Override
public Set getPermissions(IdmRole entity, AuthorizationPolicy policy) {
Set permissions = super.getPermissions(entity, policy);
permissions.addAll(policy.getPermissions());
return permissions;
}
}
Our evaluator will be add access for user to roles that name is ended with some value from application properties. At first we will need autowire these beans: **SecurityService** (for actual logged user) and **ConfigurationService** (for read application properties), all these beans are from package **eu.bcvsolutions.idm.core.**.
Constructor after autowire:
private final SecurityService securityService;
private final ConfigurationService configurationService;
@Autowired
public TestingEvaluator(
SecurityService securityService,
ConfigurationService configurationService) {
//
Assert.notNull(securityService);
Assert.notNull(configurationService);
//
this.securityService = securityService;
this.configurationService = configurationService;
}
To method **getPredicate** we will now add check for current logged user.
AbstractAuthentication authentication = securityService.getAuthentication();
if (authentication == null || authentication.getCurrentIdentity() == null) {
return null;
}
Now we are add get value from application properties and build query:
String valueFromProperties = configurationService.getValue("some_attribute");
//
if (hasPermission(policy, permission)) {
return query.where(
builder.like(
root.get(IdmRole_.name), "%" + valueFromProperties
)
).getRestriction();
}
return null;
As you see from configurationService we get attribute with key //some_attribute// and after that we build simple query.
===== Finished evaluator =====
There is finished evaluator:
@Component
@Description("Testing evaluator.")
public class TestingEvaluator extends AbstractAuthorizationEvaluator {
private final SecurityService securityService;
private final ConfigurationService configurationService;
@Autowired
public TestingEvaluator(SecurityService securityService, ConfigurationService configurationService) {
//
Assert.notNull(securityService);
Assert.notNull(configurationService);
//
this.securityService = securityService;
this.configurationService = configurationService;
}
@Override
public Predicate getPredicate(Root root, CriteriaQuery> query, CriteriaBuilder builder,
AuthorizationPolicy policy, BasePermission... permission) {
AbstractAuthentication authentication = securityService.getAuthentication();
if (authentication == null || authentication.getCurrentIdentity() == null) {
return null;
}
//
String valueFromProperties = configurationService.getValue("some_attribute");
//
if (hasPermission(policy, permission) && !StringUtils.isEmpty(valueFromProperties)) {
return query.where(builder.like(root.get(IdmRole_.name), valueFromProperties)).getRestriction();
}
return null;
}
@Override
public Set getPermissions(IdmRole entity, AuthorizationPolicy policy) {
Set permissions = super.getPermissions(entity, policy);
//
String valueFromProperties = configurationService.getValue("some_attribute");
//
if (!StringUtils.isEmpty(valueFromProperties) && entity.getName().endsWith(valueFromProperties)) {
permissions.addAll(policy.getPermissions());
}
return permissions;
}
}