parent
29233f33c8
commit
2ecf250e37
38 changed files with 405 additions and 318 deletions
|
@ -477,16 +477,16 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
|
||||||
ClusterProvider cluster = session.getProvider(ClusterProvider.class);
|
ClusterProvider cluster = session.getProvider(ClusterProvider.class);
|
||||||
cluster.registerListener(REALM_CLEAR_CACHE_EVENTS, (ClusterEvent event) -> {
|
cluster.registerListener(REALM_CLEAR_CACHE_EVENTS, (ClusterEvent event) -> {
|
||||||
if (event instanceof ClearCacheEvent) {
|
if (event instanceof ClearCacheEvent) {
|
||||||
sessionFactory.invalidate(ObjectType._ALL_);
|
sessionFactory.invalidate(null, ObjectType._ALL_);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
cluster.registerListener(REALM_INVALIDATION_EVENTS, (ClusterEvent event) -> {
|
cluster.registerListener(REALM_INVALIDATION_EVENTS, (ClusterEvent event) -> {
|
||||||
if (event instanceof RealmUpdatedEvent) {
|
if (event instanceof RealmUpdatedEvent) {
|
||||||
RealmUpdatedEvent rr = (RealmUpdatedEvent) event;
|
RealmUpdatedEvent rr = (RealmUpdatedEvent) event;
|
||||||
sessionFactory.invalidate(ObjectType.REALM, rr.getId());
|
sessionFactory.invalidate(null, ObjectType.REALM, rr.getId());
|
||||||
} else if (event instanceof RealmRemovedEvent) {
|
} else if (event instanceof RealmRemovedEvent) {
|
||||||
RealmRemovedEvent rr = (RealmRemovedEvent) event;
|
RealmRemovedEvent rr = (RealmRemovedEvent) event;
|
||||||
sessionFactory.invalidate(ObjectType.REALM, rr.getId());
|
sessionFactory.invalidate(null, ObjectType.REALM, rr.getId());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ package org.keycloak.models.map.authSession;
|
||||||
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
||||||
import org.keycloak.sessions.AuthenticationSessionProvider;
|
|
||||||
import org.keycloak.sessions.AuthenticationSessionProviderFactory;
|
import org.keycloak.sessions.AuthenticationSessionProviderFactory;
|
||||||
|
|
||||||
import org.keycloak.sessions.RootAuthenticationSessionModel;
|
import org.keycloak.sessions.RootAuthenticationSessionModel;
|
||||||
|
@ -26,15 +25,15 @@ import org.keycloak.sessions.RootAuthenticationSessionModel;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||||
*/
|
*/
|
||||||
public class MapRootAuthenticationSessionProviderFactory extends AbstractMapProviderFactory<AuthenticationSessionProvider, MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel>
|
public class MapRootAuthenticationSessionProviderFactory extends AbstractMapProviderFactory<MapRootAuthenticationSessionProvider, MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel>
|
||||||
implements AuthenticationSessionProviderFactory {
|
implements AuthenticationSessionProviderFactory<MapRootAuthenticationSessionProvider> {
|
||||||
|
|
||||||
public MapRootAuthenticationSessionProviderFactory() {
|
public MapRootAuthenticationSessionProviderFactory() {
|
||||||
super(RootAuthenticationSessionModel.class);
|
super(RootAuthenticationSessionModel.class, MapRootAuthenticationSessionProvider.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthenticationSessionProvider create(KeycloakSession session) {
|
public MapRootAuthenticationSessionProvider createNew(KeycloakSession session) {
|
||||||
return new MapRootAuthenticationSessionProvider(session, getStorage(session));
|
return new MapRootAuthenticationSessionProvider(session, getStorage(session));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,21 +17,8 @@
|
||||||
|
|
||||||
package org.keycloak.models.map.client;
|
package org.keycloak.models.map.client;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.models.ClientModel;
|
|
||||||
import org.keycloak.models.ClientModel.ClientUpdatedEvent;
|
|
||||||
import org.keycloak.models.ClientModel.SearchableFields;
|
|
||||||
import org.keycloak.models.ClientProvider;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.ModelDuplicateException;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.models.RoleModel;
|
|
||||||
|
|
||||||
import org.keycloak.models.map.common.TimeAdapter;
|
|
||||||
import org.keycloak.models.map.storage.MapKeycloakTransaction;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -41,18 +28,30 @@ import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.ClientModel.ClientUpdatedEvent;
|
||||||
|
import org.keycloak.models.ClientModel.SearchableFields;
|
||||||
|
import org.keycloak.models.ClientProvider;
|
||||||
|
import org.keycloak.models.ClientScopeModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.ModelDuplicateException;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.map.common.TimeAdapter;
|
||||||
|
import org.keycloak.models.map.storage.MapKeycloakTransaction;
|
||||||
|
import org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator;
|
||||||
import org.keycloak.models.map.storage.MapStorage;
|
import org.keycloak.models.map.storage.MapStorage;
|
||||||
|
import org.keycloak.models.map.storage.criteria.DefaultModelCriteria;
|
||||||
|
|
||||||
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
||||||
import org.keycloak.models.ClientScopeModel;
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.CLIENT_AFTER_REMOVE;
|
||||||
import org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator;
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.CLIENT_BEFORE_REMOVE;
|
||||||
import org.keycloak.models.map.storage.criteria.DefaultModelCriteria;
|
|
||||||
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
||||||
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
||||||
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;
|
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
public class MapClientProvider implements ClientProvider {
|
public class MapClientProvider implements ClientProvider {
|
||||||
|
|
||||||
private static final Logger LOG = Logger.getLogger(MapClientProvider.class);
|
private static final Logger LOG = Logger.getLogger(MapClientProvider.class);
|
||||||
|
@ -196,33 +195,19 @@ public class MapClientProvider implements ClientProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeClient(RealmModel realm, String id) {
|
public boolean removeClient(RealmModel realm, String id) {
|
||||||
if (id == null) {
|
if (id == null) return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.tracef("removeClient(%s, %s)%s", realm, id, getShortStackTrace());
|
LOG.tracef("removeClient(%s, %s)%s", realm, id, getShortStackTrace());
|
||||||
|
|
||||||
// TODO: Sending an event (and client role removal) should be extracted to store layer
|
|
||||||
final ClientModel client = getClientById(realm, id);
|
final ClientModel client = getClientById(realm, id);
|
||||||
if (client == null) return false;
|
if (client == null) return false;
|
||||||
session.users().preRemove(realm, client);
|
|
||||||
session.roles().removeRoles(client);
|
|
||||||
|
|
||||||
session.getKeycloakSessionFactory().publish(new ClientModel.ClientRemovedEvent() {
|
session.invalidate(CLIENT_BEFORE_REMOVE, realm, client);
|
||||||
@Override
|
|
||||||
public ClientModel getClient() {
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public KeycloakSession getKeycloakSession() {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// TODO: ^^^^^^^ Up to here
|
|
||||||
|
|
||||||
tx.delete(id);
|
tx.delete(id);
|
||||||
|
|
||||||
|
session.invalidate(CLIENT_AFTER_REMOVE, client);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,6 +359,14 @@ public class MapClientProvider implements ClientProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void preRemove(RealmModel realm) {
|
||||||
|
LOG.tracef("preRemove(%s)%s", realm, getShortStackTrace());
|
||||||
|
DefaultModelCriteria<ClientModel> mcb = criteria();
|
||||||
|
mcb = mcb.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId());
|
||||||
|
|
||||||
|
tx.delete(withCriteria(mcb));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
|
|
||||||
|
|
|
@ -16,72 +16,54 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.map.client;
|
package org.keycloak.models.map.client;
|
||||||
|
|
||||||
import org.keycloak.models.ClientModel;
|
|
||||||
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
|
||||||
import org.keycloak.models.ClientProvider;
|
|
||||||
import org.keycloak.models.ClientProviderFactory;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.models.RoleContainerModel;
|
|
||||||
import org.keycloak.models.RoleContainerModel.RoleRemovedEvent;
|
|
||||||
import org.keycloak.models.RoleModel;
|
|
||||||
import org.keycloak.provider.ProviderEvent;
|
|
||||||
import org.keycloak.provider.ProviderEventListener;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
||||||
|
import org.keycloak.models.ClientProviderFactory;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.provider.InvalidationHandler;
|
||||||
|
import org.keycloak.provider.InvalidationHandler.InvalidableObjectType;
|
||||||
|
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.CLIENT_AFTER_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.REALM_BEFORE_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.ROLE_BEFORE_REMOVE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author hmlnarik
|
* @author hmlnarik
|
||||||
*/
|
*/
|
||||||
public class MapClientProviderFactory extends AbstractMapProviderFactory<ClientProvider, MapClientEntity, ClientModel> implements ClientProviderFactory, ProviderEventListener {
|
public class MapClientProviderFactory extends AbstractMapProviderFactory<MapClientProvider, MapClientEntity, ClientModel> implements ClientProviderFactory<MapClientProvider>, InvalidationHandler {
|
||||||
|
|
||||||
private final ConcurrentHashMap<String, ConcurrentMap<String, Long>> REGISTERED_NODES_STORE = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, ConcurrentMap<String, Long>> REGISTERED_NODES_STORE = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private Runnable onClose;
|
|
||||||
|
|
||||||
public MapClientProviderFactory() {
|
public MapClientProviderFactory() {
|
||||||
super(ClientModel.class);
|
super(ClientModel.class, MapClientProvider.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postInit(KeycloakSessionFactory factory) {
|
public MapClientProvider createNew(KeycloakSession session) {
|
||||||
factory.register(this);
|
|
||||||
onClose = () -> factory.unregister(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MapClientProvider create(KeycloakSession session) {
|
|
||||||
return new MapClientProvider(session, getStorage(session), REGISTERED_NODES_STORE);
|
return new MapClientProvider(session, getStorage(session), REGISTERED_NODES_STORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
super.close();
|
|
||||||
onClose.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getHelpText() {
|
public String getHelpText() {
|
||||||
return "Client provider";
|
return "Client provider";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(ProviderEvent event) {
|
public void invalidate(KeycloakSession session, InvalidableObjectType type, Object... params) {
|
||||||
if (event instanceof RoleContainerModel.RoleRemovedEvent) {
|
if (type == REALM_BEFORE_REMOVE) {
|
||||||
RoleRemovedEvent e = (RoleContainerModel.RoleRemovedEvent) event;
|
create(session).preRemove((RealmModel) params[0]);
|
||||||
RoleModel role = e.getRole();
|
} else if (type == ROLE_BEFORE_REMOVE) {
|
||||||
RoleContainerModel container = role.getContainer();
|
create(session).preRemove((RealmModel) params[0], (RoleModel) params[1]);
|
||||||
RealmModel realm;
|
} else if (type == CLIENT_AFTER_REMOVE) {
|
||||||
if (container instanceof RealmModel) {
|
session.getKeycloakSessionFactory().publish(new ClientModel.ClientRemovedEvent() {
|
||||||
realm = (RealmModel) container;
|
@Override public ClientModel getClient() { return (ClientModel) params[0]; }
|
||||||
} else if (container instanceof ClientModel) {
|
@Override public KeycloakSession getKeycloakSession() { return session; }
|
||||||
realm = ((ClientModel) container).getRealm();
|
});
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
((MapClientProvider) e.getKeycloakSession().getProvider(ClientProvider.class)).preRemove(realm, role);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
|
||||||
import org.keycloak.models.ClientScopeModel.SearchableFields;
|
import org.keycloak.models.ClientScopeModel.SearchableFields;
|
||||||
import org.keycloak.models.ClientScopeModel;
|
import org.keycloak.models.ClientScopeModel;
|
||||||
import org.keycloak.models.ClientScopeProvider;
|
import org.keycloak.models.ClientScopeProvider;
|
||||||
|
@ -36,6 +35,9 @@ import org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator;
|
||||||
import org.keycloak.models.map.storage.criteria.DefaultModelCriteria;
|
import org.keycloak.models.map.storage.criteria.DefaultModelCriteria;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
|
||||||
|
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.CLIENT_SCOPE_AFTER_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.CLIENT_SCOPE_BEFORE_REMOVE;
|
||||||
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
||||||
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
||||||
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;
|
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;
|
||||||
|
@ -106,23 +108,12 @@ public class MapClientScopeProvider implements ClientScopeProvider {
|
||||||
ClientScopeModel clientScope = getClientScopeById(realm, id);
|
ClientScopeModel clientScope = getClientScopeById(realm, id);
|
||||||
if (clientScope == null) return false;
|
if (clientScope == null) return false;
|
||||||
|
|
||||||
session.users().preRemove(clientScope);
|
session.invalidate(CLIENT_SCOPE_BEFORE_REMOVE, realm, clientScope);
|
||||||
realm.removeDefaultClientScope(clientScope);
|
|
||||||
|
|
||||||
session.getKeycloakSessionFactory().publish(new ClientScopeModel.ClientScopeRemovedEvent() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public KeycloakSession getKeycloakSession() {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClientScopeModel getClientScope() {
|
|
||||||
return clientScope;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
tx.delete(id);
|
tx.delete(id);
|
||||||
|
|
||||||
|
session.invalidate(CLIENT_SCOPE_AFTER_REMOVE, clientScope);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,6 +141,14 @@ public class MapClientScopeProvider implements ClientScopeProvider {
|
||||||
: entityToAdapterFunc(realm).apply(entity);
|
: entityToAdapterFunc(realm).apply(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void preRemove(RealmModel realm) {
|
||||||
|
LOG.tracef("preRemove(%s)%s", realm, getShortStackTrace());
|
||||||
|
DefaultModelCriteria<ClientScopeModel> mcb = criteria();
|
||||||
|
mcb = mcb.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId());
|
||||||
|
|
||||||
|
tx.delete(withCriteria(mcb));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,19 +17,24 @@
|
||||||
package org.keycloak.models.map.clientscope;
|
package org.keycloak.models.map.clientscope;
|
||||||
|
|
||||||
import org.keycloak.models.ClientScopeModel;
|
import org.keycloak.models.ClientScopeModel;
|
||||||
import org.keycloak.models.ClientScopeProvider;
|
|
||||||
import org.keycloak.models.ClientScopeProviderFactory;
|
import org.keycloak.models.ClientScopeProviderFactory;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
||||||
|
import org.keycloak.provider.InvalidationHandler;
|
||||||
|
|
||||||
public class MapClientScopeProviderFactory extends AbstractMapProviderFactory<ClientScopeProvider, MapClientScopeEntity, ClientScopeModel> implements ClientScopeProviderFactory {
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.CLIENT_SCOPE_AFTER_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.CLIENT_SCOPE_BEFORE_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.REALM_BEFORE_REMOVE;
|
||||||
|
|
||||||
|
public class MapClientScopeProviderFactory extends AbstractMapProviderFactory<MapClientScopeProvider, MapClientScopeEntity, ClientScopeModel> implements ClientScopeProviderFactory<MapClientScopeProvider>, InvalidationHandler {
|
||||||
|
|
||||||
public MapClientScopeProviderFactory() {
|
public MapClientScopeProviderFactory() {
|
||||||
super(ClientScopeModel.class);
|
super(ClientScopeModel.class, MapClientScopeProvider.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientScopeProvider create(KeycloakSession session) {
|
public MapClientScopeProvider createNew(KeycloakSession session) {
|
||||||
return new MapClientScopeProvider(session, getStorage(session));
|
return new MapClientScopeProvider(session, getStorage(session));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,4 +42,18 @@ public class MapClientScopeProviderFactory extends AbstractMapProviderFactory<Cl
|
||||||
public String getHelpText() {
|
public String getHelpText() {
|
||||||
return "Client scope provider";
|
return "Client scope provider";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidate(KeycloakSession session, InvalidableObjectType type, Object... params) {
|
||||||
|
if (type == REALM_BEFORE_REMOVE) {
|
||||||
|
create(session).preRemove((RealmModel) params[0]);
|
||||||
|
} else if (type == CLIENT_SCOPE_BEFORE_REMOVE) {
|
||||||
|
((RealmModel) params[0]).removeDefaultClientScope((ClientScopeModel) params[1]);
|
||||||
|
} else if (type == CLIENT_SCOPE_AFTER_REMOVE) {
|
||||||
|
session.getKeycloakSessionFactory().publish(new ClientScopeModel.ClientScopeRemovedEvent() {
|
||||||
|
@Override public ClientScopeModel getClientScope() { return (ClientScopeModel) params[0]; }
|
||||||
|
@Override public KeycloakSession getKeycloakSession() { return session; }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.map.common;
|
package org.keycloak.models.map.common;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import org.keycloak.Config.Scope;
|
import org.keycloak.Config.Scope;
|
||||||
import org.keycloak.common.Profile;
|
import org.keycloak.common.Profile;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
@ -25,9 +26,11 @@ import org.keycloak.models.map.storage.MapStorageSpi;
|
||||||
import org.keycloak.component.AmphibianProviderFactory;
|
import org.keycloak.component.AmphibianProviderFactory;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||||
|
import org.keycloak.provider.InvalidationHandler;
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import static org.keycloak.models.utils.KeycloakModelUtils.getComponentFactory;
|
import static org.keycloak.models.utils.KeycloakModelUtils.getComponentFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,13 +45,59 @@ public abstract class AbstractMapProviderFactory<T extends Provider, V extends A
|
||||||
|
|
||||||
protected final Logger LOG = Logger.getLogger(getClass());
|
protected final Logger LOG = Logger.getLogger(getClass());
|
||||||
|
|
||||||
|
public static final AtomicInteger uniqueCounter = new AtomicInteger();
|
||||||
|
private final String uniqueKey = getClass().getName() + uniqueCounter.incrementAndGet();
|
||||||
|
|
||||||
protected final Class<M> modelType;
|
protected final Class<M> modelType;
|
||||||
|
private final Class<T> providerType;
|
||||||
|
|
||||||
private Scope storageConfigScope;
|
private Scope storageConfigScope;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
protected AbstractMapProviderFactory(Class<M> modelType, Class<T> providerType) {
|
||||||
protected AbstractMapProviderFactory(Class<M> modelType) {
|
|
||||||
this.modelType = modelType;
|
this.modelType = modelType;
|
||||||
|
this.providerType = providerType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MapProviderObjectType implements InvalidationHandler.InvalidableObjectType {
|
||||||
|
CLIENT_BEFORE_REMOVE,
|
||||||
|
CLIENT_AFTER_REMOVE,
|
||||||
|
CLIENT_SCOPE_BEFORE_REMOVE,
|
||||||
|
CLIENT_SCOPE_AFTER_REMOVE,
|
||||||
|
GROUP_BEFORE_REMOVE,
|
||||||
|
GROUP_AFTER_REMOVE,
|
||||||
|
REALM_BEFORE_REMOVE,
|
||||||
|
REALM_AFTER_REMOVE,
|
||||||
|
ROLE_BEFORE_REMOVE,
|
||||||
|
ROLE_AFTER_REMOVE,
|
||||||
|
USER_BEFORE_REMOVE,
|
||||||
|
USER_AFTER_REMOVE
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new instance of a provider.
|
||||||
|
*
|
||||||
|
* @param session
|
||||||
|
* @return See description.
|
||||||
|
*/
|
||||||
|
public abstract T createNew(KeycloakSession session);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns instance of a provider. If the instance is already created within
|
||||||
|
* the session (it's found in session attributes), it's returned from there,
|
||||||
|
* otherwise new instance is created (and stored among the session attributes).
|
||||||
|
*
|
||||||
|
* @param session
|
||||||
|
* @return See description.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public T create(KeycloakSession session) {
|
||||||
|
T provider = session.getAttribute(uniqueKey, providerType);
|
||||||
|
if (provider != null) {
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
provider = createNew(session);
|
||||||
|
session.setAttribute(uniqueKey, provider);
|
||||||
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -36,10 +36,11 @@ import org.keycloak.models.map.storage.criteria.DefaultModelCriteria;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.GROUP_AFTER_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.GROUP_BEFORE_REMOVE;
|
||||||
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
||||||
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
||||||
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;
|
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;
|
||||||
|
@ -214,34 +215,12 @@ public class MapGroupProvider implements GroupProvider {
|
||||||
LOG.tracef("removeGroup(%s, %s)%s", realm, group, getShortStackTrace());
|
LOG.tracef("removeGroup(%s, %s)%s", realm, group, getShortStackTrace());
|
||||||
if (group == null) return false;
|
if (group == null) return false;
|
||||||
|
|
||||||
// TODO: Sending an event (, user group removal and realm default groups) should be extracted to store layer
|
session.invalidate(GROUP_BEFORE_REMOVE, realm, group);
|
||||||
session.getKeycloakSessionFactory().publish(new GroupModel.GroupRemovedEvent() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RealmModel getRealm() {
|
|
||||||
return realm;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupModel getGroup() {
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public KeycloakSession getKeycloakSession() {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
session.users().preRemove(realm, group);
|
|
||||||
realm.removeDefaultGroup(group);
|
|
||||||
|
|
||||||
group.getSubGroupsStream().collect(Collectors.toSet()).forEach(subGroup -> session.groups().removeGroup(realm, subGroup));
|
|
||||||
|
|
||||||
// TODO: ^^^^^^^ Up to here
|
|
||||||
|
|
||||||
tx.delete(group.getId());
|
tx.delete(group.getId());
|
||||||
|
|
||||||
|
session.invalidate(GROUP_AFTER_REMOVE, realm, group);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,9 +285,16 @@ public class MapGroupProvider implements GroupProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void preRemove(RealmModel realm) {
|
||||||
|
LOG.tracef("preRemove(%s)%s", realm, getShortStackTrace());
|
||||||
|
DefaultModelCriteria<GroupModel> mcb = criteria();
|
||||||
|
mcb = mcb.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId());
|
||||||
|
|
||||||
|
tx.delete(withCriteria(mcb));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,70 +16,58 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.map.group;
|
package org.keycloak.models.map.group;
|
||||||
|
|
||||||
import org.keycloak.models.ClientModel;
|
import java.util.stream.Collectors;
|
||||||
import org.keycloak.models.GroupModel;
|
import org.keycloak.models.GroupModel;
|
||||||
import org.keycloak.models.GroupProvider;
|
|
||||||
import org.keycloak.models.GroupProviderFactory;
|
import org.keycloak.models.GroupProviderFactory;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleContainerModel;
|
|
||||||
import org.keycloak.models.RoleContainerModel.RoleRemovedEvent;
|
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
|
|
||||||
import org.keycloak.provider.ProviderEvent;
|
|
||||||
import org.keycloak.provider.ProviderEventListener;
|
|
||||||
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
||||||
|
import org.keycloak.provider.InvalidationHandler;
|
||||||
|
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.GROUP_AFTER_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.GROUP_BEFORE_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.REALM_BEFORE_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.ROLE_BEFORE_REMOVE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author mhajas
|
* @author mhajas
|
||||||
*/
|
*/
|
||||||
public class MapGroupProviderFactory extends AbstractMapProviderFactory<GroupProvider, MapGroupEntity, GroupModel> implements GroupProviderFactory, ProviderEventListener {
|
public class MapGroupProviderFactory extends AbstractMapProviderFactory<MapGroupProvider, MapGroupEntity, GroupModel> implements GroupProviderFactory<MapGroupProvider>, InvalidationHandler {
|
||||||
|
|
||||||
private Runnable onClose;
|
|
||||||
|
|
||||||
public MapGroupProviderFactory() {
|
public MapGroupProviderFactory() {
|
||||||
super(GroupModel.class);
|
super(GroupModel.class, MapGroupProvider.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postInit(KeycloakSessionFactory factory) {
|
public MapGroupProvider createNew(KeycloakSession session) {
|
||||||
factory.register(this);
|
|
||||||
onClose = () -> factory.unregister(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MapGroupProvider create(KeycloakSession session) {
|
|
||||||
return new MapGroupProvider(session, getStorage(session));
|
return new MapGroupProvider(session, getStorage(session));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
super.close();
|
|
||||||
onClose.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getHelpText() {
|
public String getHelpText() {
|
||||||
return "Group provider";
|
return "Group provider";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(ProviderEvent event) {
|
public void invalidate(KeycloakSession session, InvalidableObjectType type, Object... params) {
|
||||||
if (event instanceof RoleContainerModel.RoleRemovedEvent) {
|
if (type == REALM_BEFORE_REMOVE) {
|
||||||
RoleRemovedEvent e = (RoleContainerModel.RoleRemovedEvent) event;
|
create(session).preRemove((RealmModel) params[0]);
|
||||||
RoleModel role = e.getRole();
|
} else if (type == ROLE_BEFORE_REMOVE) {
|
||||||
RoleContainerModel container = role.getContainer();
|
create(session).preRemove((RealmModel) params[0], (RoleModel) params[1]);
|
||||||
RealmModel realm;
|
} else if (type == GROUP_BEFORE_REMOVE) {
|
||||||
if (container instanceof RealmModel) {
|
RealmModel realm = (RealmModel) params[0];
|
||||||
realm = (RealmModel) container;
|
GroupModel group = (GroupModel) params[1];
|
||||||
} else if (container instanceof ClientModel) {
|
|
||||||
realm = ((ClientModel) container).getRealm();
|
realm.removeDefaultGroup(group);
|
||||||
} else {
|
group.getSubGroupsStream().collect(Collectors.toSet()).forEach(subGroup -> create(session).removeGroup(realm, subGroup));
|
||||||
return;
|
} else if (type == GROUP_AFTER_REMOVE) {
|
||||||
}
|
session.getKeycloakSessionFactory().publish(new GroupModel.GroupRemovedEvent() {
|
||||||
((MapGroupProvider) e.getKeycloakSession().getProvider(GroupProvider.class)).preRemove(realm, role);
|
@Override public RealmModel getRealm() { return (RealmModel) params[0]; }
|
||||||
|
@Override public GroupModel getGroup() { return (GroupModel) params[1]; }
|
||||||
|
@Override public KeycloakSession getKeycloakSession() { return session; }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,43 +17,28 @@
|
||||||
package org.keycloak.models.map.loginFailure;
|
package org.keycloak.models.map.loginFailure;
|
||||||
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserLoginFailureProvider;
|
|
||||||
import org.keycloak.models.UserLoginFailureProviderFactory;
|
import org.keycloak.models.UserLoginFailureProviderFactory;
|
||||||
import org.keycloak.models.UserLoginFailureModel;
|
import org.keycloak.models.UserLoginFailureModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.map.common.AbstractEntity;
|
|
||||||
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
||||||
import org.keycloak.provider.ProviderEvent;
|
import org.keycloak.provider.InvalidationHandler;
|
||||||
import org.keycloak.provider.ProviderEventListener;
|
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.REALM_BEFORE_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.USER_BEFORE_REMOVE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||||
*/
|
*/
|
||||||
public class MapUserLoginFailureProviderFactory extends AbstractMapProviderFactory<UserLoginFailureProvider, MapUserLoginFailureEntity, UserLoginFailureModel>
|
public class MapUserLoginFailureProviderFactory extends AbstractMapProviderFactory<MapUserLoginFailureProvider, MapUserLoginFailureEntity, UserLoginFailureModel>
|
||||||
implements UserLoginFailureProviderFactory, ProviderEventListener {
|
implements UserLoginFailureProviderFactory<MapUserLoginFailureProvider>, InvalidationHandler {
|
||||||
|
|
||||||
private Runnable onClose;
|
|
||||||
|
|
||||||
public MapUserLoginFailureProviderFactory() {
|
public MapUserLoginFailureProviderFactory() {
|
||||||
super(UserLoginFailureModel.class);
|
super(UserLoginFailureModel.class, MapUserLoginFailureProvider.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postInit(KeycloakSessionFactory factory) {
|
public MapUserLoginFailureProvider createNew(KeycloakSession session) {
|
||||||
factory.register(this);
|
|
||||||
onClose = () -> factory.unregister(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
super.close();
|
|
||||||
onClose.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MapUserLoginFailureProvider create(KeycloakSession session) {
|
|
||||||
return new MapUserLoginFailureProvider(session, getStorage(session));
|
return new MapUserLoginFailureProvider(session, getStorage(session));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,17 +48,11 @@ public class MapUserLoginFailureProviderFactory extends AbstractMapProviderFacto
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(ProviderEvent event) {
|
public void invalidate(KeycloakSession session, InvalidableObjectType type, Object... params) {
|
||||||
if (event instanceof UserModel.UserRemovedEvent) {
|
if (type == REALM_BEFORE_REMOVE) {
|
||||||
UserModel.UserRemovedEvent userRemovedEvent = (UserModel.UserRemovedEvent) event;
|
create(session).removeAllUserLoginFailures((RealmModel) params[0]);
|
||||||
|
} else if (type == USER_BEFORE_REMOVE) {
|
||||||
MapUserLoginFailureProvider provider = MapUserLoginFailureProviderFactory.this.create(userRemovedEvent.getKeycloakSession());
|
create(session).removeUserLoginFailure((RealmModel) params[0], ((UserModel) params[1]).getId());
|
||||||
provider.removeUserLoginFailure(userRemovedEvent.getRealm(), userRemovedEvent.getUser().getId());
|
|
||||||
} else if (event instanceof RealmModel.RealmRemovedEvent) {
|
|
||||||
RealmModel.RealmRemovedEvent realmRemovedEvent = (RealmModel.RealmRemovedEvent) event;
|
|
||||||
|
|
||||||
MapUserLoginFailureProvider provider = MapUserLoginFailureProviderFactory.this.create(realmRemovedEvent.getKeycloakSession());
|
|
||||||
provider.removeAllUserLoginFailures(realmRemovedEvent.getRealm());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.ClientScopeModel;
|
import org.keycloak.models.ClientScopeModel;
|
||||||
import org.keycloak.models.GroupModel;
|
import org.keycloak.models.GroupModel;
|
||||||
|
@ -37,6 +36,10 @@ import org.keycloak.models.map.storage.MapStorage;
|
||||||
import org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator;
|
import org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator;
|
||||||
import org.keycloak.models.map.storage.criteria.DefaultModelCriteria;
|
import org.keycloak.models.map.storage.criteria.DefaultModelCriteria;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
|
||||||
|
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.REALM_AFTER_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.REALM_BEFORE_REMOVE;
|
||||||
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
||||||
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
||||||
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;
|
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;
|
||||||
|
@ -135,27 +138,12 @@ public class MapRealmProvider implements RealmProvider {
|
||||||
|
|
||||||
if (realm == null) return false;
|
if (realm == null) return false;
|
||||||
|
|
||||||
session.users().preRemove(realm);
|
session.invalidate(REALM_BEFORE_REMOVE, realm);
|
||||||
session.clients().removeClients(realm);
|
|
||||||
session.clientScopes().removeClientScopes(realm);
|
|
||||||
session.roles().removeRoles(realm);
|
|
||||||
realm.getTopLevelGroupsStream().forEach(realm::removeGroup);
|
|
||||||
|
|
||||||
// TODO: Sending an event should be extracted to store layer
|
|
||||||
session.getKeycloakSessionFactory().publish(new RealmModel.RealmRemovedEvent() {
|
|
||||||
@Override
|
|
||||||
public RealmModel getRealm() {
|
|
||||||
return realm;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public KeycloakSession getKeycloakSession() {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// TODO: ^^^^^^^ Up to here
|
|
||||||
|
|
||||||
tx.delete(id);
|
tx.delete(id);
|
||||||
|
|
||||||
|
session.invalidate(REALM_AFTER_REMOVE, realm);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,22 +19,34 @@ package org.keycloak.models.map.realm;
|
||||||
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RealmProvider;
|
|
||||||
import org.keycloak.models.RealmProviderFactory;
|
import org.keycloak.models.RealmProviderFactory;
|
||||||
|
import org.keycloak.provider.InvalidationHandler;
|
||||||
|
|
||||||
public class MapRealmProviderFactory extends AbstractMapProviderFactory<RealmProvider, MapRealmEntity, RealmModel> implements RealmProviderFactory {
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.REALM_AFTER_REMOVE;
|
||||||
|
|
||||||
|
public class MapRealmProviderFactory extends AbstractMapProviderFactory<MapRealmProvider, MapRealmEntity, RealmModel> implements RealmProviderFactory<MapRealmProvider>, InvalidationHandler {
|
||||||
|
|
||||||
public MapRealmProviderFactory() {
|
public MapRealmProviderFactory() {
|
||||||
super(RealmModel.class);
|
super(RealmModel.class, MapRealmProvider.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RealmProvider create(KeycloakSession session) {
|
public MapRealmProvider createNew(KeycloakSession session) {
|
||||||
return new MapRealmProvider(session, getStorage(session));
|
return new MapRealmProvider(session, getStorage(session));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getHelpText() {
|
public String getHelpText() {
|
||||||
return "Realm provider";
|
return "Realm provider";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidate(KeycloakSession session, InvalidableObjectType type, Object... params) {
|
||||||
|
if (type == REALM_AFTER_REMOVE) {
|
||||||
|
session.getKeycloakSessionFactory().publish(new RealmModel.RealmRemovedEvent() {
|
||||||
|
@Override public RealmModel getRealm() { return (RealmModel) params[0]; }
|
||||||
|
@Override public KeycloakSession getKeycloakSession() { return session; }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,30 +17,29 @@
|
||||||
|
|
||||||
package org.keycloak.models.map.role;
|
package org.keycloak.models.map.role;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
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.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.map.storage.MapKeycloakTransaction;
|
import org.keycloak.models.map.storage.MapKeycloakTransaction;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import org.keycloak.models.map.storage.MapStorage;
|
import org.keycloak.models.map.storage.MapStorage;
|
||||||
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
|
||||||
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
|
||||||
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
|
||||||
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;
|
|
||||||
|
|
||||||
import org.keycloak.models.RoleContainerModel;
|
|
||||||
import org.keycloak.models.RoleModel.SearchableFields;
|
import org.keycloak.models.RoleModel.SearchableFields;
|
||||||
import org.keycloak.models.RoleProvider;
|
import org.keycloak.models.RoleProvider;
|
||||||
import org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator;
|
import org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator;
|
||||||
import org.keycloak.models.map.storage.criteria.DefaultModelCriteria;
|
import org.keycloak.models.map.storage.criteria.DefaultModelCriteria;
|
||||||
|
|
||||||
|
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.ROLE_AFTER_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.ROLE_BEFORE_REMOVE;
|
||||||
|
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
||||||
|
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
||||||
|
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;
|
||||||
|
|
||||||
public class MapRoleProvider implements RoleProvider {
|
public class MapRoleProvider implements RoleProvider {
|
||||||
|
|
||||||
private static final Logger LOG = Logger.getLogger(MapRoleProvider.class);
|
private static final Logger LOG = Logger.getLogger(MapRoleProvider.class);
|
||||||
|
@ -161,24 +160,12 @@ public class MapRoleProvider implements RoleProvider {
|
||||||
|
|
||||||
RealmModel realm = role.isClientRole() ? ((ClientModel)role.getContainer()).getRealm() : (RealmModel)role.getContainer();
|
RealmModel realm = role.isClientRole() ? ((ClientModel)role.getContainer()).getRealm() : (RealmModel)role.getContainer();
|
||||||
|
|
||||||
session.users().preRemove(realm, role);
|
session.invalidate(ROLE_BEFORE_REMOVE, realm, role);
|
||||||
|
|
||||||
// TODO: Sending an event should be extracted to store layer
|
|
||||||
session.getKeycloakSessionFactory().publish(new RoleContainerModel.RoleRemovedEvent() {
|
|
||||||
@Override
|
|
||||||
public RoleModel getRole() {
|
|
||||||
return role;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public KeycloakSession getKeycloakSession() {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// TODO: ^^^^^^^ Up to here
|
|
||||||
|
|
||||||
tx.delete(role.getId());
|
tx.delete(role.getId());
|
||||||
|
|
||||||
|
session.invalidate(ROLE_AFTER_REMOVE, realm, role);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,6 +271,14 @@ public class MapRoleProvider implements RoleProvider {
|
||||||
.map(entityToAdapterFunc(client.getRealm()));
|
.map(entityToAdapterFunc(client.getRealm()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void preRemove(RealmModel realm) {
|
||||||
|
LOG.tracef("preRemove(%s)%s", realm, getShortStackTrace());
|
||||||
|
DefaultModelCriteria<RoleModel> mcb = criteria();
|
||||||
|
mcb = mcb.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId());
|
||||||
|
|
||||||
|
tx.delete(withCriteria(mcb));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,20 +16,27 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.map.role;
|
package org.keycloak.models.map.role;
|
||||||
|
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleContainerModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.RoleProvider;
|
|
||||||
import org.keycloak.models.RoleProviderFactory;
|
import org.keycloak.models.RoleProviderFactory;
|
||||||
|
import org.keycloak.provider.InvalidationHandler;
|
||||||
|
|
||||||
public class MapRoleProviderFactory extends AbstractMapProviderFactory<RoleProvider, MapRoleEntity, RoleModel> implements RoleProviderFactory {
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.CLIENT_BEFORE_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.REALM_BEFORE_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.ROLE_AFTER_REMOVE;
|
||||||
|
|
||||||
|
public class MapRoleProviderFactory extends AbstractMapProviderFactory<MapRoleProvider, MapRoleEntity, RoleModel> implements RoleProviderFactory<MapRoleProvider>, InvalidationHandler {
|
||||||
|
|
||||||
public MapRoleProviderFactory() {
|
public MapRoleProviderFactory() {
|
||||||
super(RoleModel.class);
|
super(RoleModel.class, MapRoleProvider.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RoleProvider create(KeycloakSession session) {
|
public MapRoleProvider createNew(KeycloakSession session) {
|
||||||
return new MapRoleProvider(session, getStorage(session));
|
return new MapRoleProvider(session, getStorage(session));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,4 +44,18 @@ public class MapRoleProviderFactory extends AbstractMapProviderFactory<RoleProvi
|
||||||
public String getHelpText() {
|
public String getHelpText() {
|
||||||
return "Role provider";
|
return "Role provider";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidate(KeycloakSession session, InvalidableObjectType type, Object... params) {
|
||||||
|
if (type == REALM_BEFORE_REMOVE) {
|
||||||
|
create(session).preRemove((RealmModel) params[0]);
|
||||||
|
} else if (type == CLIENT_BEFORE_REMOVE) {
|
||||||
|
create(session).removeRoles((ClientModel) params[1]);
|
||||||
|
} else if (type == ROLE_AFTER_REMOVE) {
|
||||||
|
session.getKeycloakSessionFactory().publish(new RoleContainerModel.RoleRemovedEvent() {
|
||||||
|
@Override public RoleModel getRole() { return (RoleModel) params[1]; }
|
||||||
|
@Override public KeycloakSession getKeycloakSession() { return session; }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,8 @@ import static org.keycloak.models.UserModel.EMAIL_VERIFIED;
|
||||||
import static org.keycloak.models.UserModel.FIRST_NAME;
|
import static org.keycloak.models.UserModel.FIRST_NAME;
|
||||||
import static org.keycloak.models.UserModel.LAST_NAME;
|
import static org.keycloak.models.UserModel.LAST_NAME;
|
||||||
import static org.keycloak.models.UserModel.USERNAME;
|
import static org.keycloak.models.UserModel.USERNAME;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.USER_AFTER_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.USER_BEFORE_REMOVE;
|
||||||
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
||||||
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
||||||
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;
|
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;
|
||||||
|
@ -727,7 +729,11 @@ public class MapUserProvider implements UserProvider.Streams, UserCredentialStor
|
||||||
String userId = user.getId();
|
String userId = user.getId();
|
||||||
Optional<MapUserEntity> userById = getEntityById(realm, userId);
|
Optional<MapUserEntity> userById = getEntityById(realm, userId);
|
||||||
if (userById.isPresent()) {
|
if (userById.isPresent()) {
|
||||||
|
session.invalidate(USER_BEFORE_REMOVE, realm, user);
|
||||||
|
|
||||||
tx.delete(userId);
|
tx.delete(userId);
|
||||||
|
|
||||||
|
session.invalidate(USER_AFTER_REMOVE, realm, user);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,24 +17,35 @@
|
||||||
|
|
||||||
package org.keycloak.models.map.user;
|
package org.keycloak.models.map.user;
|
||||||
|
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.ClientScopeModel;
|
||||||
|
import org.keycloak.models.GroupModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserProvider;
|
|
||||||
import org.keycloak.models.UserProviderFactory;
|
import org.keycloak.models.UserProviderFactory;
|
||||||
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
||||||
|
import org.keycloak.provider.InvalidationHandler;
|
||||||
|
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.CLIENT_BEFORE_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.CLIENT_SCOPE_BEFORE_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.GROUP_BEFORE_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.REALM_BEFORE_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.ROLE_BEFORE_REMOVE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author mhajas
|
* @author mhajas
|
||||||
*/
|
*/
|
||||||
public class MapUserProviderFactory extends AbstractMapProviderFactory<UserProvider, MapUserEntity, UserModel> implements UserProviderFactory {
|
public class MapUserProviderFactory extends AbstractMapProviderFactory<MapUserProvider, MapUserEntity, UserModel> implements UserProviderFactory<MapUserProvider>, InvalidationHandler {
|
||||||
|
|
||||||
public MapUserProviderFactory() {
|
public MapUserProviderFactory() {
|
||||||
super(UserModel.class);
|
super(UserModel.class, MapUserProvider.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserProvider create(KeycloakSession session) {
|
public MapUserProvider createNew(KeycloakSession session) {
|
||||||
return new MapUserProvider(session, getStorage(session));
|
return new MapUserProvider(session, getStorage(session));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,4 +54,18 @@ public class MapUserProviderFactory extends AbstractMapProviderFactory<UserProvi
|
||||||
return "User provider";
|
return "User provider";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidate(KeycloakSession session, InvalidableObjectType type, Object... params) {
|
||||||
|
if (type == REALM_BEFORE_REMOVE) {
|
||||||
|
create(session).preRemove((RealmModel) params[0]);
|
||||||
|
} else if (type == ROLE_BEFORE_REMOVE) {
|
||||||
|
create(session).preRemove((RealmModel) params[0], (RoleModel) params[1]);
|
||||||
|
} else if (type == CLIENT_SCOPE_BEFORE_REMOVE) {
|
||||||
|
create(session).preRemove((ClientScopeModel) params[1]);
|
||||||
|
} else if (type == CLIENT_BEFORE_REMOVE) {
|
||||||
|
create(session).preRemove((RealmModel) params[0], (ClientModel) params[1]);
|
||||||
|
} else if (type == GROUP_BEFORE_REMOVE) {
|
||||||
|
create(session).preRemove((RealmModel) params[0], (GroupModel) params[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.keycloak.component.AmphibianProviderFactory;
|
||||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||||
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.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.models.UserSessionProvider;
|
import org.keycloak.models.UserSessionProvider;
|
||||||
|
@ -30,27 +31,28 @@ import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
||||||
import org.keycloak.models.map.storage.MapStorage;
|
import org.keycloak.models.map.storage.MapStorage;
|
||||||
import org.keycloak.models.map.storage.MapStorageProvider;
|
import org.keycloak.models.map.storage.MapStorageProvider;
|
||||||
import org.keycloak.models.map.storage.MapStorageProviderFactory;
|
import org.keycloak.models.map.storage.MapStorageProviderFactory;
|
||||||
|
|
||||||
import org.keycloak.models.map.storage.MapStorageSpi;
|
import org.keycloak.models.map.storage.MapStorageSpi;
|
||||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||||
import org.keycloak.provider.ProviderEvent;
|
import org.keycloak.provider.InvalidationHandler;
|
||||||
import org.keycloak.provider.ProviderEventListener;
|
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.USER_BEFORE_REMOVE;
|
||||||
|
import static org.keycloak.models.map.common.AbstractMapProviderFactory.uniqueCounter;
|
||||||
import static org.keycloak.models.utils.KeycloakModelUtils.getComponentFactory;
|
import static org.keycloak.models.utils.KeycloakModelUtils.getComponentFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||||
*/
|
*/
|
||||||
public class MapUserSessionProviderFactory<UK, CK> implements AmphibianProviderFactory<UserSessionProvider>, UserSessionProviderFactory, ProviderEventListener, EnvironmentDependentProviderFactory {
|
public class MapUserSessionProviderFactory<UK, CK> implements AmphibianProviderFactory<UserSessionProvider>, UserSessionProviderFactory, EnvironmentDependentProviderFactory, InvalidationHandler {
|
||||||
|
|
||||||
public static final String CONFIG_STORAGE_USER_SESSIONS = "storage-user-sessions";
|
public static final String CONFIG_STORAGE_USER_SESSIONS = "storage-user-sessions";
|
||||||
public static final String CONFIG_STORAGE_CLIENT_SESSIONS = "storage-client-sessions";
|
public static final String CONFIG_STORAGE_CLIENT_SESSIONS = "storage-client-sessions";
|
||||||
public static final String PROVIDER_ID = AbstractMapProviderFactory.PROVIDER_ID;
|
public static final String PROVIDER_ID = AbstractMapProviderFactory.PROVIDER_ID;
|
||||||
|
|
||||||
|
private final String uniqueKey = getClass().getName() + uniqueCounter.incrementAndGet();
|
||||||
|
|
||||||
private Scope storageConfigScopeUserSessions;
|
private Scope storageConfigScopeUserSessions;
|
||||||
private Scope storageConfigScopeClientSessions;
|
private Scope storageConfigScopeClientSessions;
|
||||||
|
|
||||||
private Runnable onClose;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return PROVIDER_ID;
|
return PROVIDER_ID;
|
||||||
|
@ -64,14 +66,11 @@ public class MapUserSessionProviderFactory<UK, CK> implements AmphibianProviderF
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postInit(KeycloakSessionFactory factory) {
|
public void postInit(KeycloakSessionFactory factory) {
|
||||||
factory.register(this);
|
|
||||||
onClose = () -> factory.unregister(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
AmphibianProviderFactory.super.close();
|
AmphibianProviderFactory.super.close();
|
||||||
onClose.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -79,7 +78,12 @@ public class MapUserSessionProviderFactory<UK, CK> implements AmphibianProviderF
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public MapUserSessionProvider create(KeycloakSession session) {
|
public MapUserSessionProvider create(KeycloakSession session) {
|
||||||
|
MapUserSessionProvider provider = session.getAttribute(uniqueKey, MapUserSessionProvider.class);
|
||||||
|
|
||||||
|
if (provider != null) return provider;
|
||||||
|
|
||||||
MapStorageProviderFactory storageProviderFactoryUs = (MapStorageProviderFactory) getComponentFactory(session.getKeycloakSessionFactory(),
|
MapStorageProviderFactory storageProviderFactoryUs = (MapStorageProviderFactory) getComponentFactory(session.getKeycloakSessionFactory(),
|
||||||
MapStorageProvider.class, storageConfigScopeUserSessions, MapStorageSpi.NAME);
|
MapStorageProvider.class, storageConfigScopeUserSessions, MapStorageSpi.NAME);
|
||||||
final MapStorageProvider factoryUs = storageProviderFactoryUs.create(session);
|
final MapStorageProvider factoryUs = storageProviderFactoryUs.create(session);
|
||||||
|
@ -90,7 +94,9 @@ public class MapUserSessionProviderFactory<UK, CK> implements AmphibianProviderF
|
||||||
final MapStorageProvider factoryCs = storageProviderFactoryCs.create(session);
|
final MapStorageProvider factoryCs = storageProviderFactoryCs.create(session);
|
||||||
MapStorage clientSessionStore = factoryCs.getStorage(AuthenticatedClientSessionModel.class);
|
MapStorage clientSessionStore = factoryCs.getStorage(AuthenticatedClientSessionModel.class);
|
||||||
|
|
||||||
return new MapUserSessionProvider(session, userSessionStore, clientSessionStore);
|
provider = new MapUserSessionProvider(session, userSessionStore, clientSessionStore);
|
||||||
|
session.setAttribute(uniqueKey, provider);
|
||||||
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -99,12 +105,9 @@ public class MapUserSessionProviderFactory<UK, CK> implements AmphibianProviderF
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(ProviderEvent event) {
|
public void invalidate(KeycloakSession session, InvalidableObjectType type, Object... params) {
|
||||||
if (event instanceof UserModel.UserRemovedEvent) {
|
if (type == USER_BEFORE_REMOVE) {
|
||||||
UserModel.UserRemovedEvent userRemovedEvent = (UserModel.UserRemovedEvent) event;
|
create(session).removeUserSessions((RealmModel) params[0], (UserModel) params[1]);
|
||||||
|
|
||||||
MapUserSessionProvider provider = MapUserSessionProviderFactory.this.create(userRemovedEvent.getKeycloakSession());
|
|
||||||
provider.removeUserSessions(userRemovedEvent.getRealm(), userRemovedEvent.getUser());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,5 +19,5 @@ package org.keycloak.models;
|
||||||
|
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
|
||||||
public interface ClientProviderFactory extends ProviderFactory<ClientProvider> {
|
public interface ClientProviderFactory<T extends ClientProvider> extends ProviderFactory<T> {
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,5 +19,5 @@ package org.keycloak.models;
|
||||||
|
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
|
||||||
public interface ClientScopeProviderFactory extends ProviderFactory<ClientScopeProvider> {
|
public interface ClientScopeProviderFactory<T extends ClientScopeProvider> extends ProviderFactory<T> {
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,5 +19,5 @@ package org.keycloak.models;
|
||||||
|
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
|
||||||
public interface GroupProviderFactory extends ProviderFactory<GroupProvider> {
|
public interface GroupProviderFactory<T extends GroupProvider> extends ProviderFactory<T> {
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,5 +23,5 @@ import org.keycloak.provider.ProviderFactory;
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public interface RealmProviderFactory extends ProviderFactory<RealmProvider> {
|
public interface RealmProviderFactory<T extends RealmProvider> extends ProviderFactory<T> {
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,5 +19,5 @@ package org.keycloak.models;
|
||||||
|
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
|
||||||
public interface RoleProviderFactory extends ProviderFactory<RoleProvider> {
|
public interface RoleProviderFactory<T extends RoleProvider> extends ProviderFactory<T> {
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,6 @@ import org.keycloak.provider.ProviderFactory;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||||
*/
|
*/
|
||||||
public interface UserLoginFailureProviderFactory extends ProviderFactory<UserLoginFailureProvider> {
|
public interface UserLoginFailureProviderFactory<T extends UserLoginFailureProvider> extends ProviderFactory<T> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,5 +23,5 @@ import org.keycloak.provider.ProviderFactory;
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public interface UserProviderFactory extends ProviderFactory<UserProvider> {
|
public interface UserProviderFactory<T extends UserProvider> extends ProviderFactory<T> {
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,5 +22,5 @@ import org.keycloak.provider.ProviderFactory;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
public interface AuthenticationSessionProviderFactory extends ProviderFactory<AuthenticationSessionProvider> {
|
public interface AuthenticationSessionProviderFactory<T extends AuthenticationSessionProvider> extends ProviderFactory<T> {
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.keycloak.models;
|
||||||
|
|
||||||
import org.keycloak.component.ComponentModel;
|
import org.keycloak.component.ComponentModel;
|
||||||
import org.keycloak.models.cache.UserCache;
|
import org.keycloak.models.cache.UserCache;
|
||||||
import org.keycloak.provider.InvalidationHandler;
|
import org.keycloak.provider.InvalidationHandler.InvalidableObjectType;
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
import org.keycloak.services.clientpolicy.ClientPolicyManager;
|
import org.keycloak.services.clientpolicy.ClientPolicyManager;
|
||||||
import org.keycloak.sessions.AuthenticationSessionProvider;
|
import org.keycloak.sessions.AuthenticationSessionProvider;
|
||||||
|
@ -33,7 +33,7 @@ import java.util.function.Function;
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public interface KeycloakSession extends InvalidationHandler {
|
public interface KeycloakSession {
|
||||||
|
|
||||||
KeycloakContext getContext();
|
KeycloakContext getContext();
|
||||||
|
|
||||||
|
@ -128,10 +128,9 @@ public interface KeycloakSession extends InvalidationHandler {
|
||||||
/**
|
/**
|
||||||
* Invalidates intermediate states of the given objects, both immediately and at the end of this session.
|
* Invalidates intermediate states of the given objects, both immediately and at the end of this session.
|
||||||
* @param type Type of the objects to invalidate
|
* @param type Type of the objects to invalidate
|
||||||
* @param ids Identifiers of the invalidated objects
|
* @param params Parameters used for the invalidation
|
||||||
*/
|
*/
|
||||||
@Override
|
void invalidate(InvalidableObjectType type, Object... params);
|
||||||
void invalidate(InvalidableObjectType type, Object... ids);
|
|
||||||
|
|
||||||
void enlistForClose(Provider provider);
|
void enlistForClose(Provider provider);
|
||||||
|
|
||||||
|
|
|
@ -29,11 +29,9 @@ import org.keycloak.storage.client.ClientStorageProvider;
|
||||||
import org.keycloak.storage.client.ClientStorageProviderModel;
|
import org.keycloak.storage.client.ClientStorageProviderModel;
|
||||||
import org.keycloak.storage.role.RoleStorageProvider;
|
import org.keycloak.storage.role.RoleStorageProvider;
|
||||||
import org.keycloak.storage.role.RoleStorageProviderModel;
|
import org.keycloak.storage.role.RoleStorageProviderModel;
|
||||||
import org.keycloak.utils.StringUtil;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.provider;
|
package org.keycloak.provider;
|
||||||
|
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles invalidation requests. This interface is specifically implemented by
|
* Handles invalidation requests. This interface is specifically implemented by
|
||||||
* providers that implement a cache of objects that might change in the outside.
|
* providers that implement a cache of objects that might change in the outside.
|
||||||
|
@ -40,9 +42,10 @@ public interface InvalidationHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalidates intermediate states of the given objects
|
* Invalidates intermediate states of the given objects
|
||||||
|
* @param session KeycloakSession
|
||||||
* @param type Type of the objects to invalidate
|
* @param type Type of the objects to invalidate
|
||||||
* @param ids Identifiers of the invalidated objects
|
* @param params Parameters used for the invalidation
|
||||||
*/
|
*/
|
||||||
void invalidate(InvalidableObjectType type, Object... ids);
|
void invalidate(KeycloakSession session, InvalidableObjectType type, Object... params);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.keycloak.common.util.StackUtil;
|
||||||
import org.keycloak.component.ComponentFactoryProviderFactory;
|
import org.keycloak.component.ComponentFactoryProviderFactory;
|
||||||
import org.keycloak.component.ComponentModel;
|
import org.keycloak.component.ComponentModel;
|
||||||
import org.keycloak.component.ComponentModelScope;
|
import org.keycloak.component.ComponentModelScope;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
import org.keycloak.provider.InvalidationHandler;
|
import org.keycloak.provider.InvalidationHandler;
|
||||||
|
@ -155,7 +156,7 @@ public class DefaultComponentFactoryProviderFactory implements ComponentFactoryP
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invalidate(InvalidableObjectType type, Object... ids) {
|
public void invalidate(KeycloakSession session, InvalidableObjectType type, Object... ids) {
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
LOG.debugf("Invalidating %s: %s", type, Arrays.asList(ids));
|
LOG.debugf("Invalidating %s: %s", type, Arrays.asList(ids));
|
||||||
}
|
}
|
||||||
|
@ -169,25 +170,25 @@ public class DefaultComponentFactoryProviderFactory implements ComponentFactoryP
|
||||||
Stream.of(ids)
|
Stream.of(ids)
|
||||||
.map(componentsMap.get()::remove).filter(Objects::nonNull)
|
.map(componentsMap.get()::remove).filter(Objects::nonNull)
|
||||||
.forEach(ProviderFactory::close);
|
.forEach(ProviderFactory::close);
|
||||||
propagateInvalidation(componentsMap.get(), type, ids);
|
propagateInvalidation(session, componentsMap.get(), type, ids);
|
||||||
} else if (type == ObjectType.REALM || type == ObjectType.PROVIDER_FACTORY) {
|
} else if (type == ObjectType.REALM || type == ObjectType.PROVIDER_FACTORY) {
|
||||||
Stream.of(ids)
|
Stream.of(ids)
|
||||||
.map(dependentInvalidations::get).filter(Objects::nonNull).flatMap(Collection::stream)
|
.map(dependentInvalidations::get).filter(Objects::nonNull).flatMap(Collection::stream)
|
||||||
.map(componentsMap.get()::remove).filter(Objects::nonNull)
|
.map(componentsMap.get()::remove).filter(Objects::nonNull)
|
||||||
.forEach(ProviderFactory::close);
|
.forEach(ProviderFactory::close);
|
||||||
Stream.of(ids).forEach(dependentInvalidations::remove);
|
Stream.of(ids).forEach(dependentInvalidations::remove);
|
||||||
propagateInvalidation(componentsMap.get(), type, ids);
|
propagateInvalidation(session, componentsMap.get(), type, ids);
|
||||||
} else {
|
} else {
|
||||||
propagateInvalidation(componentsMap.get(), type, ids);
|
propagateInvalidation(session, componentsMap.get(), type, ids);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void propagateInvalidation(ConcurrentMap<String, ProviderFactory> componentsMap, InvalidableObjectType type, Object[] ids) {
|
private void propagateInvalidation(KeycloakSession session, ConcurrentMap<String, ProviderFactory> componentsMap, InvalidableObjectType type, Object[] ids) {
|
||||||
componentsMap.values()
|
componentsMap.values()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(InvalidationHandler.class::isInstance)
|
.filter(InvalidationHandler.class::isInstance)
|
||||||
.map(InvalidationHandler.class::cast)
|
.map(InvalidationHandler.class::cast)
|
||||||
.forEach(ih -> ih.invalidate(type, ids));
|
.forEach(ih -> ih.invalidate(session, type, ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -41,10 +41,11 @@ import org.keycloak.models.UserSessionProvider;
|
||||||
import org.keycloak.models.cache.CacheRealmProvider;
|
import org.keycloak.models.cache.CacheRealmProvider;
|
||||||
import org.keycloak.models.cache.UserCache;
|
import org.keycloak.models.cache.UserCache;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
import org.keycloak.provider.InvalidationHandler.InvalidableObjectType;
|
||||||
|
import org.keycloak.provider.InvalidationHandler.ObjectType;
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
import org.keycloak.services.clientpolicy.ClientPolicyManager;
|
import org.keycloak.services.clientpolicy.ClientPolicyManager;
|
||||||
import org.keycloak.services.clientpolicy.DefaultClientPolicyManager;
|
|
||||||
import org.keycloak.sessions.AuthenticationSessionProvider;
|
import org.keycloak.sessions.AuthenticationSessionProvider;
|
||||||
import org.keycloak.storage.ClientStorageManager;
|
import org.keycloak.storage.ClientStorageManager;
|
||||||
import org.keycloak.storage.ClientScopeStorageManager;
|
import org.keycloak.storage.ClientScopeStorageManager;
|
||||||
|
@ -169,8 +170,10 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invalidate(InvalidableObjectType type, Object... ids) {
|
public void invalidate(InvalidableObjectType type, Object... ids) {
|
||||||
factory.invalidate(type, ids);
|
factory.invalidate(this, type, ids);
|
||||||
invalidationMap.computeIfAbsent(type, o -> new HashSet<>()).addAll(Arrays.asList(ids));
|
if (type == ObjectType.PROVIDER_FACTORY) {
|
||||||
|
invalidationMap.computeIfAbsent(type, o -> new HashSet<>()).addAll(Arrays.asList(ids));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -524,7 +527,7 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
||||||
providers.values().forEach(safeClose);
|
providers.values().forEach(safeClose);
|
||||||
closable.forEach(safeClose);
|
closable.forEach(safeClose);
|
||||||
for (Entry<InvalidableObjectType, Set<Object>> me : invalidationMap.entrySet()) {
|
for (Entry<InvalidableObjectType, Set<Object>> me : invalidationMap.entrySet()) {
|
||||||
factory.invalidate(me.getKey(), me.getValue().toArray());
|
factory.invalidate(this, me.getKey(), me.getValue().toArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,7 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
|
||||||
checkProvider();
|
checkProvider();
|
||||||
boolean cfChanged = false;
|
boolean cfChanged = false;
|
||||||
for (ProviderFactory factory : undeployed) {
|
for (ProviderFactory factory : undeployed) {
|
||||||
invalidate(ObjectType.PROVIDER_FACTORY, factory.getClass());
|
invalidate(null, ObjectType.PROVIDER_FACTORY, factory.getClass());
|
||||||
factory.close();
|
factory.close();
|
||||||
cfChanged |= (componentFactoryPF == factory);
|
cfChanged |= (componentFactoryPF == factory);
|
||||||
}
|
}
|
||||||
|
@ -359,13 +359,13 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invalidate(InvalidableObjectType type, Object... ids) {
|
public void invalidate(KeycloakSession session, InvalidableObjectType type, Object... ids) {
|
||||||
factoriesMap.values().stream()
|
factoriesMap.values().stream()
|
||||||
.map(Map::values)
|
.map(Map::values)
|
||||||
.flatMap(Collection::stream)
|
.flatMap(Collection::stream)
|
||||||
.filter(InvalidationHandler.class::isInstance)
|
.filter(InvalidationHandler.class::isInstance)
|
||||||
.map(InvalidationHandler.class::cast)
|
.map(InvalidationHandler.class::cast)
|
||||||
.forEach(ih -> ih.invalidate(type, ids));
|
.forEach(ih -> ih.invalidate(session, type, ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.keycloak.admin.client.resource.UsersResource;
|
||||||
import org.keycloak.common.Profile;
|
import org.keycloak.common.Profile;
|
||||||
import org.keycloak.common.util.KeycloakUriBuilder;
|
import org.keycloak.common.util.KeycloakUriBuilder;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
|
import org.keycloak.models.RealmProvider;
|
||||||
import org.keycloak.models.cache.CacheRealmProvider;
|
import org.keycloak.models.cache.CacheRealmProvider;
|
||||||
import org.keycloak.models.cache.UserCache;
|
import org.keycloak.models.cache.UserCache;
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
|
@ -720,6 +721,25 @@ public abstract class AbstractKeycloakTest {
|
||||||
return isProduct ? Profile.PRODUCT_NAME : Profile.PROJECT_NAME;
|
return isProduct ? Profile.PRODUCT_NAME : Profile.PROJECT_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MapRealmProvider uses session.invalidate() instead of calling e.g.
|
||||||
|
* session.clients().removeClients(realm); for clients (where clients are being removed one by one)
|
||||||
|
*
|
||||||
|
* Therefore it doesn't call session.users().preRemove(realm, client) for each client.
|
||||||
|
* Due to that JpaUserFederatedStorageProvider.preRemove(realm, client) is not called.
|
||||||
|
* So there remains objects in the database in user federation related tables after realm removal.
|
||||||
|
*
|
||||||
|
* Same for roles etc.
|
||||||
|
*
|
||||||
|
* Legacy federated storage is NOT supposed to work with map storage, so this method
|
||||||
|
* returns true if realm provider is "jpa" to be able to skip particular tests.
|
||||||
|
*/
|
||||||
|
protected boolean isJpaRealmProvider() {
|
||||||
|
String realmProvider = testingClient.server()
|
||||||
|
.fetchString(s -> s.getKeycloakSessionFactory().getProviderFactory(RealmProvider.class).getId());
|
||||||
|
return Objects.equals(realmProvider, "\"jpa\"");
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean isRealmCacheEnabled() {
|
protected boolean isRealmCacheEnabled() {
|
||||||
String realmCache = testingClient.server()
|
String realmCache = testingClient.server()
|
||||||
.fetchString(s -> s.getKeycloakSessionFactory().getProviderFactory(CacheRealmProvider.class));
|
.fetchString(s -> s.getKeycloakSessionFactory().getProviderFactory(CacheRealmProvider.class));
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.keycloak.testsuite.federation.storage;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import org.junit.Assume;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.admin.client.resource.RealmResource;
|
import org.keycloak.admin.client.resource.RealmResource;
|
||||||
|
@ -42,7 +43,6 @@ import javax.ws.rs.NotFoundException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
|
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
|
||||||
|
@ -61,6 +61,8 @@ public class FederatedStorageExportImportTest extends AbstractAuthTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setDirs() {
|
public void setDirs() {
|
||||||
|
Assume.assumeTrue("RealmProvider is not 'jpa'", isJpaRealmProvider());
|
||||||
|
|
||||||
File baseDir = new File(System.getProperty("auth.server.config.dir", "target"));
|
File baseDir = new File(System.getProperty("auth.server.config.dir", "target"));
|
||||||
|
|
||||||
exportFileAbsolutePath = new File (baseDir, "singleFile-full.json").getAbsolutePath();
|
exportFileAbsolutePath = new File (baseDir, "singleFile-full.json").getAbsolutePath();
|
||||||
|
|
|
@ -57,7 +57,10 @@ import org.keycloak.testsuite.util.OAuthClient;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import org.junit.Assume;
|
||||||
|
import org.keycloak.models.RealmProvider;
|
||||||
|
|
||||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
|
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
|
||||||
import org.keycloak.testsuite.util.ContainerAssume;
|
import org.keycloak.testsuite.util.ContainerAssume;
|
||||||
|
@ -95,6 +98,8 @@ public class UserStorageFailureTest extends AbstractTestRealmKeycloakTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void addProvidersBeforeTest() {
|
public void addProvidersBeforeTest() {
|
||||||
|
Assume.assumeTrue("RealmProvider is not 'jpa'", isJpaRealmProvider());
|
||||||
|
|
||||||
ComponentRepresentation memProvider = new ComponentRepresentation();
|
ComponentRepresentation memProvider = new ComponentRepresentation();
|
||||||
memProvider.setName("failure");
|
memProvider.setName("failure");
|
||||||
memProvider.setProviderId(FailableHardcodedStorageProviderFactory.PROVIDER_ID);
|
memProvider.setProviderId(FailableHardcodedStorageProviderFactory.PROVIDER_ID);
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
import org.jboss.arquillian.graphene.page.Page;
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
|
import org.junit.Assume;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -89,6 +90,8 @@ public class UserStorageOTPTest extends AbstractTestRealmKeycloakTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void addProvidersBeforeTest() throws URISyntaxException, IOException {
|
public void addProvidersBeforeTest() throws URISyntaxException, IOException {
|
||||||
|
Assume.assumeTrue("RealmProvider is not 'jpa'", isJpaRealmProvider());
|
||||||
|
|
||||||
ComponentRepresentation dummyProvider = new ComponentRepresentation();
|
ComponentRepresentation dummyProvider = new ComponentRepresentation();
|
||||||
dummyProvider.setName("dummy");
|
dummyProvider.setName("dummy");
|
||||||
dummyProvider.setId(componentId);
|
dummyProvider.setId(componentId);
|
||||||
|
|
|
@ -39,6 +39,8 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import org.junit.Assume;
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
|
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
|
||||||
|
|
||||||
|
@ -53,6 +55,11 @@ public class SyncFederationTest extends AbstractAuthTest {
|
||||||
|
|
||||||
private static final Logger log = Logger.getLogger(SyncFederationTest.class);
|
private static final Logger log = Logger.getLogger(SyncFederationTest.class);
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void enabled() {
|
||||||
|
Assume.assumeTrue("RealmProvider is not 'jpa'", isJpaRealmProvider());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that period sync is triggered when creating a synchronized User Storage Provider
|
* Test that period sync is triggered when creating a synchronized User Storage Provider
|
||||||
*
|
*
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.testsuite.model;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import org.junit.Assume;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.component.ComponentModel;
|
import org.keycloak.component.ComponentModel;
|
||||||
|
@ -59,6 +60,7 @@ public class UserConsentWithUserStorageModelTest extends AbstractTestRealmKeyclo
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() {
|
public void before() {
|
||||||
|
Assume.assumeTrue("RealmProvider is not 'jpa'", isJpaRealmProvider());
|
||||||
testingClient.server().run(UserConsentWithUserStorageModelTest::setupEnv);
|
testingClient.server().run(UserConsentWithUserStorageModelTest::setupEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,11 +143,11 @@ public class ConcurrentHashMapStorageTest extends KeycloakModelTest {
|
||||||
assertClientsPersisted(component1Id, component2Id, idMain, id1, id2);
|
assertClientsPersisted(component1Id, component2Id, idMain, id1, id2);
|
||||||
|
|
||||||
// Invalidate one component and check that the storage still contains what it should
|
// Invalidate one component and check that the storage still contains what it should
|
||||||
getFactory().invalidate(ObjectType.COMPONENT, component1Id);
|
getFactory().invalidate(null, ObjectType.COMPONENT, component1Id);
|
||||||
assertClientsPersisted(component1Id, component2Id, idMain, id1, id2);
|
assertClientsPersisted(component1Id, component2Id, idMain, id1, id2);
|
||||||
|
|
||||||
// Invalidate whole realm and check that the storage still contains what it should
|
// Invalidate whole realm and check that the storage still contains what it should
|
||||||
getFactory().invalidate(ObjectType.REALM, realmId);
|
getFactory().invalidate(null, ObjectType.REALM, realmId);
|
||||||
assertClientsPersisted(component1Id, component2Id, idMain, id1, id2);
|
assertClientsPersisted(component1Id, component2Id, idMain, id1, id2);
|
||||||
|
|
||||||
// Refresh factory (akin server restart) and check that the storage still contains what it should
|
// Refresh factory (akin server restart) and check that the storage still contains what it should
|
||||||
|
|
Loading…
Reference in a new issue