Incrementally cache consents on a per client basis

Closes #16224
This commit is contained in:
Pedro Igor 2023-01-03 11:10:00 -03:00
parent 496c6d598e
commit fb554c09db
3 changed files with 63 additions and 8 deletions

View file

@ -65,6 +65,7 @@ import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.client.ClientStorageProvider;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -681,13 +682,35 @@ public class UserCacheSession implements UserCache, OnCreateComponent, OnUpdateC
CachedUserConsents cached = cache.get(cacheKey, CachedUserConsents.class);
if (cached == null) {
UserConsentModel consent = getDelegate().getConsentByClient(realm, userId, clientId);
List<CachedUserConsent> consents;
if (consent == null) {
consents = Collections.singletonList(new CachedUserConsent(clientId));
} else {
consents = Collections.singletonList(new CachedUserConsent(consent));
}
Long loaded = cache.getCurrentRevision(cacheKey);
List<UserConsentModel> consents = getDelegate().getConsentsStream(realm, userId).collect(Collectors.toList());
cached = new CachedUserConsents(loaded, cacheKey, realm, consents);
cached = new CachedUserConsents(loaded, cacheKey, realm, consents, false);
cache.addRevisioned(cached, startupRevision);
}
CachedUserConsent cachedConsent = cached.getConsents().get(clientId);
if (cachedConsent == null) return null;
Map<String, CachedUserConsent> consents = cached.getConsents();
CachedUserConsent cachedConsent = consents.get(clientId);
if (cachedConsent == null) {
UserConsentModel consent = getDelegate().getConsentByClient(realm, userId, clientId);
if (consent == null) {
cachedConsent = new CachedUserConsent(clientId);
} else {
cachedConsent = new CachedUserConsent(consent);
}
consents.put(cachedConsent.getClientDbId(), cachedConsent);
}
return toConsentModel(realm, cachedConsent);
}
@ -702,10 +725,15 @@ public class UserCacheSession implements UserCache, OnCreateComponent, OnUpdateC
CachedUserConsents cached = cache.get(cacheKey, CachedUserConsents.class);
if (cached != null && !cached.isAllConsents()) {
cached = null;
cache.invalidateObject(cacheKey);
}
if (cached == null) {
Long loaded = cache.getCurrentRevision(cacheKey);
List<UserConsentModel> consents = getDelegate().getConsentsStream(realm, userId).collect(Collectors.toList());
cached = new CachedUserConsents(loaded, cacheKey, realm, consents);
cached = new CachedUserConsents(loaded, cacheKey, realm, consents.stream().map(CachedUserConsent::new).collect(Collectors.toList()));
cache.addRevisioned(cached, startupRevision);
return consents.stream();
} else {
@ -715,6 +743,10 @@ public class UserCacheSession implements UserCache, OnCreateComponent, OnUpdateC
}
private UserConsentModel toConsentModel(RealmModel realm, CachedUserConsent cachedConsent) {
if (cachedConsent.isNotExistent()) {
return null;
}
ClientModel client = session.clients().getClientById(realm, cachedConsent.getClientDbId());
if (client == null) {
return null;

View file

@ -32,6 +32,7 @@ public class CachedUserConsent {
private final Set<String> clientScopeIds = new HashSet<>();
private final Long createdDate;
private final Long lastUpdatedDate;
private boolean notExistent;
public CachedUserConsent(UserConsentModel consentModel) {
this.clientDbId = consentModel.getClient().getId();
@ -42,6 +43,13 @@ public class CachedUserConsent {
this.lastUpdatedDate = consentModel.getLastUpdatedDate();
}
public CachedUserConsent(String clientDbId) {
this.clientDbId = clientDbId;
this.createdDate = null;
this.lastUpdatedDate = null;
this.notExistent = true;
}
public String getClientDbId() {
return clientDbId;
}
@ -57,4 +65,8 @@ public class CachedUserConsent {
public Long getLastUpdatedDate() {
return lastUpdatedDate;
}
public boolean isNotExistent() {
return notExistent;
}
}

View file

@ -29,14 +29,21 @@ import java.util.List;
public class CachedUserConsents extends AbstractRevisioned implements InRealm {
private HashMap<String, CachedUserConsent> consents = new HashMap<>();
private final String realmId;
private boolean allConsents;
public CachedUserConsents(Long revision, String id, RealmModel realm,
List<UserConsentModel> consents) {
List<CachedUserConsent> consents) {
this(revision, id, realm, consents, true);
}
public CachedUserConsents(Long revision, String id, RealmModel realm,
List<CachedUserConsent> consents, boolean allConsents) {
super(revision, id);
this.realmId = realm.getId();
this.allConsents = allConsents;
if (consents != null) {
for (UserConsentModel consent : consents) {
this.consents.put(consent.getClient().getId(), new CachedUserConsent(consent));
for (CachedUserConsent consent : consents) {
this.consents.put(consent.getClientDbId(), consent);
}
}
}
@ -50,4 +57,8 @@ public class CachedUserConsents extends AbstractRevisioned implements InRealm {
public HashMap<String, CachedUserConsent> getConsents() {
return consents;
}
public boolean isAllConsents() {
return allConsents;
}
}