Also cache client roles if looked up by name and not found

Closes #36919

Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
Alexander Schwartz 2025-01-30 22:25:42 +01:00 committed by Pedro Igor
parent a3c175ffc0
commit 61a44657f0
2 changed files with 56 additions and 2 deletions

View File

@ -895,12 +895,20 @@ public class RealmCacheSession implements CacheRealmProvider {
if (query == null) {
Long loaded = cache.getCurrentRevision(cacheKey);
RoleModel model = getRoleDelegate().getClientRole(client, name);
if (model == null) return null;
query = new RoleListQuery(loaded, cacheKey, client.getRealm(), model.getId(), client.getClientId());
if (model == null) {
// caching empty results will speed up the policy evaluation which tries to look up the role by name and ID
query = new RoleListQuery(loaded, cacheKey, client.getRealm(), Set.of());
} else {
query = new RoleListQuery(loaded, cacheKey, client.getRealm(), model.getId(), client.getClientId());
}
logger.tracev("adding client role cache miss: client {0} key {1}", client.getClientId(), cacheKey);
cache.addRevisioned(query, startupRevision);
return model;
}
Iterator<String> iterator = query.getRoles().iterator();
if (!iterator.hasNext()) {
return null;
}
RoleModel role = getRoleById(client.getRealm(), query.getRoles().iterator().next());
if (role == null) {
invalidations.add(cacheKey);

View File

@ -348,6 +348,52 @@ public class RoleModelTest extends KeycloakModelTest {
}
@Test
public void getClientRoleByNameFromTheDatabaseAndTheCache() {
String roleName = "role-" + new Random().nextInt();
// Look up a non-existent role from the database
withRealm(realmId, (session, realm) -> {
ClientModel client = session.clients().getClientByClientId(realm, CLIENT_NAME);
RoleModel role = session.roles().getClientRole(client, roleName);
assertThat(role, nullValue());
return null;
});
// Look up a non-existent role from the cache
withRealm(realmId, (session, realm) -> {
ClientModel client = session.clients().getClientByClientId(realm, CLIENT_NAME);
RoleModel role = session.roles().getClientRole(client, roleName);
assertThat(role, nullValue());
return null;
});
// Create the role, and invalidate the cache
withRealm(realmId, (session, realm) -> {
ClientModel client = session.clients().getClientByClientId(realm, CLIENT_NAME);
RoleModel role = session.roles().addClientRole(client, roleName);
assertThat(role, notNullValue());
return null;
});
// Find the role from the database
withRealm(realmId, (session, realm) -> {
ClientModel client = session.clients().getClientByClientId(realm, CLIENT_NAME);
RoleModel role = session.roles().getClientRole(client, roleName);
assertThat(role, notNullValue());
return null;
});
// Find the role from the cache
withRealm(realmId, (session, realm) -> {
ClientModel client = session.clients().getClientByClientId(realm, CLIENT_NAME);
RoleModel role = session.roles().getClientRole(client, roleName);
assertThat(role, notNullValue());
return null;
});
}
public void testRolesWithIdsPaginationSearchQueries(GetResult resultProvider) {
// test all parameters together
List<RoleModel> result = resultProvider.getResult("1", 4, 3);