Trigger clearing the user cache when the duplicate email allowed flag changes
Closes #31045 Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
parent
0b5f42f95d
commit
6d404b86c9
3 changed files with 53 additions and 25 deletions
|
@ -29,12 +29,11 @@ import org.keycloak.models.cache.UserCache;
|
|||
import org.keycloak.models.cache.UserCacheProviderFactory;
|
||||
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
||||
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||
import org.keycloak.provider.InvalidationHandler;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class InfinispanUserCacheProviderFactory implements UserCacheProviderFactory, InvalidationHandler {
|
||||
public class InfinispanUserCacheProviderFactory implements UserCacheProviderFactory {
|
||||
|
||||
private static final Logger log = Logger.getLogger(InfinispanUserCacheProviderFactory.class);
|
||||
public static final String USER_CLEAR_CACHE_EVENTS = "USER_CLEAR_CACHE_EVENTS";
|
||||
|
@ -79,15 +78,6 @@ public class InfinispanUserCacheProviderFactory implements UserCacheProviderFact
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate(KeycloakSession session, InvalidableObjectType type, Object... params) {
|
||||
if (type == ObjectType.REALM || type == ObjectType.USER) {
|
||||
if (this.userCache != null) {
|
||||
this.userCache.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
}
|
||||
|
|
|
@ -18,9 +18,32 @@
|
|||
package org.keycloak.models.cache.infinispan;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.cluster.ClusterProvider;
|
||||
import org.keycloak.common.enums.SslRequired;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.*;
|
||||
import org.keycloak.models.AbstractKeycloakTransaction;
|
||||
import org.keycloak.models.AuthenticationExecutionModel;
|
||||
import org.keycloak.models.AuthenticationFlowModel;
|
||||
import org.keycloak.models.AuthenticatorConfigModel;
|
||||
import org.keycloak.models.CibaConfig;
|
||||
import org.keycloak.models.ClientInitialAccessModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ClientScopeModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.IdentityProviderMapperModel;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.OAuth2DeviceConfig;
|
||||
import org.keycloak.models.OTPPolicy;
|
||||
import org.keycloak.models.OrganizationModel;
|
||||
import org.keycloak.models.ParConfig;
|
||||
import org.keycloak.models.PasswordPolicy;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RequiredActionConfigModel;
|
||||
import org.keycloak.models.RequiredActionProviderModel;
|
||||
import org.keycloak.models.RequiredCredentialModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.WebAuthnPolicy;
|
||||
import org.keycloak.models.cache.CachedRealmModel;
|
||||
import org.keycloak.models.cache.UserCache;
|
||||
import org.keycloak.models.cache.infinispan.entities.CachedRealm;
|
||||
|
@ -28,7 +51,12 @@ import org.keycloak.storage.UserStorageProvider;
|
|||
import org.keycloak.storage.UserStorageUtil;
|
||||
import org.keycloak.storage.client.ClientStorageProvider;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -362,6 +390,22 @@ public class RealmAdapter implements CachedRealmModel {
|
|||
@Override
|
||||
public void setDuplicateEmailsAllowed(boolean duplicateEmailsAllowed) {
|
||||
getDelegateForUpdate();
|
||||
if (updated.isDuplicateEmailsAllowed() != duplicateEmailsAllowed) {
|
||||
// If the flag changed, we need to clear all entries from the user cache as there are entries with the key of the email address which need to be re-evaluated.
|
||||
// Still, this must only happen after all changes have been written to the database, therefore we enlist this to run after the completion of the transaction.
|
||||
session.getTransactionManager().enlistAfterCompletion(new AbstractKeycloakTransaction() {
|
||||
@Override
|
||||
protected void commitImpl() {
|
||||
ClusterProvider cluster = session.getProvider(ClusterProvider.class);
|
||||
cluster.notify(InfinispanUserCacheProviderFactory.USER_CLEAR_CACHE_EVENTS, ClearCacheEvent.getInstance(), false, ClusterProvider.DCNotify.ALL_DCS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void rollbackImpl() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
updated.setDuplicateEmailsAllowed(duplicateEmailsAllowed);
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,6 @@ import org.keycloak.models.utils.RepresentationToModel;
|
|||
import org.keycloak.partialimport.ErrorResponseException;
|
||||
import org.keycloak.partialimport.PartialImportResult;
|
||||
import org.keycloak.partialimport.PartialImportResults;
|
||||
import org.keycloak.provider.InvalidationHandler;
|
||||
import org.keycloak.representations.adapters.action.GlobalRequestResult;
|
||||
import org.keycloak.representations.idm.AdminEventRepresentation;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
|
@ -446,7 +445,6 @@ public class RealmAdminResource {
|
|||
}
|
||||
}
|
||||
|
||||
boolean wasDuplicateEmailsAllowed = realm.isDuplicateEmailsAllowed();
|
||||
RepresentationToModel.updateRealm(rep, realm, session);
|
||||
|
||||
// Refresh periodic sync tasks for configured federationProviders
|
||||
|
@ -457,10 +455,6 @@ public class RealmAdminResource {
|
|||
|
||||
adminEvent.operation(OperationType.UPDATE).representation(rep).success();
|
||||
|
||||
if (rep.isDuplicateEmailsAllowed() != null && rep.isDuplicateEmailsAllowed() != wasDuplicateEmailsAllowed) {
|
||||
session.invalidate(InvalidationHandler.ObjectType.REALM, realm.getId());
|
||||
}
|
||||
|
||||
return Response.noContent().build();
|
||||
} catch (ModelDuplicateException e) {
|
||||
throw ErrorResponse.exists("Realm with same name exists");
|
||||
|
|
Loading…
Reference in a new issue