Description
Disclaimer: I'm hesitant to create this issue for sometime as this is quite subjective, but I thought that I still want to make the suggestion to see if there's any other ways to achieve it (that I've perhaps missed out on)
Currently, if I want to define a RoleHierarchy
, I can do it like
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
String roleHierarchyFromMap = "ROLE_ADMIN > ROLE_STAFF \n ROLE_STAFF > ROLE_USER \n ROLE_STAFF > ROLE_GUEST";
roleHierarchy.setHierarchy(roleHierarchyFromMap);
return roleHierarchy;
}
The result would be something like
2023-06-09 21:17:39.881 DEBUG 20580 --- [ restartedMain] o.s.s.a.h.RoleHierarchyImpl : setHierarchy() - The following role hierarchy was set: ROLE_ADMIN > ROLE_STAFF
ROLE_STAFF > ROLE_USER
ROLE_STAFF > ROLE_GUEST
2023-06-09 21:17:39.884 DEBUG 20580 --- [ restartedMain] o.s.s.a.h.RoleHierarchyImpl : buildRolesReachableInOneStepMap() - From role ROLE_ADMIN one
can reach role ROLE_STAFF in one step.
2023-06-09 21:17:39.885 DEBUG 20580 --- [ restartedMain] o.s.s.a.h.RoleHierarchyImpl : buildRolesReachableInOneStepMap() - From role ROLE_STAFF one
can reach role ROLE_USER in one step.
2023-06-09 21:17:39.885 DEBUG 20580 --- [ restartedMain] o.s.s.a.h.RoleHierarchyImpl : buildRolesReachableInOneStepMap() - From role ROLE_STAFF one
can reach role ROLE_GUEST in one step.
2023-06-09 21:17:39.886 DEBUG 20580 --- [ restartedMain] o.s.s.a.h.RoleHierarchyImpl : buildRolesReachableInOneOrMoreStepsMap() - From role ROLE_STAFF one can reach [ROLE_USER, ROLE_GUEST] in one or more steps.
2023-06-09 21:17:39.888 DEBUG 20580 --- [ restartedMain] o.s.s.a.h.RoleHierarchyImpl : buildRolesReachableInOneOrMoreStepsMap() - From role ROLE_ADMIN one can reach [ROLE_USER, ROLE_STAFF, ROLE_GUEST] in one or more steps.
Which is correct, but it is more prone to mistake (with more complex setup), and "uglier" to declare this way via \n
Luckily, for most use case, I can replace it with RoleHierarchyUtils.roleHierarchyFromMap
but not for this case where there's a repeated key. And since we are using Map
, key
has to be unique.
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
Map<String, List<String>> roleHierarchyMap = new HashMap<>();
roleHierarchyMap.put("ROLE_ADMIN", List.of("ROLE_STAFF"));
roleHierarchyMap.put("ROLE_STAFF", List.of("ROLE_USER"));
// Because it is Map, I can't quite define this
// roleHierarchyMap.put("ROLE_STAFF", List.of("ROLE_GUEST"));
String roleHierarchyFromMap = RoleHierarchyUtils.roleHierarchyFromMap(roleHierarchyMap);
roleHierarchy.setHierarchy(roleHierarchyFromMap);
return roleHierarchy;
}
Note that for this use case, ROLE_STAFF
inherit ROLE_USER
AND inherit ROLE_GUEST
but ROLE_USER
does not inherit ROLE_GUEST
. Hence, I can't simply do the following
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
Map<String, List<String>> roleHierarchyMap = new HashMap<>();
roleHierarchyMap.put("ROLE_ADMIN", List.of("ROLE_STAFF"));
roleHierarchyMap.put("ROLE_STAFF", List.of("ROLE_USER", "ROLE_GUEST"));
String roleHierarchyFromMap = RoleHierarchyUtils.roleHierarchyFromMap(roleHierarchyMap);
roleHierarchy.setHierarchy(roleHierarchyFromMap);
return roleHierarchy;
}
Which is a limitation for this use case.
I have another way to declare. Since Java now supports TextBlock
, I can still define as
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
Map<String, List<String>> roleHierarchyMap = new HashMap<>();
String roleHierarchyFromMap = """
ROLE_ADMIN > ROLE_STAFF
ROLE_STAFF > ROLE_USER
ROLE_STAFF > ROLE_GUEST
""";
roleHierarchy.setHierarchy(roleHierarchyFromMap);
return roleHierarchy;
}
Which still works. But I do still like the way that I use Map
to define my hierarchy, which is still clearer, better and straightforward IMO. And I think it's easier to support the declaration via application.yaml
and construct through @ConfigurationProperties
and set it.
I wonder if there's any way to support my use case which make the declaration easier.
Thanks!