Skip to content

Commit

Permalink
More efficient listing of assigned and available client role mappings
Browse files Browse the repository at this point in the history
Closes keycloak#23404

Signed-off-by: Sebastian Schuster <sebastian.schuster@bosch.io>
Co-authored-by: Vlasta Ramik <vramik@users.noreply.github.com>
  • Loading branch information
sschu and vramik authored Nov 22, 2023
1 parent 203eb34 commit 030f42e
Show file tree
Hide file tree
Showing 14 changed files with 380 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,16 @@ public Stream<RoleModel> searchForClientRolesStream(ClientModel client, String s
return getRoleDelegate().searchForClientRolesStream(client, search, first, max);
}

@Override
public Stream<RoleModel> searchForClientRolesStream(RealmModel realm, Stream<String> ids, String search, Integer first, Integer max) {
return getRoleDelegate().searchForClientRolesStream(realm, ids, search, first, max);
}

@Override
public Stream<RoleModel> searchForClientRolesStream(RealmModel realm, String search, Stream<String> excludedIds, Integer first, Integer max) {
return getRoleDelegate().searchForClientRolesStream(realm, search, excludedIds, first, max);
}

@Override
public Stream<RoleModel> searchForRolesStream(RealmModel realm, String search, Integer first, Integer max) {
return getRoleDelegate().searchForRolesStream(realm, search, first, max);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,53 @@ public Stream<RoleModel> getRolesStream(RealmModel realm, Stream<String> ids, St
.map(g -> session.roles().getRoleById(realm, g));
}

@Override
public Stream<RoleModel> searchForClientRolesStream(RealmModel realm, Stream<String> ids, String search, Integer first, Integer max) {
return searchForClientRolesStream(realm, ids, search, first, max, false);
}
@Override
public Stream<RoleModel> searchForClientRolesStream(RealmModel realm, String search, Stream<String> excludedIds, Integer first, Integer max) {
return searchForClientRolesStream(realm, excludedIds, search, first, max, true);
}

private Stream<RoleModel> searchForClientRolesStream(RealmModel realm, Stream<String> ids, String search, Integer first, Integer max, boolean negateIds) {
List<String> idList = null;
if(ids != null) {
idList = ids.collect(Collectors.toList());
if(idList.isEmpty() && !negateIds)
return Stream.empty();
}
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<RoleEntity> query = cb.createQuery(RoleEntity.class);

Root<RoleEntity> roleRoot = query.from(RoleEntity.class);
Root<ClientEntity> clientRoot = query.from(ClientEntity.class);

List<Predicate> predicates = new ArrayList<>();
predicates.add(cb.equal(roleRoot.get("realmId"), realm.getId()));
predicates.add(cb.isTrue(roleRoot.get("clientRole")));
predicates.add(cb.equal(roleRoot.get("clientId"),clientRoot.get("id")));
if(search != null && !search.isEmpty()) {
search = "%" + search.trim().toLowerCase() + "%";
predicates.add(cb.or(
cb.like(cb.lower(roleRoot.get("name")), search),
cb.like(cb.lower(clientRoot.get("clientId")), search)
));
}
if(idList != null && !idList.isEmpty()) {
Predicate idFilter = roleRoot.get("id").in(idList);
if(negateIds) idFilter = cb.not(idFilter);
predicates.add(idFilter);
}
query.select(roleRoot).where(predicates.toArray(new Predicate[0]))
.orderBy(
cb.asc(clientRoot.get("clientId")),
cb.asc(roleRoot.get("name")));
return closing(paginateQuery(em.createQuery(query),first,max).getResultStream())
.map(roleEntity -> new RoleAdapter(session, realm, em, roleEntity));
}


@Override
public Stream<RoleModel> getClientRolesStream(ClientModel client, Integer first, Integer max) {
TypedQuery<RoleEntity> query = em.createNamedQuery("getClientRoles", RoleEntity.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,28 @@ public Stream<RoleModel> searchForClientRolesStream(ClientModel client, String s
return Stream.concat(local, ext);
}

@Override
public Stream<RoleModel> searchForClientRolesStream(RealmModel realm, Stream<String> ids, String search, Integer first, Integer max) {
Stream<RoleModel> local = localStorage().searchForClientRolesStream(realm, ids, search, first, max);
Stream<RoleModel> ext = getEnabledStorageProviders(session, realm, RoleLookupProvider.class)
.flatMap(ServicesUtils.timeBound(session,
roleStorageProviderTimeout,
p -> ((RoleLookupProvider) p).searchForClientRolesStream(realm, ids, search, first, max)));

return Stream.concat(local, ext);
}

@Override
public Stream<RoleModel> searchForClientRolesStream(RealmModel realm, String search, Stream<String> excludedIds, Integer first, Integer max) {
Stream<RoleModel> local = localStorage().searchForClientRolesStream(realm, search, excludedIds, first, max);
Stream<RoleModel> ext = getEnabledStorageProviders(session, realm, RoleLookupProvider.class)
.flatMap(ServicesUtils.timeBound(session,
roleStorageProviderTimeout,
p -> ((RoleLookupProvider) p).searchForClientRolesStream(realm, search, excludedIds, first, max)));

return Stream.concat(local, ext);
}

@Override
public void close() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,8 @@


public class AuthenticationManagementResource extends RoleMappingResource {
private final KeycloakSession session;

private RealmModel realm;
private AdminPermissionEvaluator auth;

public AuthenticationManagementResource(KeycloakSession session, RealmModel realm, AdminPermissionEvaluator auth) {
super(realm, auth);
this.realm = realm;
this.auth = auth;
this.session = session;
super(session, realm, auth);
}

@GET
Expand Down
Loading

0 comments on commit 030f42e

Please sign in to comment.