
org.molgenis.data.security.DataserviceRoleHierarchy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of molgenis-data-security Show documentation
Show all versions of molgenis-data-security Show documentation
Security data model and data layer security.
package org.molgenis.data.security;
import static com.google.common.collect.ImmutableSet.copyOf;
import static com.google.common.collect.Sets.difference;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
import static org.molgenis.data.security.auth.RoleMetadata.INCLUDES;
import static org.molgenis.data.security.auth.RoleMetadata.NAME;
import static org.molgenis.data.security.auth.RoleMetadata.ROLE;
import static org.molgenis.security.core.SidUtils.ROLE_PREFIX;
import static org.molgenis.security.core.runas.RunAsSystemAspect.runAsSystem;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.molgenis.data.DataService;
import org.molgenis.data.Fetch;
import org.molgenis.data.Query;
import org.molgenis.data.Sort;
import org.molgenis.data.security.auth.Role;
import org.molgenis.data.support.QueryImpl;
import org.molgenis.security.core.SidUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
public class DataserviceRoleHierarchy implements RoleHierarchy {
private static final Logger LOG = LoggerFactory.getLogger(DataserviceRoleHierarchy.class);
private static final int PAGE_SIZE = 1000;
private final DataService dataService;
public DataserviceRoleHierarchy(DataService dataService) {
this.dataService = requireNonNull(dataService);
}
@Override
public Collection extends GrantedAuthority> getReachableGrantedAuthorities(
Collection extends GrantedAuthority> authorities) {
// TODO RunAsSystem annotation not hit via OIDC route (but why?!)
return runAsSystem(
() -> {
if (authorities == null || authorities.isEmpty()) {
return AuthorityUtils.NO_AUTHORITIES;
}
Set roleNames =
authorities
.stream()
.map(GrantedAuthority::getAuthority)
.filter(name -> name.startsWith(ROLE_PREFIX))
.map(name -> name.substring(ROLE_PREFIX.length()))
.collect(toSet());
Multimap allRoleInclusions = getAllRoleInclusions();
Set newlyDiscovered = roleNames;
while (!newlyDiscovered.isEmpty()) {
Set included =
newlyDiscovered
.stream()
.flatMap(role -> allRoleInclusions.get(role).stream())
.collect(toSet());
newlyDiscovered = copyOf(difference(included, roleNames));
roleNames.addAll(newlyDiscovered);
}
Set reachableRoles =
roleNames
.stream()
.map(SidUtils::createRoleAuthority)
.map(SimpleGrantedAuthority::new)
.collect(toSet());
LOG.debug(
"getReachableGrantedAuthorities() - From the roles {} one can reach {} in zero or more steps.",
authorities,
reachableRoles);
return reachableRoles;
});
}
private Multimap getAllRoleInclusions() {
ImmutableMultimap.Builder result = ImmutableMultimap.builder();
for (Role role : getAllRoles()) {
for (Role included : role.getIncludes()) {
result.put(role.getName(), included.getName());
}
}
return result.build();
}
private List getAllRoles() {
ImmutableList.Builder result = new ImmutableList.Builder<>();
int offSet = 0;
List batch = getRolesBatch(offSet);
while (batch.size() == PAGE_SIZE) {
result.addAll(batch);
batch = getRolesBatch(++offSet);
}
result.addAll(batch);
return result.build();
}
private List getRolesBatch(int offSet) {
Query query = QueryImpl.query();
Fetch fetch = new Fetch();
Fetch childFetch = new Fetch();
childFetch.field(NAME);
fetch.field(NAME).field(INCLUDES, childFetch);
query.fetch(fetch);
query.pageSize(PAGE_SIZE);
query.offset(offSet);
query.sort(new Sort(NAME));
return dataService.findAll(ROLE, query, Role.class).collect(toList());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy