KEYCLOAK-16077 Remove need for MapStorage.replace

This commit is contained in:
Hynek Mlnarik 2020-10-26 12:19:28 +01:00 committed by Hynek Mlnařík
parent 1418c6e938
commit 925f089d62
14 changed files with 53 additions and 62 deletions

View file

@ -23,7 +23,7 @@ import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.RealmModel.ClientRemovedEvent; import org.keycloak.models.ClientModel.ClientRemovedEvent;
import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation; import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
import org.keycloak.representations.idm.authorization.PolicyRepresentation; import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;

View file

@ -32,6 +32,7 @@ import org.keycloak.jose.jwk.JWK;
import org.keycloak.keys.PublicKeyStorageProvider; import org.keycloak.keys.PublicKeyStorageProvider;
import org.keycloak.keys.PublicKeyStorageProviderFactory; import org.keycloak.keys.PublicKeyStorageProviderFactory;
import org.keycloak.keys.PublicKeyStorageUtils; import org.keycloak.keys.PublicKeyStorageUtils;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
@ -117,15 +118,15 @@ public class InfinispanPublicKeyStorageProviderFactory implements PublicKeyStora
private SessionAndKeyHolder getCacheKeyToInvalidate(ProviderEvent event) { private SessionAndKeyHolder getCacheKeyToInvalidate(ProviderEvent event) {
ArrayList<String> cacheKeys = new ArrayList<>(); ArrayList<String> cacheKeys = new ArrayList<>();
String cacheKey = null; String cacheKey = null;
if (event instanceof RealmModel.ClientUpdatedEvent) { if (event instanceof ClientModel.ClientUpdatedEvent) {
RealmModel.ClientUpdatedEvent eventt = (RealmModel.ClientUpdatedEvent) event; ClientModel.ClientUpdatedEvent eventt = (ClientModel.ClientUpdatedEvent) event;
cacheKey = PublicKeyStorageUtils.getClientModelCacheKey(eventt.getUpdatedClient().getRealm().getId(), eventt.getUpdatedClient().getId(), JWK.Use.SIG); cacheKey = PublicKeyStorageUtils.getClientModelCacheKey(eventt.getUpdatedClient().getRealm().getId(), eventt.getUpdatedClient().getId(), JWK.Use.SIG);
cacheKeys.add(cacheKey); cacheKeys.add(cacheKey);
cacheKey = PublicKeyStorageUtils.getClientModelCacheKey(eventt.getUpdatedClient().getRealm().getId(), eventt.getUpdatedClient().getId(), JWK.Use.ENCRYPTION); cacheKey = PublicKeyStorageUtils.getClientModelCacheKey(eventt.getUpdatedClient().getRealm().getId(), eventt.getUpdatedClient().getId(), JWK.Use.ENCRYPTION);
cacheKeys.add(cacheKey); cacheKeys.add(cacheKey);
return new SessionAndKeyHolder(eventt.getKeycloakSession(), cacheKeys); return new SessionAndKeyHolder(eventt.getKeycloakSession(), cacheKeys);
} else if (event instanceof RealmModel.ClientRemovedEvent) { } else if (event instanceof ClientModel.ClientRemovedEvent) {
RealmModel.ClientRemovedEvent eventt = (RealmModel.ClientRemovedEvent) event; ClientModel.ClientRemovedEvent eventt = (ClientModel.ClientRemovedEvent) event;
cacheKey = PublicKeyStorageUtils.getClientModelCacheKey(eventt.getClient().getRealm().getId(), eventt.getClient().getId(), JWK.Use.SIG); cacheKey = PublicKeyStorageUtils.getClientModelCacheKey(eventt.getClient().getRealm().getId(), eventt.getClient().getId(), JWK.Use.SIG);
cacheKeys.add(cacheKey); cacheKeys.add(cacheKey);
cacheKey = PublicKeyStorageUtils.getClientModelCacheKey(eventt.getClient().getRealm().getId(), eventt.getClient().getId(), JWK.Use.ENCRYPTION); cacheKey = PublicKeyStorageUtils.getClientModelCacheKey(eventt.getClient().getRealm().getId(), eventt.getClient().getId(), JWK.Use.ENCRYPTION);

View file

@ -513,8 +513,7 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
@Override @Override
public void updateClient() { public void updateClient() {
em.flush(); session.getKeycloakSessionFactory().publish(new ClientModel.ClientUpdatedEvent() {
session.getKeycloakSessionFactory().publish(new RealmModel.ClientUpdatedEvent() {
@Override @Override
public ClientModel getUpdatedClient() { public ClientModel getUpdatedClient() {

View file

@ -624,6 +624,10 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, GroupPro
@Override @Override
public ClientModel addClient(RealmModel realm, String id, String clientId) { public ClientModel addClient(RealmModel realm, String id, String clientId) {
if (id == null) {
id = KeycloakModelUtils.generateId();
}
if (clientId == null) { if (clientId == null) {
clientId = id; clientId = id;
} }
@ -638,16 +642,10 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, GroupPro
RealmEntity realmRef = em.getReference(RealmEntity.class, realm.getId()); RealmEntity realmRef = em.getReference(RealmEntity.class, realm.getId());
entity.setRealm(realmRef); entity.setRealm(realmRef);
em.persist(entity); em.persist(entity);
em.flush();
final ClientModel resource = new ClientAdapter(realm, em, session, entity); final ClientModel resource = new ClientAdapter(realm, em, session, entity);
em.flush(); session.getKeycloakSessionFactory().publish((ClientModel.ClientCreationEvent) () -> resource);
session.getKeycloakSessionFactory().publish(new RealmModel.ClientCreationEvent() {
@Override
public ClientModel getCreatedClient() {
return resource;
}
});
return resource; return resource;
} }
@ -745,7 +743,7 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, GroupPro
ClientEntity clientEntity = em.find(ClientEntity.class, id, LockModeType.PESSIMISTIC_WRITE); ClientEntity clientEntity = em.find(ClientEntity.class, id, LockModeType.PESSIMISTIC_WRITE);
session.getKeycloakSessionFactory().publish(new RealmModel.ClientRemovedEvent() { session.getKeycloakSessionFactory().publish(new ClientModel.ClientRemovedEvent() {
@Override @Override
public ClientModel getClient() { public ClientModel getClient() {
return client; return client;

View file

@ -19,12 +19,12 @@ package org.keycloak.models.map.client;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientModel.ClientUpdatedEvent;
import org.keycloak.models.ClientProvider; import org.keycloak.models.ClientProvider;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.RealmModel.ClientUpdatedEvent;
import org.keycloak.models.map.storage.MapKeycloakTransaction; import org.keycloak.models.map.storage.MapKeycloakTransaction;
import org.keycloak.models.map.common.Serialization; import org.keycloak.models.map.common.Serialization;
import java.util.Comparator; import java.util.Comparator;
@ -71,7 +71,7 @@ public class MapClientProvider implements ClientProvider {
} }
private ClientUpdatedEvent clientUpdatedEvent(ClientModel c) { private ClientUpdatedEvent clientUpdatedEvent(ClientModel c) {
return new RealmModel.ClientUpdatedEvent() { return new ClientModel.ClientUpdatedEvent() {
@Override @Override
public ClientModel getUpdatedClient() { public ClientModel getUpdatedClient() {
return c; return c;
@ -96,8 +96,6 @@ public class MapClientProvider implements ClientProvider {
return origEntity -> new MapClientAdapter(session, realm, registerEntityForChanges(origEntity)) { return origEntity -> new MapClientAdapter(session, realm, registerEntityForChanges(origEntity)) {
@Override @Override
public void updateClient() { public void updateClient() {
// commit
MapClientProvider.this.tx.replace(entity.getId(), this.entity);
session.getKeycloakSessionFactory().publish(clientUpdatedEvent(this)); session.getKeycloakSessionFactory().publish(clientUpdatedEvent(this));
} }
@ -178,7 +176,7 @@ public class MapClientProvider implements ClientProvider {
final ClientModel resource = entityToAdapterFunc(realm).apply(entity); final ClientModel resource = entityToAdapterFunc(realm).apply(entity);
// TODO: Sending an event should be extracted to store layer // TODO: Sending an event should be extracted to store layer
session.getKeycloakSessionFactory().publish((RealmModel.ClientCreationEvent) () -> resource); session.getKeycloakSessionFactory().publish((ClientModel.ClientCreationEvent) () -> resource);
resource.updateClient(); // This is actualy strange contract - it should be the store code to call updateClient resource.updateClient(); // This is actualy strange contract - it should be the store code to call updateClient
return resource; return resource;
@ -214,7 +212,7 @@ public class MapClientProvider implements ClientProvider {
session.users().preRemove(realm, client); session.users().preRemove(realm, client);
session.roles().removeRoles(client); session.roles().removeRoles(client);
session.getKeycloakSessionFactory().publish(new RealmModel.ClientRemovedEvent() { session.getKeycloakSessionFactory().publish(new ClientModel.ClientRemovedEvent() {
@Override @Override
public ClientModel getClient() { public ClientModel getClient() {
return client; return client;

View file

@ -65,17 +65,6 @@ public class MapKeycloakTransaction<K, V> implements KeycloakTransaction {
}; };
} }
}, },
REPLACE {
@Override
protected <K, V> MapTaskWithValue<K, V> taskFor(K key, V value) {
return new MapTaskWithValue<K, V>(value) {
@Override
public void execute(MapStorage<K, V> map) {
map.replace(key, getValue());
}
};
}
},
; ;
protected abstract <K, V> MapTaskWithValue<K, V> taskFor(K key, V value); protected abstract <K, V> MapTaskWithValue<K, V> taskFor(K key, V value);
@ -179,10 +168,6 @@ public class MapKeycloakTransaction<K, V> implements KeycloakTransaction {
tasks.merge(taskKey, op, MapTaskCompose::new); tasks.merge(taskKey, op, MapTaskCompose::new);
} }
public void replace(K key, V value) {
addTask(MapOperation.REPLACE, key, value);
}
public void remove(K key) { public void remove(K key) {
addTask(MapOperation.REMOVE, key, null); addTask(MapOperation.REMOVE, key, null);
} }

View file

@ -34,8 +34,6 @@ public interface MapStorage<K, V> {
V remove(K key); V remove(K key);
V replace(K key, V value);
Set<K> keySet(); Set<K> keySet();
Set<Map.Entry<K,V>> entrySet(); Set<Map.Entry<K,V>> entrySet();

View file

@ -28,7 +28,7 @@ import org.keycloak.authorization.store.syncronization.Synchronizer;
import org.keycloak.authorization.store.syncronization.UserSynchronizer; import org.keycloak.authorization.store.syncronization.UserSynchronizer;
import org.keycloak.models.GroupModel; import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel.ClientRemovedEvent; import org.keycloak.models.ClientModel.ClientRemovedEvent;
import org.keycloak.models.RealmModel.RealmRemovedEvent; import org.keycloak.models.RealmModel.RealmRemovedEvent;
import org.keycloak.models.UserModel.UserRemovedEvent; import org.keycloak.models.UserModel.UserRemovedEvent;
import org.keycloak.provider.ProviderEvent; import org.keycloak.provider.ProviderEvent;

View file

@ -30,7 +30,7 @@ import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
import org.keycloak.authorization.store.ResourceServerStore; import org.keycloak.authorization.store.ResourceServerStore;
import org.keycloak.authorization.store.StoreFactory; import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel.ClientRemovedEvent; import org.keycloak.models.ClientModel.ClientRemovedEvent;
import org.keycloak.provider.ProviderFactory; import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation; import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;

View file

@ -46,8 +46,8 @@ public abstract class AbstractLoginProtocolFactory implements LoginProtocolFacto
factory.register(new ProviderEventListener() { factory.register(new ProviderEventListener() {
@Override @Override
public void onEvent(ProviderEvent event) { public void onEvent(ProviderEvent event) {
if (event instanceof RealmModel.ClientCreationEvent) { if (event instanceof ClientModel.ClientCreationEvent) {
ClientModel client = ((RealmModel.ClientCreationEvent)event).getCreatedClient(); ClientModel client = ((ClientModel.ClientCreationEvent)event).getCreatedClient();
addDefaultClientScopes(client.getRealm(), client); addDefaultClientScopes(client.getRealm(), client);
addDefaults(client); addDefaults(client);
} }

View file

@ -120,7 +120,7 @@ public abstract class AbstractClientStorageAdapter extends UnsupportedOperations
*/ */
@Override @Override
public void updateClient() { public void updateClient() {
session.getKeycloakSessionFactory().publish(new RealmModel.ClientUpdatedEvent() { session.getKeycloakSessionFactory().publish(new ClientModel.ClientUpdatedEvent() {
@Override @Override
public ClientModel getUpdatedClient() { public ClientModel getUpdatedClient() {

View file

@ -21,6 +21,8 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import org.keycloak.common.util.ObjectUtil; import org.keycloak.common.util.ObjectUtil;
import org.keycloak.provider.ProviderEvent;
import org.keycloak.provider.ProviderEventManager;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -34,10 +36,35 @@ public interface ClientModel extends ClientScopeModel, RoleContainerModel, Prot
String PUBLIC_KEY = "publicKey"; String PUBLIC_KEY = "publicKey";
String X509CERTIFICATE = "X509Certificate"; String X509CERTIFICATE = "X509Certificate";
interface ClientCreationEvent extends ProviderEvent {
ClientModel getCreatedClient();
}
// Called also during client creation after client is fully initialized (including all attributes etc)
interface ClientUpdatedEvent extends ProviderEvent {
ClientModel getUpdatedClient();
KeycloakSession getKeycloakSession();
}
interface ClientRemovedEvent extends ProviderEvent {
ClientModel getClient();
KeycloakSession getKeycloakSession();
}
/** /**
* Stores the current state of the client immediately to the underlying store, similarly to a commit. * Notifies other providers that this client has been updated.
* <p>
* After a client is updated, providers can register for {@link ClientUpdatedEvent}.
* The setters in this model do not send an update for individual updates of the model.
* This method is here to allow for sending this event for this client,
* allowsing for to group multiple changes of a client and signal that
* all the changes in this client have been performed.
* *
* @deprecated Do not use, to be removed * @deprecated Do not use, to be removed
*
* @see ProviderEvent
* @see ProviderEventManager
* @see ClientUpdatedEvent
*/ */
void updateClient(); void updateClient();

View file

@ -52,21 +52,6 @@ public interface RealmModel extends RoleContainerModel {
KeycloakSession getKeycloakSession(); KeycloakSession getKeycloakSession();
} }
interface ClientCreationEvent extends ProviderEvent {
ClientModel getCreatedClient();
}
// Called also during client creation after client is fully initialized (including all attributes etc)
interface ClientUpdatedEvent extends ProviderEvent {
ClientModel getUpdatedClient();
KeycloakSession getKeycloakSession();
}
interface ClientRemovedEvent extends ProviderEvent {
ClientModel getClient();
KeycloakSession getKeycloakSession();
}
interface IdentityProviderUpdatedEvent extends ProviderEvent { interface IdentityProviderUpdatedEvent extends ProviderEvent {
RealmModel getRealm(); RealmModel getRealm();
IdentityProviderModel getUpdatedIdentityProvider(); IdentityProviderModel getUpdatedIdentityProvider();

View file

@ -69,8 +69,8 @@ public class AdminPermissions {
realm = (RealmModel)role.getContainer(); realm = (RealmModel)role.getContainer();
} }
management(cast.getKeycloakSession(), realm).roles().setPermissionsEnabled(role, false); management(cast.getKeycloakSession(), realm).roles().setPermissionsEnabled(role, false);
} else if (event instanceof RealmModel.ClientRemovedEvent) { } else if (event instanceof ClientModel.ClientRemovedEvent) {
RealmModel.ClientRemovedEvent cast = (RealmModel.ClientRemovedEvent)event; ClientModel.ClientRemovedEvent cast = (ClientModel.ClientRemovedEvent)event;
management(cast.getKeycloakSession(), cast.getClient().getRealm()).clients().setPermissionsEnabled(cast.getClient(), false); management(cast.getKeycloakSession(), cast.getClient().getRealm()).clients().setPermissionsEnabled(cast.getClient(), false);
} else if (event instanceof GroupModel.GroupRemovedEvent) { } else if (event instanceof GroupModel.GroupRemovedEvent) {
GroupModel.GroupRemovedEvent cast = (GroupModel.GroupRemovedEvent)event; GroupModel.GroupRemovedEvent cast = (GroupModel.GroupRemovedEvent)event;