Infinispan Protostream Marshaller (#29474)
Closes #29394 Signed-off-by: Pedro Ruivo <pruivo@redhat.com> Co-authored-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
parent
ca0833b2e4
commit
18a6c79011
134 changed files with 2617 additions and 4553 deletions
|
@ -9,3 +9,12 @@ to different organizations.
|
||||||
When creating a social broker, you should now provide an `Alias` and optionally a `Display name` just like any other
|
When creating a social broker, you should now provide an `Alias` and optionally a `Display name` just like any other
|
||||||
broker.
|
broker.
|
||||||
|
|
||||||
|
= Infinispan marshalling changes to Infinispan Protostream
|
||||||
|
|
||||||
|
Marshalling is the process of converting Java objects into bytes to send them across the network between {project_name} servers.
|
||||||
|
With {project_name} 26, we changed the marshalling format from JBoss Marshalling to Infinispan Protostream.
|
||||||
|
|
||||||
|
WARNING: JBoss Marshalling and Infinispan Protostream are not compatible with each other and incorrect usage may lead to data loss.
|
||||||
|
Consequently, all caches are cleared when upgrading to this version.
|
||||||
|
|
||||||
|
Infinispan Protostream is based on https://protobuf.dev/programming-guides/proto3/[Protocol Buffers] (proto 3), which has the advantage of backwards/forwards compatibility.
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
= Infinispan marshalling changes
|
||||||
|
|
||||||
|
Marshalling is the process of converting Java objects into bytes to send them across the network between {project_name} servers.
|
||||||
|
With {project_name} 26, the marshalling library has changed from JBoss Marshalling to Infinispan Protostream.
|
||||||
|
The libraries are not compatible between each other and, it requires some steps to ensure the session data is not lost.
|
||||||
|
|
||||||
|
WARNING: JBoss Marshalling and Infinispan Protostream are not compatible with each other and incorrect usage may lead to data loss.
|
||||||
|
Consequently, all caches are cleared when upgrading to this version.
|
||||||
|
|
||||||
|
To prevent losing user sessions upgrade to Keycloak 25 first and enable the persistent sessions feature as outlined in the migration guide for {project_name} 25.
|
|
@ -1,6 +1,10 @@
|
||||||
[[migration-changes]]
|
[[migration-changes]]
|
||||||
== Migration Changes
|
== Migration Changes
|
||||||
|
|
||||||
|
=== Migrating to 26.0.0
|
||||||
|
|
||||||
|
include::changes-26_0_0.adoc[leveloffset=3]
|
||||||
|
|
||||||
=== Migrating to 25.0.0
|
=== Migrating to 25.0.0
|
||||||
|
|
||||||
include::changes-25_0_0.adoc[leveloffset=3]
|
include::changes-25_0_0.adoc[leveloffset=3]
|
||||||
|
|
|
@ -67,7 +67,23 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-jboss-marshalling</artifactId>
|
<artifactId>infinispan-component-annotations</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.infinispan.protostream</groupId>
|
||||||
|
<artifactId>protostream</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.infinispan.protostream</groupId>
|
||||||
|
<artifactId>protostream-types</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.infinispan.protostream</groupId>
|
||||||
|
<artifactId>protostream-processor</artifactId>
|
||||||
|
<!-- compile-only dependency -->
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
package org.keycloak.cluster.infinispan;
|
package org.keycloak.cluster.infinispan;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
|
@ -35,10 +34,10 @@ abstract class CrossDCAwareCacheFactory {
|
||||||
protected static final Logger logger = Logger.getLogger(CrossDCAwareCacheFactory.class);
|
protected static final Logger logger = Logger.getLogger(CrossDCAwareCacheFactory.class);
|
||||||
|
|
||||||
|
|
||||||
abstract BasicCache<String, Serializable> getCache();
|
abstract BasicCache<String, Object> getCache();
|
||||||
|
|
||||||
|
|
||||||
static CrossDCAwareCacheFactory getFactory(Cache<String, Serializable> workCache, Set<RemoteStore> remoteStores) {
|
static CrossDCAwareCacheFactory getFactory(Cache<String, Object> workCache, Set<RemoteStore> remoteStores) {
|
||||||
if (remoteStores.isEmpty()) {
|
if (remoteStores.isEmpty()) {
|
||||||
logger.debugf("No configured remoteStore available. Cross-DC scenario is not used");
|
logger.debugf("No configured remoteStore available. Cross-DC scenario is not used");
|
||||||
return new InfinispanCacheWrapperFactory(workCache);
|
return new InfinispanCacheWrapperFactory(workCache);
|
||||||
|
@ -66,14 +65,14 @@ abstract class CrossDCAwareCacheFactory {
|
||||||
// We don't have external JDG configured. No cross-DC.
|
// We don't have external JDG configured. No cross-DC.
|
||||||
private static class InfinispanCacheWrapperFactory extends CrossDCAwareCacheFactory {
|
private static class InfinispanCacheWrapperFactory extends CrossDCAwareCacheFactory {
|
||||||
|
|
||||||
private final Cache<String, Serializable> workCache;
|
private final Cache<String, Object> workCache;
|
||||||
|
|
||||||
InfinispanCacheWrapperFactory(Cache<String, Serializable> workCache) {
|
InfinispanCacheWrapperFactory(Cache<String, Object> workCache) {
|
||||||
this.workCache = workCache;
|
this.workCache = workCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
BasicCache<String, Serializable> getCache() {
|
BasicCache<String, Object> getCache() {
|
||||||
return workCache;
|
return workCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,14 +82,14 @@ abstract class CrossDCAwareCacheFactory {
|
||||||
// We have external JDG configured. Cross-DC should be enabled
|
// We have external JDG configured. Cross-DC should be enabled
|
||||||
private static class RemoteCacheWrapperFactory extends CrossDCAwareCacheFactory {
|
private static class RemoteCacheWrapperFactory extends CrossDCAwareCacheFactory {
|
||||||
|
|
||||||
private final RemoteCache<String, Serializable> remoteCache;
|
private final RemoteCache<String, Object> remoteCache;
|
||||||
|
|
||||||
RemoteCacheWrapperFactory(RemoteCache<String, Serializable> remoteCache) {
|
RemoteCacheWrapperFactory(RemoteCache<String, Object> remoteCache) {
|
||||||
this.remoteCache = remoteCache;
|
this.remoteCache = remoteCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
BasicCache<String, Serializable> getCache() {
|
BasicCache<String, Object> getCache() {
|
||||||
// Flags are per-invocation!
|
// Flags are per-invocation!
|
||||||
return remoteCache.withFlags(Flag.FORCE_RETURN_VALUE);
|
return remoteCache.withFlags(Flag.FORCE_RETURN_VALUE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,18 +17,17 @@
|
||||||
|
|
||||||
package org.keycloak.cluster.infinispan;
|
package org.keycloak.cluster.infinispan;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.cluster.ClusterEvent;
|
import org.keycloak.cluster.ClusterEvent;
|
||||||
import org.keycloak.cluster.ClusterListener;
|
import org.keycloak.cluster.ClusterListener;
|
||||||
import org.keycloak.cluster.ClusterProvider;
|
import org.keycloak.cluster.ClusterProvider;
|
||||||
import org.keycloak.cluster.ExecutionResult;
|
import org.keycloak.cluster.ExecutionResult;
|
||||||
import org.keycloak.common.util.Retry;
|
import org.keycloak.common.util.Retry;
|
||||||
import org.keycloak.common.util.Time;
|
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -130,26 +129,18 @@ public class InfinispanClusterProvider implements ClusterProvider {
|
||||||
this.notificationsManager.notify(taskKey, event, ignoreSender, dcNotify);
|
this.notificationsManager.notify(taskKey, event, ignoreSender, dcNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LockEntry createLockEntry() {
|
|
||||||
LockEntry lock = new LockEntry();
|
|
||||||
lock.setNode(myAddress);
|
|
||||||
lock.setTimestamp(Time.currentTime());
|
|
||||||
return lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private boolean tryLock(String cacheKey, int taskTimeoutInSeconds) {
|
private boolean tryLock(String cacheKey, int taskTimeoutInSeconds) {
|
||||||
LockEntry myLock = createLockEntry();
|
LockEntry myLock = new LockEntry(myAddress);
|
||||||
|
|
||||||
LockEntry existingLock = InfinispanClusterProviderFactory.putIfAbsentWithRetries(crossDCAwareCacheFactory, cacheKey, myLock, taskTimeoutInSeconds);
|
LockEntry existingLock = InfinispanClusterProviderFactory.putIfAbsentWithRetries(crossDCAwareCacheFactory, cacheKey, myLock, taskTimeoutInSeconds);
|
||||||
if (existingLock != null) {
|
if (existingLock != null) {
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.tracef("Task %s in progress already by node %s. Ignoring task.", cacheKey, existingLock.getNode());
|
logger.tracef("Task %s in progress already by node %s. Ignoring task.", cacheKey, existingLock.node());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.tracef("Successfully acquired lock for task %s. Our node is %s", cacheKey, myLock.getNode());
|
logger.tracef("Successfully acquired lock for task %s. Our node is %s", cacheKey, myLock.node());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,6 @@ import org.keycloak.connections.infinispan.TopologyInfo;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
@ -59,7 +58,7 @@ public class InfinispanClusterProviderFactory implements ClusterProviderFactory
|
||||||
protected static final Logger logger = Logger.getLogger(InfinispanClusterProviderFactory.class);
|
protected static final Logger logger = Logger.getLogger(InfinispanClusterProviderFactory.class);
|
||||||
|
|
||||||
// Infinispan cache
|
// Infinispan cache
|
||||||
private volatile Cache<String, Serializable> workCache;
|
private volatile Cache<String, Object> workCache;
|
||||||
|
|
||||||
// Ensure that atomic operations (like putIfAbsent) must work correctly in any of: non-clustered, clustered or cross-Data-Center (cross-DC) setups
|
// Ensure that atomic operations (like putIfAbsent) must work correctly in any of: non-clustered, clustered or cross-Data-Center (cross-DC) setups
|
||||||
private CrossDCAwareCacheFactory crossDCAwareCacheFactory;
|
private CrossDCAwareCacheFactory crossDCAwareCacheFactory;
|
||||||
|
@ -134,7 +133,7 @@ public class InfinispanClusterProviderFactory implements ClusterProviderFactory
|
||||||
|
|
||||||
// Will retry few times for the case when backup site not available in cross-dc environment.
|
// Will retry few times for the case when backup site not available in cross-dc environment.
|
||||||
// The site might be taken offline automatically if "take-offline" properly configured
|
// The site might be taken offline automatically if "take-offline" properly configured
|
||||||
static <V extends Serializable> V putIfAbsentWithRetries(CrossDCAwareCacheFactory crossDCAwareCacheFactory, String key, V value, int taskTimeoutInSeconds) {
|
static <V> V putIfAbsentWithRetries(CrossDCAwareCacheFactory crossDCAwareCacheFactory, String key, V value, int taskTimeoutInSeconds) {
|
||||||
AtomicReference<V> resultRef = new AtomicReference<>();
|
AtomicReference<V> resultRef = new AtomicReference<>();
|
||||||
|
|
||||||
Retry.executeWithBackoff(iteration -> {
|
Retry.executeWithBackoff(iteration -> {
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class InfinispanNotificationsManager {
|
||||||
|
|
||||||
private final ConcurrentMap<String, TaskCallback> taskCallbacks = new ConcurrentHashMap<>();
|
private final ConcurrentMap<String, TaskCallback> taskCallbacks = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final Cache<String, Serializable> workCache;
|
private final Cache<String, Object> workCache;
|
||||||
|
|
||||||
private final RemoteCache<Object, Serializable> workRemoteCache;
|
private final RemoteCache<Object, Serializable> workRemoteCache;
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ public class InfinispanNotificationsManager {
|
||||||
|
|
||||||
private final ExecutorService listenersExecutor;
|
private final ExecutorService listenersExecutor;
|
||||||
|
|
||||||
protected InfinispanNotificationsManager(Cache<String, Serializable> workCache, RemoteCache<Object, Serializable> workRemoteCache, String myAddress, String mySite, ExecutorService listenersExecutor) {
|
protected InfinispanNotificationsManager(Cache<String, Object> workCache, RemoteCache<Object, Serializable> workRemoteCache, String myAddress, String mySite, ExecutorService listenersExecutor) {
|
||||||
this.workCache = workCache;
|
this.workCache = workCache;
|
||||||
this.workRemoteCache = workRemoteCache;
|
this.workRemoteCache = workRemoteCache;
|
||||||
this.myAddress = myAddress;
|
this.myAddress = myAddress;
|
||||||
|
@ -95,7 +95,7 @@ public class InfinispanNotificationsManager {
|
||||||
|
|
||||||
|
|
||||||
// Create and init manager including all listeners etc
|
// Create and init manager including all listeners etc
|
||||||
public static InfinispanNotificationsManager create(KeycloakSession session, Cache<String, Serializable> workCache, String myAddress, String mySite, Set<RemoteStore> remoteStores) {
|
public static InfinispanNotificationsManager create(KeycloakSession session, Cache<String, Object> workCache, String myAddress, String mySite, Set<RemoteStore> remoteStores) {
|
||||||
RemoteCache<Object, Serializable> workRemoteCache = null;
|
RemoteCache<Object, Serializable> workRemoteCache = null;
|
||||||
|
|
||||||
if (!remoteStores.isEmpty()) {
|
if (!remoteStores.isEmpty()) {
|
||||||
|
@ -141,13 +141,7 @@ public class InfinispanNotificationsManager {
|
||||||
|
|
||||||
|
|
||||||
void notify(String taskKey, ClusterEvent event, boolean ignoreSender, ClusterProvider.DCNotify dcNotify) {
|
void notify(String taskKey, ClusterEvent event, boolean ignoreSender, ClusterProvider.DCNotify dcNotify) {
|
||||||
WrapperClusterEvent wrappedEvent = new WrapperClusterEvent();
|
var wrappedEvent = WrapperClusterEvent.wrap(taskKey, event, myAddress, mySite, dcNotify, ignoreSender);
|
||||||
wrappedEvent.setEventKey(taskKey);
|
|
||||||
wrappedEvent.setDelegateEvent(event);
|
|
||||||
wrappedEvent.setIgnoreSender(ignoreSender);
|
|
||||||
wrappedEvent.setIgnoreSenderSite(dcNotify == ClusterProvider.DCNotify.ALL_BUT_LOCAL_DC);
|
|
||||||
wrappedEvent.setSender(myAddress);
|
|
||||||
wrappedEvent.setSenderSite(mySite);
|
|
||||||
|
|
||||||
String eventKey = UUID.randomUUID().toString();
|
String eventKey = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
@ -186,17 +180,17 @@ public class InfinispanNotificationsManager {
|
||||||
public class CacheEntryListener {
|
public class CacheEntryListener {
|
||||||
|
|
||||||
@CacheEntryCreated
|
@CacheEntryCreated
|
||||||
public void cacheEntryCreated(CacheEntryCreatedEvent<String, Serializable> event) {
|
public void cacheEntryCreated(CacheEntryCreatedEvent<String, Object> event) {
|
||||||
eventReceived(event.getKey(), event.getValue());
|
eventReceived(event.getKey(), event.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@CacheEntryModified
|
@CacheEntryModified
|
||||||
public void cacheEntryModified(CacheEntryModifiedEvent<String, Serializable> event) {
|
public void cacheEntryModified(CacheEntryModifiedEvent<String, Object> event) {
|
||||||
eventReceived(event.getKey(), event.getNewValue());
|
eventReceived(event.getKey(), event.getNewValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@CacheEntryRemoved
|
@CacheEntryRemoved
|
||||||
public void cacheEntryRemoved(CacheEntryRemovedEvent<String, Serializable> event) {
|
public void cacheEntryRemoved(CacheEntryRemovedEvent<String, Object> event) {
|
||||||
taskFinished(event.getKey());
|
taskFinished(event.getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +261,7 @@ public class InfinispanNotificationsManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void eventReceived(String key, Serializable obj) {
|
private void eventReceived(String key, Object obj) {
|
||||||
if (!(obj instanceof WrapperClusterEvent event)) {
|
if (!(obj instanceof WrapperClusterEvent event)) {
|
||||||
// Items with the TASK_KEY_PREFIX might be gone fast once the locking is complete, therefore, don't log them.
|
// Items with the TASK_KEY_PREFIX might be gone fast once the locking is complete, therefore, don't log them.
|
||||||
// It is still good to have the warning in case of real events return null because they have been, for example, expired
|
// It is still good to have the warning in case of real events return null because they have been, for example, expired
|
||||||
|
@ -277,17 +271,9 @@ public class InfinispanNotificationsManager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.isIgnoreSender()) {
|
if (event.rejectEvent(myAddress, mySite)) {
|
||||||
if (this.myAddress.equals(event.getSender())) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (event.isIgnoreSenderSite()) {
|
|
||||||
if (this.mySite == null || this.mySite.equals(event.getSenderSite())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String eventKey = event.getEventKey();
|
String eventKey = event.getEventKey();
|
||||||
|
|
||||||
|
|
|
@ -17,67 +17,14 @@
|
||||||
|
|
||||||
package org.keycloak.cluster.infinispan;
|
package org.keycloak.cluster.infinispan;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.infinispan.protostream.annotations.Proto;
|
||||||
import java.io.ObjectInput;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import java.io.ObjectOutput;
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.KeycloakMarshallUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(LockEntry.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.LOCK_ENTRY)
|
||||||
public class LockEntry implements Serializable {
|
@Proto
|
||||||
|
public record LockEntry(String node) {
|
||||||
private String node;
|
|
||||||
private int timestamp;
|
|
||||||
|
|
||||||
public String getNode() {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNode(String node) {
|
|
||||||
this.node = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTimestamp() {
|
|
||||||
return timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTimestamp(int timestamp) {
|
|
||||||
this.timestamp = timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<LockEntry> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, LockEntry obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
MarshallUtil.marshallString(obj.node, output);
|
|
||||||
KeycloakMarshallUtil.marshall(obj.timestamp, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LockEntry readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LockEntry readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
LockEntry entry = new LockEntry();
|
|
||||||
entry.setNode(MarshallUtil.unmarshallString(input));
|
|
||||||
entry.setTimestamp(KeycloakMarshallUtil.unmarshallInteger(input));
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,67 +18,38 @@
|
||||||
|
|
||||||
package org.keycloak.cluster.infinispan;
|
package org.keycloak.cluster.infinispan;
|
||||||
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
import java.util.HashSet;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.KeycloakMarshallUtil;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(LockEntryPredicate.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.LOCK_ENTRY_PREDICATE)
|
||||||
public class LockEntryPredicate implements Predicate<Map.Entry<String, Serializable>> {
|
public class LockEntryPredicate implements Predicate<Map.Entry<String, Object>> {
|
||||||
|
|
||||||
private final Set<String> removedNodesAddresses;
|
private final Set<String> removedNodesAddresses;
|
||||||
|
|
||||||
|
@ProtoFactory
|
||||||
public LockEntryPredicate(Set<String> removedNodesAddresses) {
|
public LockEntryPredicate(Set<String> removedNodesAddresses) {
|
||||||
this.removedNodesAddresses = removedNodesAddresses;
|
this.removedNodesAddresses = removedNodesAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@ProtoField(value = 1, collectionImplementation = HashSet.class)
|
||||||
public boolean test(Map.Entry<String, Serializable> entry) {
|
Set<String> getRemovedNodesAddresses() {
|
||||||
if (!(entry.getValue() instanceof LockEntry)) {
|
return removedNodesAddresses;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
LockEntry lock = (LockEntry) entry.getValue();
|
|
||||||
|
|
||||||
return removedNodesAddresses.contains(lock.getNode());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<LockEntryPredicate> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, LockEntryPredicate obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
KeycloakMarshallUtil.writeCollection(obj.removedNodesAddresses, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LockEntryPredicate readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
public boolean test(Map.Entry<String, Object> entry) {
|
||||||
switch (input.readByte()) {
|
return entry.getValue() instanceof LockEntry lock &&
|
||||||
case VERSION_1:
|
removedNodesAddresses.contains(lock.node());
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LockEntryPredicate readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
return new LockEntryPredicate(
|
|
||||||
KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, ConcurrentHashMap::newKeySet)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,134 +17,124 @@
|
||||||
|
|
||||||
package org.keycloak.cluster.infinispan;
|
package org.keycloak.cluster.infinispan;
|
||||||
|
|
||||||
import org.keycloak.cluster.ClusterEvent;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
import org.infinispan.protostream.WrappedMessage;
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import org.infinispan.protostream.annotations.Proto;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.cluster.ClusterEvent;
|
||||||
|
import org.keycloak.cluster.ClusterProvider;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(WrapperClusterEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.WRAPPED_CLUSTER_EVENT)
|
||||||
public class WrapperClusterEvent implements ClusterEvent {
|
public class WrapperClusterEvent implements ClusterEvent {
|
||||||
|
|
||||||
private String eventKey;
|
@ProtoField(1)
|
||||||
private String sender;
|
final String eventKey;
|
||||||
private String senderSite;
|
@ProtoField(2)
|
||||||
private boolean ignoreSender;
|
final String senderAddress; // null means invoke everywhere
|
||||||
private boolean ignoreSenderSite;
|
@ProtoField(3)
|
||||||
private ClusterEvent delegateEvent;
|
final String senderSite; // can be null
|
||||||
|
@ProtoField(4)
|
||||||
|
final SiteFilter siteFilter;
|
||||||
|
final ClusterEvent delegateEvent;
|
||||||
|
|
||||||
|
private WrapperClusterEvent(String eventKey, String senderAddress, String senderSite, SiteFilter siteFilter, ClusterEvent delegateEvent) {
|
||||||
|
this.eventKey = Objects.requireNonNull(eventKey);
|
||||||
|
this.senderAddress = senderAddress;
|
||||||
|
this.senderSite = senderSite;
|
||||||
|
this.siteFilter = Objects.requireNonNull(siteFilter);
|
||||||
|
this.delegateEvent = Objects.requireNonNull(delegateEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtoFactory
|
||||||
|
static WrapperClusterEvent protoFactory(String eventKey, String senderAddress, String senderSite, SiteFilter siteFilter, WrappedMessage eventPS) {
|
||||||
|
return new WrapperClusterEvent(eventKey, Marshalling.emptyStringToNull(senderAddress), Marshalling.emptyStringToNull(senderSite), siteFilter, (ClusterEvent) eventPS.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WrapperClusterEvent wrap(String eventKey, ClusterEvent event, String senderAddress, String senderSite, ClusterProvider.DCNotify dcNotify, boolean ignoreSender) {
|
||||||
|
senderAddress = ignoreSender ? Objects.requireNonNull(senderAddress) : null;
|
||||||
|
senderSite = dcNotify == ClusterProvider.DCNotify.ALL_DCS ? null : senderSite;
|
||||||
|
var siteNotification = switch (dcNotify) {
|
||||||
|
case ALL_DCS -> SiteFilter.ALL;
|
||||||
|
case LOCAL_DC_ONLY -> SiteFilter.LOCAL;
|
||||||
|
case ALL_BUT_LOCAL_DC -> SiteFilter.REMOTE;
|
||||||
|
};
|
||||||
|
return new WrapperClusterEvent(eventKey, senderAddress, senderSite, siteNotification, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtoField(5)
|
||||||
|
WrappedMessage getEventPS() {
|
||||||
|
return new WrappedMessage(delegateEvent);
|
||||||
|
}
|
||||||
|
|
||||||
public String getEventKey() {
|
public String getEventKey() {
|
||||||
return eventKey;
|
return eventKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEventKey(String eventKey) {
|
|
||||||
this.eventKey = eventKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSender() {
|
|
||||||
return sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSender(String sender) {
|
|
||||||
this.sender = sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSenderSite() {
|
|
||||||
return senderSite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSenderSite(String senderSite) {
|
|
||||||
this.senderSite = senderSite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isIgnoreSender() {
|
|
||||||
return ignoreSender;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIgnoreSender(boolean ignoreSender) {
|
|
||||||
this.ignoreSender = ignoreSender;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isIgnoreSenderSite() {
|
|
||||||
return ignoreSenderSite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIgnoreSenderSite(boolean ignoreSenderSite) {
|
|
||||||
this.ignoreSenderSite = ignoreSenderSite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClusterEvent getDelegateEvent() {
|
public ClusterEvent getDelegateEvent() {
|
||||||
return delegateEvent;
|
return delegateEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDelegateEvent(ClusterEvent delegateEvent) {
|
public boolean rejectEvent(String mySiteAddress, String mySiteName) {
|
||||||
this.delegateEvent = delegateEvent;
|
return (senderAddress != null && senderAddress.equals(mySiteAddress)) ||
|
||||||
|
(senderSite != null && siteFilter.reject(senderSite, mySiteName));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
WrapperClusterEvent that = (WrapperClusterEvent) o;
|
WrapperClusterEvent that = (WrapperClusterEvent) o;
|
||||||
return ignoreSender == that.ignoreSender && ignoreSenderSite == that.ignoreSenderSite && Objects.equals(eventKey, that.eventKey) && Objects.equals(sender, that.sender) && Objects.equals(senderSite, that.senderSite) && Objects.equals(delegateEvent, that.delegateEvent);
|
return eventKey.equals(that.eventKey) &&
|
||||||
|
Objects.equals(senderAddress, that.senderAddress) &&
|
||||||
|
Objects.equals(senderSite, that.senderSite) &&
|
||||||
|
siteFilter == that.siteFilter &&
|
||||||
|
delegateEvent.equals(that.delegateEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(eventKey, sender, senderSite, ignoreSender, ignoreSenderSite, delegateEvent);
|
int result = eventKey.hashCode();
|
||||||
|
result = 31 * result + Objects.hashCode(senderAddress);
|
||||||
|
result = 31 * result + Objects.hashCode(senderSite);
|
||||||
|
result = 31 * result + siteFilter.hashCode();
|
||||||
|
result = 31 * result + delegateEvent.hashCode();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("WrapperClusterEvent [ eventKey=%s, sender=%s, senderSite=%s, delegateEvent=%s ]", eventKey, sender, senderSite, delegateEvent.toString());
|
return String.format("WrapperClusterEvent [ eventKey=%s, sender=%s, senderSite=%s, delegateEvent=%s ]", eventKey, senderAddress, senderSite, delegateEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<WrapperClusterEvent> {
|
@Proto
|
||||||
|
@ProtoTypeId(Marshalling.WRAPPED_CLUSTER_EVENT_SITE_FILTER)
|
||||||
private static final int VERSION_1 = 1;
|
public enum SiteFilter {
|
||||||
|
ALL {
|
||||||
@Override
|
@Override
|
||||||
public void writeObject(ObjectOutput output, WrapperClusterEvent obj) throws IOException {
|
boolean reject(String senderSite, String mySite) {
|
||||||
output.writeByte(VERSION_1);
|
return false;
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.eventKey, output);
|
|
||||||
MarshallUtil.marshallString(obj.sender, output);
|
|
||||||
MarshallUtil.marshallString(obj.senderSite, output);
|
|
||||||
output.writeBoolean(obj.ignoreSender);
|
|
||||||
output.writeBoolean(obj.ignoreSenderSite);
|
|
||||||
|
|
||||||
output.writeObject(obj.delegateEvent);
|
|
||||||
}
|
}
|
||||||
|
}, LOCAL {
|
||||||
@Override
|
@Override
|
||||||
public WrapperClusterEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
boolean reject(String senderSite, String mySite) {
|
||||||
switch (input.readByte()) {
|
return !Objects.equals(senderSite, mySite);
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
}
|
||||||
|
}, REMOTE {
|
||||||
|
@Override
|
||||||
|
boolean reject(String senderSite, String mySite) {
|
||||||
|
return Objects.equals(senderSite, mySite);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public WrapperClusterEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
abstract boolean reject(String senderSite, String mySite);
|
||||||
WrapperClusterEvent res = new WrapperClusterEvent();
|
|
||||||
|
|
||||||
res.eventKey = MarshallUtil.unmarshallString(input);
|
|
||||||
res.sender = MarshallUtil.unmarshallString(input);
|
|
||||||
res.senderSite = MarshallUtil.unmarshallString(input);
|
|
||||||
res.ignoreSender = input.readBoolean();
|
|
||||||
res.ignoreSenderSite = input.readBoolean();
|
|
||||||
|
|
||||||
res.delegateEvent = (ClusterEvent) input.readObject();
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,14 @@
|
||||||
|
|
||||||
package org.keycloak.connections.infinispan;
|
package org.keycloak.connections.infinispan;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletionStage;
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.infinispan.client.hotrod.RemoteCache;
|
import org.infinispan.client.hotrod.RemoteCache;
|
||||||
|
import org.infinispan.commons.util.concurrent.CompletionStages;
|
||||||
|
import org.infinispan.factories.ComponentRegistry;
|
||||||
import org.infinispan.manager.EmbeddedCacheManager;
|
import org.infinispan.manager.EmbeddedCacheManager;
|
||||||
|
import org.infinispan.persistence.manager.PersistenceManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
@ -36,6 +41,14 @@ public class DefaultInfinispanConnectionProvider implements InfinispanConnection
|
||||||
this.topologyInfo = topologyInfo;
|
this.topologyInfo = topologyInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static PersistenceManager persistenceManager(Cache<?, ?> cache) {
|
||||||
|
return ComponentRegistry.componentOf(cache, PersistenceManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CompletionStage<Void> clearPersistenceManager(PersistenceManager persistenceManager) {
|
||||||
|
return persistenceManager.clearAllStores(PersistenceManager.AccessMode.BOTH);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <K, V> Cache<K, V> getCache(String name, boolean createIfAbsent) {
|
public <K, V> Cache<K, V> getCache(String name, boolean createIfAbsent) {
|
||||||
return cacheManager.getCache(name, createIfAbsent);
|
return cacheManager.getCache(name, createIfAbsent);
|
||||||
|
@ -51,6 +64,19 @@ public class DefaultInfinispanConnectionProvider implements InfinispanConnection
|
||||||
return topologyInfo;
|
return topologyInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletionStage<Void> migrateToProtostream() {
|
||||||
|
// Only the CacheStore (persistence) stores data in binary format and needs to be deleted.
|
||||||
|
// We assume rolling-upgrade between KC 25 and KC 26 is not available, in other words, KC 25 and KC 26 servers are not present in the same cluster.
|
||||||
|
var stage = CompletionStages.aggregateCompletionStage();
|
||||||
|
DISTRIBUTED_REPLICATED_CACHE_NAMES.stream()
|
||||||
|
.map(this::getCache)
|
||||||
|
.map(DefaultInfinispanConnectionProvider::persistenceManager)
|
||||||
|
.map(DefaultInfinispanConnectionProvider::clearPersistenceManager)
|
||||||
|
.forEach(stage::dependsOn);
|
||||||
|
return stage.freeze();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,7 +238,8 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
|
||||||
|
|
||||||
if (clustered) {
|
if (clustered) {
|
||||||
String jgroupsUdpMcastAddr = config.get("jgroupsUdpMcastAddr", System.getProperty(InfinispanConnectionProvider.JGROUPS_UDP_MCAST_ADDR));
|
String jgroupsUdpMcastAddr = config.get("jgroupsUdpMcastAddr", System.getProperty(InfinispanConnectionProvider.JGROUPS_UDP_MCAST_ADDR));
|
||||||
configureTransport(gcb, topologyInfo.getMyNodeName(), topologyInfo.getMySiteName(), jgroupsUdpMcastAddr,
|
String jgroupsBindAddr = config.get("jgroupsBindAddr", System.getProperty(InfinispanConnectionProvider.JGROUPS_BIND_ADDR));
|
||||||
|
configureTransport(gcb, topologyInfo.getMyNodeName(), topologyInfo.getMySiteName(), jgroupsUdpMcastAddr, jgroupsBindAddr,
|
||||||
"default-configs/default-keycloak-jgroups-udp.xml");
|
"default-configs/default-keycloak-jgroups-udp.xml");
|
||||||
gcb.jmx()
|
gcb.jmx()
|
||||||
.domain(InfinispanConnectionProvider.JMX_DOMAIN + "-" + topologyInfo.getMyNodeName()).enable();
|
.domain(InfinispanConnectionProvider.JMX_DOMAIN + "-" + topologyInfo.getMyNodeName()).enable();
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
package org.keycloak.connections.infinispan;
|
package org.keycloak.connections.infinispan;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletionStage;
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.infinispan.client.hotrod.RemoteCache;
|
import org.infinispan.client.hotrod.RemoteCache;
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
|
@ -57,7 +59,8 @@ public interface InfinispanConnectionProvider extends Provider {
|
||||||
|
|
||||||
// System property used on Wildfly to identify distributedCache address and sticky session route
|
// System property used on Wildfly to identify distributedCache address and sticky session route
|
||||||
String JBOSS_NODE_NAME = "jboss.node.name";
|
String JBOSS_NODE_NAME = "jboss.node.name";
|
||||||
String JGROUPS_UDP_MCAST_ADDR = "jgroups.udp.mcast_addr";
|
String JGROUPS_UDP_MCAST_ADDR = "jgroups.mcast_addr";
|
||||||
|
String JGROUPS_BIND_ADDR = "jgroups.bind.address";
|
||||||
|
|
||||||
// TODO This property is not in Wildfly. Check if corresponding property in Wildfly exists
|
// TODO This property is not in Wildfly. Check if corresponding property in Wildfly exists
|
||||||
String JBOSS_SITE_NAME = "jboss.site.name";
|
String JBOSS_SITE_NAME = "jboss.site.name";
|
||||||
|
@ -127,4 +130,11 @@ public interface InfinispanConnectionProvider extends Provider {
|
||||||
*/
|
*/
|
||||||
TopologyInfo getTopologyInfo();
|
TopologyInfo getTopologyInfo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrates the JBoss Marshalling encoding to Infinispan Protostream
|
||||||
|
*
|
||||||
|
* @return A {@link CompletionStage} to signal when the operator is completed.
|
||||||
|
*/
|
||||||
|
CompletionStage<Void> migrateToProtostream();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ public class InfinispanUtil {
|
||||||
private static final Object CHANNEL_INIT_SYNCHRONIZER = new Object();
|
private static final Object CHANNEL_INIT_SYNCHRONIZER = new Object();
|
||||||
|
|
||||||
public static void configureTransport(GlobalConfigurationBuilder gcb, String nodeName, String siteName, String jgroupsUdpMcastAddr,
|
public static void configureTransport(GlobalConfigurationBuilder gcb, String nodeName, String siteName, String jgroupsUdpMcastAddr,
|
||||||
String jgroupsConfigPath) {
|
String jgroupsBindAddr, String jgroupsConfigPath) {
|
||||||
if (nodeName == null) {
|
if (nodeName == null) {
|
||||||
gcb.transport().defaultTransport();
|
gcb.transport().defaultTransport();
|
||||||
} else {
|
} else {
|
||||||
|
@ -115,6 +115,12 @@ public class InfinispanUtil {
|
||||||
} else {
|
} else {
|
||||||
System.setProperty(InfinispanConnectionProvider.JGROUPS_UDP_MCAST_ADDR, jgroupsUdpMcastAddr);
|
System.setProperty(InfinispanConnectionProvider.JGROUPS_UDP_MCAST_ADDR, jgroupsUdpMcastAddr);
|
||||||
}
|
}
|
||||||
|
var originalBindAddr = System.getProperty(InfinispanConnectionProvider.JGROUPS_BIND_ADDR);
|
||||||
|
if (jgroupsBindAddr == null) {
|
||||||
|
System.getProperties().remove(InfinispanConnectionProvider.JGROUPS_BIND_ADDR);
|
||||||
|
} else {
|
||||||
|
System.setProperty(InfinispanConnectionProvider.JGROUPS_BIND_ADDR, jgroupsBindAddr);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
JChannel channel = new JChannel(fileLookup.lookupFileLocation(jgroupsConfigPath, InfinispanUtil.class.getClassLoader()).openStream());
|
JChannel channel = new JChannel(fileLookup.lookupFileLocation(jgroupsConfigPath, InfinispanUtil.class.getClassLoader()).openStream());
|
||||||
channel.setName(nodeName);
|
channel.setName(nodeName);
|
||||||
|
@ -144,6 +150,11 @@ public class InfinispanUtil {
|
||||||
} else {
|
} else {
|
||||||
System.setProperty(InfinispanConnectionProvider.JGROUPS_UDP_MCAST_ADDR, originalMcastAddr);
|
System.setProperty(InfinispanConnectionProvider.JGROUPS_UDP_MCAST_ADDR, originalMcastAddr);
|
||||||
}
|
}
|
||||||
|
if (originalBindAddr == null) {
|
||||||
|
System.getProperties().remove(InfinispanConnectionProvider.JGROUPS_BIND_ADDR);
|
||||||
|
} else {
|
||||||
|
System.setProperty(InfinispanConnectionProvider.JGROUPS_BIND_ADDR, originalBindAddr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,69 +17,33 @@
|
||||||
|
|
||||||
package org.keycloak.keys.infinispan;
|
package org.keycloak.keys.infinispan;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(PublicKeyStorageInvalidationEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.PUBLIC_KEY_INVALIDATION_EVENT)
|
||||||
public class PublicKeyStorageInvalidationEvent extends InvalidationEvent {
|
public class PublicKeyStorageInvalidationEvent extends InvalidationEvent {
|
||||||
|
|
||||||
private String cacheKey;
|
private PublicKeyStorageInvalidationEvent(String cacheKey) {
|
||||||
|
super(cacheKey);
|
||||||
public static PublicKeyStorageInvalidationEvent create(String cacheKey) {
|
|
||||||
PublicKeyStorageInvalidationEvent event = new PublicKeyStorageInvalidationEvent();
|
|
||||||
event.cacheKey = cacheKey;
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@ProtoFactory
|
||||||
public String getId() {
|
public static PublicKeyStorageInvalidationEvent create(String id) {
|
||||||
return cacheKey;
|
return new PublicKeyStorageInvalidationEvent(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCacheKey() {
|
public String getCacheKey() {
|
||||||
return cacheKey;
|
return getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "PublicKeyStorageInvalidationEvent [ " + cacheKey + " ]";
|
return "PublicKeyStorageInvalidationEvent [ " + getId() + " ]";
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<PublicKeyStorageInvalidationEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, PublicKeyStorageInvalidationEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.cacheKey, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PublicKeyStorageInvalidationEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PublicKeyStorageInvalidationEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
PublicKeyStorageInvalidationEvent res = new PublicKeyStorageInvalidationEvent();
|
|
||||||
res.cacheKey = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,12 @@
|
||||||
|
|
||||||
package org.keycloak.keys.infinispan;
|
package org.keycloak.keys.infinispan;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import org.keycloak.crypto.PublicKeysWrapper;
|
import org.keycloak.crypto.PublicKeysWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
public class PublicKeysEntry implements Serializable {
|
public class PublicKeysEntry {
|
||||||
|
|
||||||
private final int lastRequestTime;
|
private final int lastRequestTime;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,200 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.marshalling;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.GeneratedSchema;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoSchema;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoSyntax;
|
||||||
|
import org.infinispan.protostream.types.java.CommonTypes;
|
||||||
|
import org.keycloak.cluster.infinispan.LockEntry;
|
||||||
|
import org.keycloak.cluster.infinispan.LockEntryPredicate;
|
||||||
|
import org.keycloak.cluster.infinispan.WrapperClusterEvent;
|
||||||
|
import org.keycloak.component.ComponentModel;
|
||||||
|
import org.keycloak.keys.infinispan.PublicKeyStorageInvalidationEvent;
|
||||||
|
import org.keycloak.models.UserSessionModel;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.PolicyRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.PolicyUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.ResourceRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.ResourceServerRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.ResourceServerUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.ResourceUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.ScopeRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.events.ScopeUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.stream.InResourcePredicate;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.stream.InResourceServerPredicate;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.stream.InScopePredicate;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.AuthenticationSessionAuthNoteUpdateEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.ClientAddedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.ClientRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.ClientScopeAddedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.ClientScopeRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.ClientUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.GroupAddedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.GroupMovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.GroupRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.GroupUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.RealmRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.RealmUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.RoleAddedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.RoleRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.RoleUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.UserCacheRealmInvalidationEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.UserConsentsUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.UserFederationLinkRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.UserFederationLinkUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.UserFullInvalidationEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.UserUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.stream.GroupListPredicate;
|
||||||
|
import org.keycloak.models.cache.infinispan.stream.HasRolePredicate;
|
||||||
|
import org.keycloak.models.cache.infinispan.stream.InClientPredicate;
|
||||||
|
import org.keycloak.models.cache.infinispan.stream.InGroupPredicate;
|
||||||
|
import org.keycloak.models.cache.infinispan.stream.InIdentityProviderPredicate;
|
||||||
|
import org.keycloak.models.cache.infinispan.stream.InRealmPredicate;
|
||||||
|
import org.keycloak.models.sessions.infinispan.changes.ReplaceFunction;
|
||||||
|
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
||||||
|
import org.keycloak.models.sessions.infinispan.changes.sessions.LastSessionRefreshEvent;
|
||||||
|
import org.keycloak.models.sessions.infinispan.changes.sessions.SessionData;
|
||||||
|
import org.keycloak.models.sessions.infinispan.entities.AuthenticatedClientSessionEntity;
|
||||||
|
import org.keycloak.models.sessions.infinispan.entities.AuthenticatedClientSessionStore;
|
||||||
|
import org.keycloak.models.sessions.infinispan.entities.AuthenticationSessionEntity;
|
||||||
|
import org.keycloak.models.sessions.infinispan.entities.LoginFailureEntity;
|
||||||
|
import org.keycloak.models.sessions.infinispan.entities.LoginFailureKey;
|
||||||
|
import org.keycloak.models.sessions.infinispan.entities.RootAuthenticationSessionEntity;
|
||||||
|
import org.keycloak.models.sessions.infinispan.entities.SingleUseObjectValueEntity;
|
||||||
|
import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
|
||||||
|
import org.keycloak.models.sessions.infinispan.events.RealmRemovedSessionEvent;
|
||||||
|
import org.keycloak.models.sessions.infinispan.events.RemoveAllUserLoginFailuresEvent;
|
||||||
|
import org.keycloak.models.sessions.infinispan.events.RemoveUserSessionsEvent;
|
||||||
|
import org.keycloak.models.sessions.infinispan.initializer.InitializerState;
|
||||||
|
import org.keycloak.models.sessions.infinispan.stream.SessionPredicate;
|
||||||
|
import org.keycloak.models.sessions.infinispan.stream.SessionWrapperPredicate;
|
||||||
|
import org.keycloak.models.sessions.infinispan.stream.UserSessionPredicate;
|
||||||
|
import org.keycloak.sessions.CommonClientSessionModel;
|
||||||
|
import org.keycloak.storage.UserStorageProviderModel;
|
||||||
|
import org.keycloak.storage.managers.UserStorageSyncManager;
|
||||||
|
|
||||||
|
@ProtoSchema(
|
||||||
|
syntax = ProtoSyntax.PROTO3,
|
||||||
|
schemaPackageName = "keycloak",
|
||||||
|
schemaFilePath = "proto/generated",
|
||||||
|
|
||||||
|
// common-types for UUID
|
||||||
|
dependsOn = CommonTypes.class,
|
||||||
|
|
||||||
|
includeClasses = {
|
||||||
|
// Model
|
||||||
|
UserSessionModel.State.class,
|
||||||
|
CommonClientSessionModel.ExecutionStatus.class,
|
||||||
|
ComponentModel.MultiMapEntry.class,
|
||||||
|
UserStorageProviderModel.class,
|
||||||
|
UserStorageSyncManager.UserStorageProviderClusterEvent.class,
|
||||||
|
|
||||||
|
// clustering.infinispan package
|
||||||
|
LockEntry.class,
|
||||||
|
LockEntryPredicate.class,
|
||||||
|
WrapperClusterEvent.class,
|
||||||
|
WrapperClusterEvent.SiteFilter.class,
|
||||||
|
|
||||||
|
// keys.infinispan package
|
||||||
|
PublicKeyStorageInvalidationEvent.class,
|
||||||
|
|
||||||
|
//models.cache.infinispan.authorization.events package
|
||||||
|
PolicyUpdatedEvent.class,
|
||||||
|
PolicyRemovedEvent.class,
|
||||||
|
ResourceUpdatedEvent.class,
|
||||||
|
ResourceRemovedEvent.class,
|
||||||
|
ResourceServerUpdatedEvent.class,
|
||||||
|
ResourceServerRemovedEvent.class,
|
||||||
|
ScopeUpdatedEvent.class,
|
||||||
|
ScopeRemovedEvent.class,
|
||||||
|
|
||||||
|
// models.sessions.infinispan.initializer package
|
||||||
|
InitializerState.class,
|
||||||
|
|
||||||
|
// models.sessions.infinispan.changes package
|
||||||
|
SessionEntityWrapper.class,
|
||||||
|
|
||||||
|
// models.sessions.infinispan.changes.sessions package
|
||||||
|
LastSessionRefreshEvent.class,
|
||||||
|
SessionData.class,
|
||||||
|
|
||||||
|
// models.cache.infinispan.authorization.stream package
|
||||||
|
InResourcePredicate.class,
|
||||||
|
InResourceServerPredicate.class,
|
||||||
|
InScopePredicate.class,
|
||||||
|
|
||||||
|
// models.sessions.infinispan.events package
|
||||||
|
RealmRemovedSessionEvent.class,
|
||||||
|
RemoveAllUserLoginFailuresEvent.class,
|
||||||
|
RemoveUserSessionsEvent.class,
|
||||||
|
|
||||||
|
// models.sessions.infinispan.stream package
|
||||||
|
SessionPredicate.class,
|
||||||
|
SessionWrapperPredicate.class,
|
||||||
|
UserSessionPredicate.class,
|
||||||
|
|
||||||
|
// models.cache.infinispan.stream package
|
||||||
|
GroupListPredicate.class,
|
||||||
|
HasRolePredicate.class,
|
||||||
|
InClientPredicate.class,
|
||||||
|
InGroupPredicate.class,
|
||||||
|
InIdentityProviderPredicate.class,
|
||||||
|
InRealmPredicate.class,
|
||||||
|
|
||||||
|
// models.cache.infinispan.events package
|
||||||
|
AuthenticationSessionAuthNoteUpdateEvent.class,
|
||||||
|
ClientAddedEvent.class,
|
||||||
|
ClientUpdatedEvent.class,
|
||||||
|
ClientRemovedEvent.class,
|
||||||
|
ClientScopeAddedEvent.class,
|
||||||
|
ClientScopeRemovedEvent.class,
|
||||||
|
GroupAddedEvent.class,
|
||||||
|
GroupMovedEvent.class,
|
||||||
|
GroupRemovedEvent.class,
|
||||||
|
GroupUpdatedEvent.class,
|
||||||
|
RealmUpdatedEvent.class,
|
||||||
|
RealmRemovedEvent.class,
|
||||||
|
RoleAddedEvent.class,
|
||||||
|
RoleUpdatedEvent.class,
|
||||||
|
RoleRemovedEvent.class,
|
||||||
|
UserCacheRealmInvalidationEvent.class,
|
||||||
|
UserConsentsUpdatedEvent.class,
|
||||||
|
UserFederationLinkRemovedEvent.class,
|
||||||
|
UserFederationLinkUpdatedEvent.class,
|
||||||
|
UserFullInvalidationEvent.class,
|
||||||
|
UserUpdatedEvent.class,
|
||||||
|
|
||||||
|
|
||||||
|
// sessions.infinispan.entities package
|
||||||
|
AuthenticatedClientSessionStore.class,
|
||||||
|
AuthenticatedClientSessionEntity.class,
|
||||||
|
AuthenticationSessionEntity.class,
|
||||||
|
LoginFailureEntity.class,
|
||||||
|
LoginFailureKey.class,
|
||||||
|
RootAuthenticationSessionEntity.class,
|
||||||
|
SingleUseObjectValueEntity.class,
|
||||||
|
UserSessionEntity.class,
|
||||||
|
ReplaceFunction.class
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public interface KeycloakModelSchema extends GeneratedSchema {
|
||||||
|
|
||||||
|
KeycloakModelSchema INSTANCE = new KeycloakModelSchemaImpl();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,25 +1,155 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
package org.keycloak.marshalling;
|
package org.keycloak.marshalling;
|
||||||
|
|
||||||
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
|
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
|
||||||
import org.infinispan.jboss.marshalling.core.JBossUserMarshaller;
|
|
||||||
import org.keycloak.models.sessions.infinispan.changes.ReplaceFunction;
|
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
/**
|
||||||
|
* Ids of the protostream type.
|
||||||
|
* <p>
|
||||||
|
* Read careful the following warning to ensure compatibility when updating schemas.
|
||||||
|
* <p>
|
||||||
|
* WARNING! IDs lower or equal than 65535 are reserved for internal Inifinispan classes and cannot be used.
|
||||||
|
* WARNING! ID defined in this class must be unique. If one type is removed, its ID must not be reused. You have been
|
||||||
|
* warned! The ID identifies the message, and it is stored and used to save space.
|
||||||
|
* WARNING! The field IDs cannot be reused as well for the same reason.
|
||||||
|
* WARNING! Primitive types cannot be null in proto3 syntax (Integer, String). Take that in consideration.
|
||||||
|
* <p>
|
||||||
|
* Be Aware of the following default in Proto3 syntax!
|
||||||
|
* For strings, the default value is the empty string.
|
||||||
|
* For bytes, the default value is empty bytes.
|
||||||
|
* For bools, the default value is false.
|
||||||
|
* For numeric types, the default value is zero.
|
||||||
|
* For enums, the default value is the first defined enum value, which must be 0.
|
||||||
|
* For message fields, the field is not set. (null)
|
||||||
|
* <p>
|
||||||
|
* Docs: <a href="https://protobuf.dev/programming-guides/proto3/">Language Guide (proto 3)</a>
|
||||||
|
*/
|
||||||
public final class Marshalling {
|
public final class Marshalling {
|
||||||
|
|
||||||
private Marshalling() {
|
private Marshalling() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: Min ID is 2500
|
// Model
|
||||||
public static final Integer REPLACE_FUNCTION_ID = 2500;
|
// see org.keycloak.models.UserSessionModel.State
|
||||||
|
public static final int USER_STATE_ENUM = 65536;
|
||||||
|
// see org.keycloak.sessions.CommonClientSessionModel.ExecutionStatus
|
||||||
|
public static final int CLIENT_SESSION_EXECUTION_STATUS = 65537;
|
||||||
|
// see org.keycloak.component.ComponentModel.MultiMapEntry
|
||||||
|
public static final int MULTIMAP_ENTRY = 65538;
|
||||||
|
// see org.keycloak.storage.UserStorageProviderModel
|
||||||
|
public static final int USER_STORAGE_PROVIDER_MODES = 65539;
|
||||||
|
// see org.keycloak.storage.managers.UserStorageSyncManager.UserStorageProviderClusterEvent
|
||||||
|
public static final int USER_STORAGE_PROVIDER_CLUSTER_EVENT = 65540;
|
||||||
|
|
||||||
|
// clustering.infinispan package
|
||||||
|
public static final int LOCK_ENTRY = 65541;
|
||||||
|
public static final int LOCK_ENTRY_PREDICATE = 65542;
|
||||||
|
public static final int WRAPPED_CLUSTER_EVENT = 65543;
|
||||||
|
public static final int WRAPPED_CLUSTER_EVENT_SITE_FILTER = 65544;
|
||||||
|
|
||||||
|
// keys.infinispan package
|
||||||
|
public static final int PUBLIC_KEY_INVALIDATION_EVENT = 65545;
|
||||||
|
|
||||||
|
//models.cache.infinispan.authorization.events package
|
||||||
|
public static final int POLICY_UPDATED_EVENT = 65546;
|
||||||
|
public static final int POLICY_REMOVED_EVENT = 65547;
|
||||||
|
public static final int RESOURCE_UPDATED_EVENT = 65548;
|
||||||
|
public static final int RESOURCE_REMOVED_EVENT = 65549;
|
||||||
|
public static final int RESOURCE_SERVER_UPDATED_EVENT = 65550;
|
||||||
|
public static final int RESOURCE_SERVER_REMOVED_EVENT = 65551;
|
||||||
|
public static final int SCOPE_UPDATED_EVENT = 65552;
|
||||||
|
public static final int SCOPE_REMOVED_EVENT = 65553;
|
||||||
|
|
||||||
|
// models.sessions.infinispan.initializer package
|
||||||
|
public static final int INITIALIZER_STATE = 65554;
|
||||||
|
|
||||||
|
// models.sessions.infinispan.changes package
|
||||||
|
public static final int SESSION_ENTITY_WRAPPER = 65555;
|
||||||
|
public static final int REPLACE_FUNCTION = 65656;
|
||||||
|
|
||||||
|
// models.sessions.infinispan.changes.sessions package
|
||||||
|
public static final int LAST_SESSION_REFRESH_EVENT = 65557;
|
||||||
|
public static final int SESSION_DATA = 65558;
|
||||||
|
|
||||||
|
// models.cache.infinispan.authorization.stream package
|
||||||
|
public static final int IN_RESOURCE_PREDICATE = 65559;
|
||||||
|
public static final int IN_RESOURCE_SERVER_PREDICATE = 65560;
|
||||||
|
public static final int IN_SCOPE_PREDICATE = 65561;
|
||||||
|
|
||||||
|
// models.sessions.infinispan.events package
|
||||||
|
public static final int REALM_REMOVED_SESSION_EVENT = 65562;
|
||||||
|
public static final int REMOVE_ALL_USER_LOGIN_FAILURES_EVENT = 65563;
|
||||||
|
public static final int REMOVE_ALL_USER_SESSIONS_EVENT = 65564;
|
||||||
|
|
||||||
|
// models.sessions.infinispan.stream package
|
||||||
|
public static final int SESSION_PREDICATE = 65565;
|
||||||
|
public static final int SESSION_WRAPPER_PREDICATE = 65566;
|
||||||
|
public static final int USER_SESSION_PREDICATE = 65567;
|
||||||
|
|
||||||
|
// models.cache.infinispan.stream package
|
||||||
|
public static final int GROUP_LIST_PREDICATE = 65568;
|
||||||
|
public static final int HAS_ROLE_PREDICATE = 65569;
|
||||||
|
public static final int IN_CLIENT_PREDICATE = 65570;
|
||||||
|
public static final int IN_GROUP_PREDICATE = 65571;
|
||||||
|
public static final int IN_IDENTITY_PROVIDER_PREDICATE = 65572;
|
||||||
|
public static final int IN_REALM_PREDICATE = 65573;
|
||||||
|
|
||||||
|
// models.cache.infinispan.events package
|
||||||
|
public static final int AUTHENTICATION_SESSION_AUTH_NOTE_UPDATE_EVENT = 65574;
|
||||||
|
public static final int CLIENT_ADDED_EVENT = 65575;
|
||||||
|
public static final int CLIENT_UPDATED_EVENT = 65576;
|
||||||
|
public static final int CLIENT_REMOVED_EVENT = 65577;
|
||||||
|
public static final int CLIENT_SCOPE_ADDED_EVENT = 65578;
|
||||||
|
public static final int CLIENT_SCOPE_REMOVED_EVENT = 65579;
|
||||||
|
public static final int GROUP_ADDED_EVENT = 65580;
|
||||||
|
public static final int GROUP_MOVED_EVENT = 65581;
|
||||||
|
public static final int GROUP_REMOVED_EVENT = 65582;
|
||||||
|
public static final int GROUP_UPDATED_EVENT = 65583;
|
||||||
|
public static final int REALM_UPDATED_EVENT = 65584;
|
||||||
|
public static final int REALM_REMOVED_EVENT = 65585;
|
||||||
|
public static final int ROLE_ADDED_EVENT = 65586;
|
||||||
|
public static final int ROLE_UPDATED_EVENT = 65587;
|
||||||
|
public static final int ROLE_REMOVED_EVENT = 65588;
|
||||||
|
public static final int USER_CACHE_REALM_INVALIDATION_EVENT = 65589;
|
||||||
|
public static final int USER_CONSENTS_UPDATED_EVENT = 65590;
|
||||||
|
public static final int USER_FEDERATION_LINK_REMOVED_EVENT = 65591;
|
||||||
|
public static final int USER_FEDERATION_LINK_UPDATED_EVENT = 65592;
|
||||||
|
public static final int USER_FULL_INVALIDATION_EVENT = 65593;
|
||||||
|
public static final int USER_UPDATED_EVENT = 65594;
|
||||||
|
|
||||||
|
// sessions.infinispan.entities package
|
||||||
|
public static final int AUTHENTICATED_CLIENT_SESSION_STORE = 65595;
|
||||||
|
public static final int AUTHENTICATED_CLIENT_SESSION_ENTITY = 65596;
|
||||||
|
public static final int AUTHENTICATION_SESSION_ENTITY = 65597;
|
||||||
|
public static final int LOGIN_FAILURE_ENTITY = 65598;
|
||||||
|
public static final int LOGIN_FAILURE_KEY = 65599;
|
||||||
|
public static final int ROOT_AUTHENTICATION_SESSION_ENTITY = 65600;
|
||||||
|
public static final int SINGLE_USE_OBJECT_VALUE_ENTITY = 65601;
|
||||||
|
public static final int USER_SESSION_ENTITY = 65602;
|
||||||
|
|
||||||
// For Infinispan 10, we go with the JBoss marshalling.
|
|
||||||
// TODO: This should be replaced later with the marshalling recommended by infinispan. Probably protostream.
|
|
||||||
// See https://infinispan.org/docs/stable/titles/developing/developing.html#marshalling for the details
|
|
||||||
public static void configure(GlobalConfigurationBuilder builder) {
|
public static void configure(GlobalConfigurationBuilder builder) {
|
||||||
builder.serialization()
|
builder.serialization()
|
||||||
.marshaller(new JBossUserMarshaller())
|
.addContextInitializer(KeycloakModelSchema.INSTANCE);
|
||||||
.addAdvancedExternalizer(ReplaceFunction.INSTANCE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String emptyStringToNull(String value) {
|
||||||
|
return value == null || value.isEmpty() ? null : value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,27 +17,73 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan;
|
package org.keycloak.models.cache.infinispan;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.client.clienttype.ClientTypeManager;
|
import org.keycloak.client.clienttype.ClientTypeManager;
|
||||||
import org.keycloak.cluster.ClusterProvider;
|
import org.keycloak.cluster.ClusterProvider;
|
||||||
import org.keycloak.common.Profile;
|
import org.keycloak.common.Profile;
|
||||||
import org.keycloak.component.ComponentModel;
|
import org.keycloak.component.ComponentModel;
|
||||||
import org.keycloak.models.*;
|
import org.keycloak.models.ClientInitialAccessModel;
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.ClientProvider;
|
||||||
|
import org.keycloak.models.ClientScopeModel;
|
||||||
|
import org.keycloak.models.ClientScopeProvider;
|
||||||
|
import org.keycloak.models.GroupModel;
|
||||||
|
import org.keycloak.models.GroupProvider;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakTransaction;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RealmProvider;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.RoleProvider;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.cache.CacheRealmProvider;
|
import org.keycloak.models.cache.CacheRealmProvider;
|
||||||
import org.keycloak.models.cache.CachedRealmModel;
|
import org.keycloak.models.cache.CachedRealmModel;
|
||||||
import org.keycloak.models.cache.infinispan.entities.*;
|
import org.keycloak.models.cache.infinispan.entities.CachedClient;
|
||||||
import org.keycloak.models.cache.infinispan.events.*;
|
import org.keycloak.models.cache.infinispan.entities.CachedClientRole;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.CachedClientScope;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.CachedGroup;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.CachedRealm;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.CachedRealmRole;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.CachedRole;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.ClientListQuery;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.ClientScopeListQuery;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.GroupListQuery;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.GroupNameQuery;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.RealmListQuery;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.RoleListQuery;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.ClientAddedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.ClientRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.ClientScopeAddedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.ClientScopeRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.ClientUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.GroupAddedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.GroupMovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.GroupRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.GroupUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.RealmRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.RealmUpdatedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.RoleAddedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.RoleRemovedEvent;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.RoleUpdatedEvent;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
import org.keycloak.storage.DatastoreProvider;
|
import org.keycloak.storage.DatastoreProvider;
|
||||||
import org.keycloak.storage.StoreManagers;
|
|
||||||
import org.keycloak.storage.StorageId;
|
import org.keycloak.storage.StorageId;
|
||||||
|
import org.keycloak.storage.StoreManagers;
|
||||||
import org.keycloak.storage.client.ClientStorageProviderModel;
|
import org.keycloak.storage.client.ClientStorageProviderModel;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* - the high level architecture of this cache is an invalidation cache.
|
* - the high level architecture of this cache is an invalidation cache.
|
||||||
|
@ -221,7 +267,6 @@ public class RealmCacheSession implements CacheRealmProvider {
|
||||||
public void registerClientScopeInvalidation(String id, String realmId) {
|
public void registerClientScopeInvalidation(String id, String realmId) {
|
||||||
invalidateClientScope(id);
|
invalidateClientScope(id);
|
||||||
cache.clientScopeUpdated(realmId, invalidations);
|
cache.clientScopeUpdated(realmId, invalidations);
|
||||||
invalidationEvents.add(ClientTemplateEvent.create(id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void invalidateClientScope(String id) {
|
private void invalidateClientScope(String id) {
|
||||||
|
@ -561,7 +606,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
||||||
// this is needed so that a client that hasn't been committed isn't cached in a query
|
// this is needed so that a client that hasn't been committed isn't cached in a query
|
||||||
listInvalidations.add(realm.getId());
|
listInvalidations.add(realm.getId());
|
||||||
|
|
||||||
invalidationEvents.add(ClientAddedEvent.create(client.getId(), client.getClientId(), realm.getId()));
|
invalidationEvents.add(ClientAddedEvent.create(client.getId(), realm.getId()));
|
||||||
cache.clientAdded(realm.getId(), invalidations);
|
cache.clientAdded(realm.getId(), invalidations);
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class StoreFactoryCacheManager extends CacheManager {
|
||||||
public void resourceServerRemoval(String id, Set<String> invalidations) {
|
public void resourceServerRemoval(String id, Set<String> invalidations) {
|
||||||
resourceServerUpdated(id, invalidations);
|
resourceServerUpdated(id, invalidations);
|
||||||
|
|
||||||
addInvalidations(InResourceServerPredicate.create().resourceServer(id), invalidations);
|
addInvalidations(InResourceServerPredicate.create(id), invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void scopeUpdated(String id, String name, String serverId, Set<String> invalidations) {
|
public void scopeUpdated(String id, String name, String serverId, Set<String> invalidations) {
|
||||||
|
@ -74,7 +74,7 @@ public class StoreFactoryCacheManager extends CacheManager {
|
||||||
|
|
||||||
public void scopeRemoval(String id, String name, String serverId, Set<String> invalidations) {
|
public void scopeRemoval(String id, String name, String serverId, Set<String> invalidations) {
|
||||||
scopeUpdated(id, name, serverId, invalidations);
|
scopeUpdated(id, name, serverId, invalidations);
|
||||||
addInvalidations(InScopePredicate.create().scope(id), invalidations);
|
addInvalidations(InScopePredicate.create(id), invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resourceUpdated(String id, String name, String type, Set<String> uris, Set<String> scopes, String serverId, String owner, Set<String> invalidations) {
|
public void resourceUpdated(String id, String name, String type, Set<String> uris, Set<String> scopes, String serverId, String owner, Set<String> invalidations) {
|
||||||
|
@ -83,14 +83,14 @@ public class StoreFactoryCacheManager extends CacheManager {
|
||||||
invalidations.add(StoreFactoryCacheSession.getResourceByOwnerCacheKey(owner, serverId));
|
invalidations.add(StoreFactoryCacheSession.getResourceByOwnerCacheKey(owner, serverId));
|
||||||
invalidations.add(StoreFactoryCacheSession.getResourceByOwnerCacheKey(owner, null));
|
invalidations.add(StoreFactoryCacheSession.getResourceByOwnerCacheKey(owner, null));
|
||||||
invalidations.add(StoreFactoryCacheSession.getPermissionTicketByResource(id, serverId));
|
invalidations.add(StoreFactoryCacheSession.getPermissionTicketByResource(id, serverId));
|
||||||
addInvalidations(InResourcePredicate.create().resource(name), invalidations);
|
addInvalidations(InResourcePredicate.create(name), invalidations);
|
||||||
|
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
invalidations.add(StoreFactoryCacheSession.getResourceByTypeCacheKey(type, serverId));
|
invalidations.add(StoreFactoryCacheSession.getResourceByTypeCacheKey(type, serverId));
|
||||||
invalidations.add(StoreFactoryCacheSession.getResourceByTypeCacheKey(type, owner, serverId));
|
invalidations.add(StoreFactoryCacheSession.getResourceByTypeCacheKey(type, owner, serverId));
|
||||||
invalidations.add(StoreFactoryCacheSession.getResourceByTypeCacheKey(type, null, serverId));
|
invalidations.add(StoreFactoryCacheSession.getResourceByTypeCacheKey(type, null, serverId));
|
||||||
invalidations.add(StoreFactoryCacheSession.getResourceByTypeInstanceCacheKey(type, serverId));
|
invalidations.add(StoreFactoryCacheSession.getResourceByTypeInstanceCacheKey(type, serverId));
|
||||||
addInvalidations(InResourcePredicate.create().resource(type), invalidations);
|
addInvalidations(InResourcePredicate.create(type), invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uris != null) {
|
if (uris != null) {
|
||||||
|
@ -102,14 +102,14 @@ public class StoreFactoryCacheManager extends CacheManager {
|
||||||
if (scopes != null) {
|
if (scopes != null) {
|
||||||
for (String scope : scopes) {
|
for (String scope : scopes) {
|
||||||
invalidations.add(StoreFactoryCacheSession.getResourceByScopeCacheKey(scope, serverId));
|
invalidations.add(StoreFactoryCacheSession.getResourceByScopeCacheKey(scope, serverId));
|
||||||
addInvalidations(InScopePredicate.create().scope(scope), invalidations);
|
addInvalidations(InScopePredicate.create(scope), invalidations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resourceRemoval(String id, String name, String type, Set<String> uris, String owner, Set<String> scopes, String serverId, Set<String> invalidations) {
|
public void resourceRemoval(String id, String name, String type, Set<String> uris, String owner, Set<String> scopes, String serverId, Set<String> invalidations) {
|
||||||
resourceUpdated(id, name, type, uris, scopes, serverId, owner, invalidations);
|
resourceUpdated(id, name, type, uris, scopes, serverId, owner, invalidations);
|
||||||
addInvalidations(InResourcePredicate.create().resource(id), invalidations);
|
addInvalidations(InResourcePredicate.create(id), invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void policyUpdated(String id, String name, Set<String> resources, Set<String> resourceTypes, Set<String> scopes, String serverId, Set<String> invalidations) {
|
public void policyUpdated(String id, String name, Set<String> resources, Set<String> resourceTypes, Set<String> scopes, String serverId, Set<String> invalidations) {
|
||||||
|
|
|
@ -270,7 +270,7 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
|
||||||
ResourceAdapter adapter = managedResources.get(id);
|
ResourceAdapter adapter = managedResources.get(id);
|
||||||
if (adapter != null) adapter.invalidateFlag();
|
if (adapter != null) adapter.invalidateFlag();
|
||||||
|
|
||||||
invalidationEvents.add(ResourceUpdatedEvent.create(id, name, type, uris, scopes, serverId, owner));
|
invalidationEvents.add(ResourceUpdatedEvent.create(id, name, type, uris, owner, scopes, serverId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerPolicyInvalidation(String id, String name, Set<String> resources, Set<String> scopes, String defaultResourceType, String serverId) {
|
public void registerPolicyInvalidation(String id, String name, Set<String> resources, Set<String> scopes, String defaultResourceType, String serverId) {
|
||||||
|
@ -443,7 +443,7 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
|
||||||
if (server == null) return;
|
if (server == null) return;
|
||||||
|
|
||||||
cache.invalidateObject(id);
|
cache.invalidateObject(id);
|
||||||
invalidationEvents.add(ResourceServerRemovedEvent.create(id, server.getId()));
|
invalidationEvents.add(ResourceServerRemovedEvent.create(id));
|
||||||
cache.resourceServerRemoval(id, invalidations);
|
cache.resourceServerRemoval(id, invalidations);
|
||||||
getResourceServerStoreDelegate().delete(client);
|
getResourceServerStoreDelegate().delete(client);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
|
||||||
|
abstract class BasePolicyEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
|
final String name;
|
||||||
|
@ProtoField(value = 3, collectionImplementation = HashSet.class)
|
||||||
|
final Set<String> resources;
|
||||||
|
@ProtoField(value = 4, collectionImplementation = HashSet.class)
|
||||||
|
final Set<String> resourceTypes;
|
||||||
|
@ProtoField(value = 5, collectionImplementation = HashSet.class)
|
||||||
|
final Set<String> scopes;
|
||||||
|
@ProtoField(6)
|
||||||
|
final String serverId;
|
||||||
|
|
||||||
|
BasePolicyEvent(String id, String name, Set<String> resources, Set<String> resourceTypes, Set<String> scopes, String serverId) {
|
||||||
|
super(id);
|
||||||
|
this.name = Objects.requireNonNull(name);
|
||||||
|
this.resources = resources;
|
||||||
|
this.resourceTypes = resourceTypes;
|
||||||
|
this.scopes = scopes;
|
||||||
|
this.serverId = Objects.requireNonNull(serverId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
BasePolicyEvent that = (BasePolicyEvent) o;
|
||||||
|
return name.equals(that.name) &&
|
||||||
|
Objects.equals(resources, that.resources) &&
|
||||||
|
Objects.equals(resourceTypes, that.resourceTypes) &&
|
||||||
|
Objects.equals(scopes, that.scopes) &&
|
||||||
|
serverId.equals(that.serverId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + name.hashCode();
|
||||||
|
result = 31 * result + Objects.hashCode(resources);
|
||||||
|
result = 31 * result + Objects.hashCode(resourceTypes);
|
||||||
|
result = 31 * result + Objects.hashCode(scopes);
|
||||||
|
result = 31 * result + serverId.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s [id=%s, name=%s]", getClass().getSimpleName(), getId(), name);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
|
||||||
|
abstract class BaseResourceEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
|
final String name;
|
||||||
|
@ProtoField(3)
|
||||||
|
final String owner;
|
||||||
|
@ProtoField(4)
|
||||||
|
final String serverId;
|
||||||
|
@ProtoField(5)
|
||||||
|
final String type;
|
||||||
|
@ProtoField(value = 6, collectionImplementation = HashSet.class)
|
||||||
|
final Set<String> uris;
|
||||||
|
@ProtoField(value = 7, collectionImplementation = HashSet.class)
|
||||||
|
final Set<String> scopes;
|
||||||
|
|
||||||
|
BaseResourceEvent(String id, String name, String owner, String serverId, String type, Set<String> uris, Set<String> scopes) {
|
||||||
|
super(id);
|
||||||
|
this.name = Objects.requireNonNull(name);
|
||||||
|
this.owner = Objects.requireNonNull(owner);
|
||||||
|
this.serverId = Objects.requireNonNull(serverId);
|
||||||
|
this.type = type;
|
||||||
|
this.uris = uris;
|
||||||
|
this.scopes = scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
BaseResourceEvent that = (BaseResourceEvent) o;
|
||||||
|
return name.equals(that.name) &&
|
||||||
|
owner.equals(that.owner) &&
|
||||||
|
serverId.equals(that.serverId) &&
|
||||||
|
Objects.equals(type, that.type) &&
|
||||||
|
Objects.equals(uris, that.uris) &&
|
||||||
|
Objects.equals(scopes, that.scopes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + name.hashCode();
|
||||||
|
result = 31 * result + owner.hashCode();
|
||||||
|
result = 31 * result + serverId.hashCode();
|
||||||
|
result = 31 * result + Objects.hashCode(type);
|
||||||
|
result = 31 * result + Objects.hashCode(uris);
|
||||||
|
result = 31 * result + Objects.hashCode(scopes);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s [ id=%s, name=%s]", getClass().getSimpleName(), getId(), name);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
|
||||||
|
abstract class BaseResourceServerEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
||||||
|
|
||||||
|
BaseResourceServerEvent(String id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s [ id=%s ]", getClass().getSimpleName(), getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
|
|
||||||
|
abstract class BaseScopeEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
|
final String name;
|
||||||
|
@ProtoField(3)
|
||||||
|
final String serverId;
|
||||||
|
|
||||||
|
BaseScopeEvent(String id, String name, String serverId) {
|
||||||
|
super(id);
|
||||||
|
this.name = Objects.requireNonNull(name);
|
||||||
|
this.serverId = Objects.requireNonNull(serverId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
BaseScopeEvent that = (BaseScopeEvent) o;
|
||||||
|
return name.equals(that.name) &&
|
||||||
|
serverId.equals(that.serverId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + name.hashCode();
|
||||||
|
result = 31 * result + serverId.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s [ id=%s, name=%s ]", getClass(), getId(), name);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,6 @@ import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
*/
|
*/
|
||||||
public class PermissionTicketRemovedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
public class PermissionTicketRemovedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
||||||
|
|
||||||
private String id;
|
|
||||||
private String owner;
|
private String owner;
|
||||||
private String resource;
|
private String resource;
|
||||||
private String scope;
|
private String scope;
|
||||||
|
@ -36,9 +35,12 @@ public class PermissionTicketRemovedEvent extends InvalidationEvent implements A
|
||||||
private String requester;
|
private String requester;
|
||||||
private String resourceName;
|
private String resourceName;
|
||||||
|
|
||||||
|
private PermissionTicketRemovedEvent(String id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
public static PermissionTicketRemovedEvent create(String id, String owner, String requester, String resource, String resourceName, String scope, String serverId) {
|
public static PermissionTicketRemovedEvent create(String id, String owner, String requester, String resource, String resourceName, String scope, String serverId) {
|
||||||
PermissionTicketRemovedEvent event = new PermissionTicketRemovedEvent();
|
PermissionTicketRemovedEvent event = new PermissionTicketRemovedEvent(id);
|
||||||
event.id = id;
|
|
||||||
event.owner = owner;
|
event.owner = owner;
|
||||||
event.requester = requester;
|
event.requester = requester;
|
||||||
event.resource = resource;
|
event.resource = resource;
|
||||||
|
@ -48,32 +50,27 @@ public class PermissionTicketRemovedEvent extends InvalidationEvent implements A
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
if (!super.equals(o)) return false;
|
if (!super.equals(o)) return false;
|
||||||
PermissionTicketRemovedEvent that = (PermissionTicketRemovedEvent) o;
|
PermissionTicketRemovedEvent that = (PermissionTicketRemovedEvent) o;
|
||||||
return Objects.equals(id, that.id) && Objects.equals(resource, that.resource) && Objects.equals(serverId, that.serverId);
|
return Objects.equals(resource, that.resource) && Objects.equals(serverId, that.serverId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(super.hashCode(), id, resource, serverId);
|
return Objects.hash(super.hashCode(), resource, serverId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("PermissionTicketRemovedEvent [ id=%s, name=%s]", id, resource);
|
return String.format("PermissionTicketRemovedEvent [ id=%s, name=%s]", getId(), resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
cache.permissionTicketRemoval(id, owner, requester, resource, resourceName, scope, serverId, invalidations);
|
cache.permissionTicketRemoval(getId(), owner, requester, resource, resourceName, scope, serverId, invalidations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||||
*/
|
*/
|
||||||
public class PermissionTicketUpdatedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
public class PermissionTicketUpdatedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
||||||
|
|
||||||
private String id;
|
|
||||||
private String owner;
|
private String owner;
|
||||||
private String resource;
|
private String resource;
|
||||||
private String scope;
|
private String scope;
|
||||||
|
@ -36,9 +35,12 @@ public class PermissionTicketUpdatedEvent extends InvalidationEvent implements A
|
||||||
private String requester;
|
private String requester;
|
||||||
private String resourceName;
|
private String resourceName;
|
||||||
|
|
||||||
|
private PermissionTicketUpdatedEvent(String id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
public static PermissionTicketUpdatedEvent create(String id, String owner, String requester, String resource, String resourceName, String scope, String serverId) {
|
public static PermissionTicketUpdatedEvent create(String id, String owner, String requester, String resource, String resourceName, String scope, String serverId) {
|
||||||
PermissionTicketUpdatedEvent event = new PermissionTicketUpdatedEvent();
|
PermissionTicketUpdatedEvent event = new PermissionTicketUpdatedEvent(id);
|
||||||
event.id = id;
|
|
||||||
event.owner = owner;
|
event.owner = owner;
|
||||||
event.requester = requester;
|
event.requester = requester;
|
||||||
event.resource = resource;
|
event.resource = resource;
|
||||||
|
@ -48,34 +50,27 @@ public class PermissionTicketUpdatedEvent extends InvalidationEvent implements A
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
if (!super.equals(o)) return false;
|
if (!super.equals(o)) return false;
|
||||||
PermissionTicketUpdatedEvent that = (PermissionTicketUpdatedEvent) o;
|
PermissionTicketUpdatedEvent that = (PermissionTicketUpdatedEvent) o;
|
||||||
return Objects.equals(id, that.id) && Objects.equals(resource, that.resource) && Objects.equals(serverId, that.serverId);
|
return Objects.equals(resource, that.resource) && Objects.equals(serverId, that.serverId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(super.hashCode(), id, resource, serverId);
|
return Objects.hash(super.hashCode(), resource, serverId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("PermissionTicketUpdatedEvent [ id=%s, name=%s]", id, resource);
|
return String.format("PermissionTicketUpdatedEvent [ id=%s, name=%s]", getId(), resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
cache.permissionTicketUpdated(id, owner, requester, resource, resourceName, scope, serverId, invalidations);
|
cache.permissionTicketUpdated(getId(), owner, requester, resource, resourceName, scope, serverId, invalidations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,109 +17,30 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.authorization.events;
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.KeycloakMarshallUtil;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(PolicyRemovedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.POLICY_REMOVED_EVENT)
|
||||||
public class PolicyRemovedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
public class PolicyRemovedEvent extends BasePolicyEvent {
|
||||||
|
|
||||||
private String id;
|
@ProtoFactory
|
||||||
private String name;
|
PolicyRemovedEvent(String id, String name, Set<String> resources, Set<String> resourceTypes, Set<String> scopes, String serverId) {
|
||||||
private Set<String> resources;
|
super(id, name, resources, resourceTypes, scopes, serverId);
|
||||||
private Set<String> resourceTypes;
|
}
|
||||||
private Set<String> scopes;
|
|
||||||
private String serverId;
|
|
||||||
|
|
||||||
public static PolicyRemovedEvent create(String id, String name, Set<String> resources, Set<String> resourceTypes, Set<String> scopes, String serverId) {
|
public static PolicyRemovedEvent create(String id, String name, Set<String> resources, Set<String> resourceTypes, Set<String> scopes, String serverId) {
|
||||||
PolicyRemovedEvent event = new PolicyRemovedEvent();
|
return new PolicyRemovedEvent(id, name, resources, resourceTypes, scopes, serverId);
|
||||||
event.id = id;
|
|
||||||
event.name = name;
|
|
||||||
event.resources = resources;
|
|
||||||
event.resourceTypes = resourceTypes;
|
|
||||||
event.scopes = scopes;
|
|
||||||
event.serverId = serverId;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
PolicyRemovedEvent that = (PolicyRemovedEvent) o;
|
|
||||||
return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(serverId, that.serverId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), id, name, serverId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("PolicyRemovedEvent [ id=%s, name=%s]", id, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
cache.policyRemoval(id, name, resources, resourceTypes, scopes, serverId, invalidations);
|
cache.policyRemoval(getId(), name, resources, resourceTypes, scopes, serverId, invalidations);
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<PolicyRemovedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, PolicyRemovedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.id, output);
|
|
||||||
MarshallUtil.marshallString(obj.name, output);
|
|
||||||
KeycloakMarshallUtil.writeCollection(obj.scopes, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
KeycloakMarshallUtil.writeCollection(obj.resources, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
KeycloakMarshallUtil.writeCollection(obj.resourceTypes, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
MarshallUtil.marshallString(obj.serverId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PolicyRemovedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PolicyRemovedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
PolicyRemovedEvent res = new PolicyRemovedEvent();
|
|
||||||
res.id = MarshallUtil.unmarshallString(input);
|
|
||||||
res.name = MarshallUtil.unmarshallString(input);
|
|
||||||
res.scopes = KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, HashSet::new);
|
|
||||||
res.resources = KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, HashSet::new);
|
|
||||||
res.resourceTypes = KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, HashSet::new);
|
|
||||||
res.serverId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,109 +17,30 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.authorization.events;
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
|
||||||
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
|
||||||
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.KeycloakMarshallUtil;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(PolicyUpdatedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.POLICY_UPDATED_EVENT)
|
||||||
public class PolicyUpdatedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
public class PolicyUpdatedEvent extends BasePolicyEvent {
|
||||||
|
|
||||||
private String id;
|
@ProtoFactory
|
||||||
private String name;
|
PolicyUpdatedEvent(String id, String name, Set<String> resources, Set<String> resourceTypes, Set<String> scopes, String serverId) {
|
||||||
private Set<String> resources;
|
super(id, name, resources, resourceTypes, scopes, serverId);
|
||||||
private Set<String> resourceTypes;
|
}
|
||||||
private Set<String> scopes;
|
|
||||||
private String serverId;
|
|
||||||
|
|
||||||
public static PolicyUpdatedEvent create(String id, String name, Set<String> resources, Set<String> resourceTypes, Set<String> scopes, String serverId) {
|
public static PolicyUpdatedEvent create(String id, String name, Set<String> resources, Set<String> resourceTypes, Set<String> scopes, String serverId) {
|
||||||
PolicyUpdatedEvent event = new PolicyUpdatedEvent();
|
return new PolicyUpdatedEvent(id, name, resources, resourceTypes, scopes, serverId);
|
||||||
event.id = id;
|
|
||||||
event.name = name;
|
|
||||||
event.resources = resources;
|
|
||||||
event.resourceTypes = resourceTypes;
|
|
||||||
event.scopes = scopes;
|
|
||||||
event.serverId = serverId;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
PolicyUpdatedEvent that = (PolicyUpdatedEvent) o;
|
|
||||||
return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(serverId, that.serverId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), id, name, serverId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("PolicyUpdatedEvent [ id=%s, name=%s ]", id, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
cache.policyUpdated(id, name, resources, resourceTypes, scopes, serverId, invalidations);
|
cache.policyUpdated(getId(), name, resources, resourceTypes, scopes, serverId, invalidations);
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<PolicyUpdatedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, PolicyUpdatedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.id, output);
|
|
||||||
MarshallUtil.marshallString(obj.name, output);
|
|
||||||
KeycloakMarshallUtil.writeCollection(obj.resources, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
KeycloakMarshallUtil.writeCollection(obj.resourceTypes, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
KeycloakMarshallUtil.writeCollection(obj.scopes, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
MarshallUtil.marshallString(obj.serverId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PolicyUpdatedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PolicyUpdatedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
PolicyUpdatedEvent res = new PolicyUpdatedEvent();
|
|
||||||
res.id = MarshallUtil.unmarshallString(input);
|
|
||||||
res.name = MarshallUtil.unmarshallString(input);
|
|
||||||
res.resources = KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, HashSet::new);
|
|
||||||
res.resourceTypes = KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, HashSet::new);
|
|
||||||
res.scopes = KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, HashSet::new);
|
|
||||||
res.serverId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,113 +17,34 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.authorization.events;
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
|
||||||
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
|
||||||
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.KeycloakMarshallUtil;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(ResourceRemovedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.RESOURCE_REMOVED_EVENT)
|
||||||
public class ResourceRemovedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
public class ResourceRemovedEvent extends BaseResourceEvent {
|
||||||
|
|
||||||
private String id;
|
@ProtoFactory
|
||||||
private String name;
|
static ResourceRemovedEvent protoFactory(String id, String name, String owner, String serverId, String type, Set<String> uris, Set<String> scopes) {
|
||||||
private String owner;
|
return new ResourceRemovedEvent(id, name, owner, serverId, Marshalling.emptyStringToNull(type), uris, scopes);
|
||||||
private String serverId;
|
}
|
||||||
private String type;
|
|
||||||
private Set<String> uris;
|
private ResourceRemovedEvent(String id, String name, String owner, String serverId, String type, Set<String> uris, Set<String> scopes) {
|
||||||
private Set<String> scopes;
|
super(id, name, owner, serverId, type, uris, scopes);
|
||||||
|
}
|
||||||
|
|
||||||
public static ResourceRemovedEvent create(String id, String name, String type, Set<String> uris, String owner, Set<String> scopes, String serverId) {
|
public static ResourceRemovedEvent create(String id, String name, String type, Set<String> uris, String owner, Set<String> scopes, String serverId) {
|
||||||
ResourceRemovedEvent event = new ResourceRemovedEvent();
|
return new ResourceRemovedEvent(id, name, owner, serverId, type, uris, scopes);
|
||||||
event.id = id;
|
|
||||||
event.name = name;
|
|
||||||
event.type = type;
|
|
||||||
event.uris = uris;
|
|
||||||
event.owner = owner;
|
|
||||||
event.scopes = scopes;
|
|
||||||
event.serverId = serverId;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
ResourceRemovedEvent that = (ResourceRemovedEvent) o;
|
|
||||||
return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(owner, that.owner) && Objects.equals(serverId, that.serverId) && Objects.equals(type, that.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), id, name, owner, serverId, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("ResourceRemovedEvent [ id=%s, name=%s ]", id, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
cache.resourceRemoval(id, name, type, uris, owner, scopes, serverId, invalidations);
|
cache.resourceRemoval(getId(), name, type, uris, owner, scopes, serverId, invalidations);
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<ResourceRemovedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, ResourceRemovedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.id, output);
|
|
||||||
MarshallUtil.marshallString(obj.name, output);
|
|
||||||
MarshallUtil.marshallString(obj.type, output);
|
|
||||||
KeycloakMarshallUtil.writeCollection(obj.uris, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
MarshallUtil.marshallString(obj.owner, output);
|
|
||||||
KeycloakMarshallUtil.writeCollection(obj.scopes, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
MarshallUtil.marshallString(obj.serverId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceRemovedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceRemovedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
ResourceRemovedEvent res = new ResourceRemovedEvent();
|
|
||||||
res.id = MarshallUtil.unmarshallString(input);
|
|
||||||
res.name = MarshallUtil.unmarshallString(input);
|
|
||||||
res.type = MarshallUtil.unmarshallString(input);
|
|
||||||
res.uris = KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, HashSet::new);
|
|
||||||
res.owner = MarshallUtil.unmarshallString(input);
|
|
||||||
res.scopes = KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, HashSet::new);
|
|
||||||
res.serverId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,91 +17,30 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.authorization.events;
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
|
||||||
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(ResourceServerRemovedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.RESOURCE_SERVER_REMOVED_EVENT)
|
||||||
public class ResourceServerRemovedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
public class ResourceServerRemovedEvent extends BaseResourceServerEvent {
|
||||||
|
|
||||||
private String id;
|
@ProtoFactory
|
||||||
private String clientId;
|
ResourceServerRemovedEvent(String id) {
|
||||||
|
super(id);
|
||||||
public static ResourceServerRemovedEvent create(String id, String clientId) {
|
|
||||||
ResourceServerRemovedEvent event = new ResourceServerRemovedEvent();
|
|
||||||
event.id = id;
|
|
||||||
event.clientId = clientId;
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static ResourceServerRemovedEvent create(String id) {
|
||||||
public String getId() {
|
return new ResourceServerRemovedEvent(id);
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
ResourceServerRemovedEvent that = (ResourceServerRemovedEvent) o;
|
|
||||||
return Objects.equals(id, that.id) && Objects.equals(clientId, that.clientId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), id, clientId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("ResourceServerRemovedEvent [ id=%s, clientId=%s ]", id, clientId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
cache.resourceServerRemoval(id, invalidations);
|
cache.resourceServerRemoval(getId(), invalidations);
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<ResourceServerRemovedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, ResourceServerRemovedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.id, output);
|
|
||||||
MarshallUtil.marshallString(obj.clientId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServerRemovedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceServerRemovedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
ResourceServerRemovedEvent res = new ResourceServerRemovedEvent();
|
|
||||||
res.id = MarshallUtil.unmarshallString(input);
|
|
||||||
res.clientId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,72 +17,30 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.authorization.events;
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
|
||||||
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(ResourceServerUpdatedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.RESOURCE_SERVER_UPDATED_EVENT)
|
||||||
public class ResourceServerUpdatedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
public class ResourceServerUpdatedEvent extends BaseResourceServerEvent {
|
||||||
|
|
||||||
private String id;
|
@ProtoFactory
|
||||||
|
ResourceServerUpdatedEvent(String id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
public static ResourceServerUpdatedEvent create(String id) {
|
public static ResourceServerUpdatedEvent create(String id) {
|
||||||
ResourceServerUpdatedEvent event = new ResourceServerUpdatedEvent();
|
return new ResourceServerUpdatedEvent(id);
|
||||||
event.id = id;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("ResourceServerRemovedEvent [ id=%s, clientId=%s ]", id, id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
cache.resourceServerUpdated(id, invalidations);
|
cache.resourceServerUpdated(getId(), invalidations);
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<ResourceServerUpdatedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, ResourceServerUpdatedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.id, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceServerUpdatedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceServerUpdatedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
ResourceServerUpdatedEvent res = new ResourceServerUpdatedEvent();
|
|
||||||
res.id = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,113 +17,35 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.authorization.events;
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
|
||||||
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
|
||||||
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.KeycloakMarshallUtil;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(ResourceUpdatedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.RESOURCE_UPDATED_EVENT)
|
||||||
public class ResourceUpdatedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
public class ResourceUpdatedEvent extends BaseResourceEvent {
|
||||||
|
|
||||||
private String id;
|
@ProtoFactory
|
||||||
private String name;
|
static ResourceUpdatedEvent protoFactory(String id, String name, String owner, String serverId, String type, Set<String> uris, Set<String> scopes) {
|
||||||
private String serverId;
|
return new ResourceUpdatedEvent(id, name, owner, serverId, Marshalling.emptyStringToNull(type), uris, scopes);
|
||||||
private String type;
|
|
||||||
private Set<String> uris;
|
|
||||||
private Set<String> scopes;
|
|
||||||
private String owner;
|
|
||||||
|
|
||||||
public static ResourceUpdatedEvent create(String id, String name, String type, Set<String> uris, Set<String> scopes, String serverId, String owner) {
|
|
||||||
ResourceUpdatedEvent event = new ResourceUpdatedEvent();
|
|
||||||
event.id = id;
|
|
||||||
event.name = name;
|
|
||||||
event.type = type;
|
|
||||||
event.uris = uris;
|
|
||||||
event.scopes = scopes;
|
|
||||||
event.serverId = serverId;
|
|
||||||
event.owner = owner;
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private ResourceUpdatedEvent(String id, String name, String owner, String serverId, String type, Set<String> uris, Set<String> scopes) {
|
||||||
public String getId() {
|
super(id, name, owner, serverId, type, uris, scopes);
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static ResourceUpdatedEvent create(String id, String name, String type, Set<String> uris, String owner, Set<String> scopes, String serverId) {
|
||||||
public boolean equals(Object o) {
|
return new ResourceUpdatedEvent(id, name, owner, serverId, type, uris, scopes);
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
ResourceUpdatedEvent that = (ResourceUpdatedEvent) o;
|
|
||||||
return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(serverId, that.serverId) && Objects.equals(type, that.type) && Objects.equals(owner, that.owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), id, name, serverId, type, owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("ResourceUpdatedEvent [ id=%s, name=%s ]", id, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
cache.resourceUpdated(id, name, type, uris, scopes, serverId, owner, invalidations);
|
cache.resourceUpdated(getId(), name, type, uris, scopes, serverId, owner, invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<ResourceUpdatedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, ResourceUpdatedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.id, output);
|
|
||||||
MarshallUtil.marshallString(obj.name, output);
|
|
||||||
MarshallUtil.marshallString(obj.type, output);
|
|
||||||
KeycloakMarshallUtil.writeCollection(obj.uris, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
KeycloakMarshallUtil.writeCollection(obj.scopes, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
MarshallUtil.marshallString(obj.serverId, output);
|
|
||||||
MarshallUtil.marshallString(obj.owner, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceUpdatedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceUpdatedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
ResourceUpdatedEvent res = new ResourceUpdatedEvent();
|
|
||||||
res.id = MarshallUtil.unmarshallString(input);
|
|
||||||
res.name = MarshallUtil.unmarshallString(input);
|
|
||||||
res.type = MarshallUtil.unmarshallString(input);
|
|
||||||
res.uris = KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, HashSet::new);
|
|
||||||
res.scopes = KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, HashSet::new);
|
|
||||||
res.serverId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.owner = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,95 +17,30 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.authorization.events;
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
|
||||||
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(ScopeRemovedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.SCOPE_REMOVED_EVENT)
|
||||||
public class ScopeRemovedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
public class ScopeRemovedEvent extends BaseScopeEvent {
|
||||||
|
|
||||||
private String id;
|
@ProtoFactory
|
||||||
private String name;
|
ScopeRemovedEvent(String id, String name, String serverId) {
|
||||||
private String serverId;
|
super(id, name, serverId);
|
||||||
|
}
|
||||||
|
|
||||||
public static ScopeRemovedEvent create(String id, String name, String serverId) {
|
public static ScopeRemovedEvent create(String id, String name, String serverId) {
|
||||||
ScopeRemovedEvent event = new ScopeRemovedEvent();
|
return new ScopeRemovedEvent(id, name, serverId);
|
||||||
event.id = id;
|
|
||||||
event.name = name;
|
|
||||||
event.serverId = serverId;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("ScopeRemovedEvent [ id=%s, name=%s]", id, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
ScopeRemovedEvent that = (ScopeRemovedEvent) o;
|
|
||||||
return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(serverId, that.serverId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), id, name, serverId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
cache.scopeRemoval(id, name, serverId, invalidations);
|
cache.scopeRemoval(getId(), name, serverId, invalidations);
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<ScopeRemovedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, ScopeRemovedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.id, output);
|
|
||||||
MarshallUtil.marshallString(obj.name, output);
|
|
||||||
MarshallUtil.marshallString(obj.serverId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ScopeRemovedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ScopeRemovedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
ScopeRemovedEvent res = new ScopeRemovedEvent();
|
|
||||||
res.id = MarshallUtil.unmarshallString(input);
|
|
||||||
res.name = MarshallUtil.unmarshallString(input);
|
|
||||||
res.serverId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,95 +17,30 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.authorization.events;
|
package org.keycloak.models.cache.infinispan.authorization.events;
|
||||||
|
|
||||||
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
|
||||||
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(ScopeUpdatedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.SCOPE_UPDATED_EVENT)
|
||||||
public class ScopeUpdatedEvent extends InvalidationEvent implements AuthorizationCacheInvalidationEvent {
|
public class ScopeUpdatedEvent extends BaseScopeEvent {
|
||||||
|
|
||||||
private String id;
|
@ProtoFactory
|
||||||
private String name;
|
ScopeUpdatedEvent(String id, String name, String serverId) {
|
||||||
private String serverId;
|
super(id, name, serverId);
|
||||||
|
}
|
||||||
|
|
||||||
public static ScopeUpdatedEvent create(String id, String name, String serverId) {
|
public static ScopeUpdatedEvent create(String id, String name, String serverId) {
|
||||||
ScopeUpdatedEvent event = new ScopeUpdatedEvent();
|
return new ScopeUpdatedEvent(id, name, serverId);
|
||||||
event.id = id;
|
|
||||||
event.name = name;
|
|
||||||
event.serverId = serverId;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
ScopeUpdatedEvent that = (ScopeUpdatedEvent) o;
|
|
||||||
return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(serverId, that.serverId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), id, name, serverId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("ScopeUpdatedEvent [ id=%s, name=%s ]", id, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
|
||||||
cache.scopeUpdated(id, name, serverId, invalidations);
|
cache.scopeUpdated(getId(), name, serverId, invalidations);
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<ScopeUpdatedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, ScopeUpdatedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.id, output);
|
|
||||||
MarshallUtil.marshallString(obj.name, output);
|
|
||||||
MarshallUtil.marshallString(obj.serverId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ScopeUpdatedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ScopeUpdatedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
ScopeUpdatedEvent res = new ScopeUpdatedEvent();
|
|
||||||
res.id = MarshallUtil.unmarshallString(input);
|
|
||||||
res.name = MarshallUtil.unmarshallString(input);
|
|
||||||
res.serverId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,71 +16,42 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.cache.infinispan.authorization.stream;
|
package org.keycloak.models.cache.infinispan.authorization.stream;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import java.util.Map;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
import java.util.function.Predicate;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
|
||||||
import org.keycloak.models.cache.infinispan.authorization.entities.InResource;
|
import org.keycloak.models.cache.infinispan.authorization.entities.InResource;
|
||||||
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
||||||
import java.io.IOException;
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
import java.util.Map;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
import java.util.Objects;
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import java.util.function.Predicate;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(InResourcePredicate.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.IN_RESOURCE_PREDICATE)
|
||||||
public class InResourcePredicate implements Predicate<Map.Entry<String, Revisioned>>, Serializable {
|
public class InResourcePredicate implements Predicate<Map.Entry<String, Revisioned>> {
|
||||||
|
|
||||||
private String resourceId;
|
private final String resourceId;
|
||||||
|
|
||||||
public static InResourcePredicate create() {
|
private InResourcePredicate(String resourceId) {
|
||||||
return new InResourcePredicate();
|
this.resourceId = Objects.requireNonNull(resourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InResourcePredicate resource(String id) {
|
@ProtoFactory
|
||||||
resourceId = id;
|
public static InResourcePredicate create(String resourceId) {
|
||||||
return this;
|
return new InResourcePredicate(resourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtoField(1)
|
||||||
|
String getResourceId() {
|
||||||
|
return resourceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean test(Map.Entry<String, Revisioned> entry) {
|
public boolean test(Map.Entry<String, Revisioned> entry) {
|
||||||
Object value = entry.getValue();
|
return entry.getValue() instanceof InResource inResource && resourceId.equals(inResource.getResourceId());
|
||||||
if (value == null) return false;
|
|
||||||
if (!(value instanceof InResource)) return false;
|
|
||||||
|
|
||||||
return resourceId.equals(((InResource)value).getResourceId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<InResourcePredicate> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, InResourcePredicate obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.resourceId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InResourcePredicate readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public InResourcePredicate readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
InResourcePredicate res = new InResourcePredicate();
|
|
||||||
res.resourceId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,70 +1,41 @@
|
||||||
package org.keycloak.models.cache.infinispan.authorization.stream;
|
package org.keycloak.models.cache.infinispan.authorization.stream;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.authorization.entities.InResourceServer;
|
import org.keycloak.models.cache.infinispan.authorization.entities.InResourceServer;
|
||||||
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 $
|
||||||
*/
|
*/
|
||||||
@SerializeWith(InResourceServerPredicate.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.IN_RESOURCE_SERVER_PREDICATE)
|
||||||
public class InResourceServerPredicate implements Predicate<Map.Entry<String, Revisioned>>, Serializable {
|
public class InResourceServerPredicate implements Predicate<Map.Entry<String, Revisioned>> {
|
||||||
private String serverId;
|
private final String serverId;
|
||||||
|
|
||||||
public static InResourceServerPredicate create() {
|
private InResourceServerPredicate(String serverId) {
|
||||||
return new InResourceServerPredicate();
|
this.serverId = Objects.requireNonNull(serverId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InResourceServerPredicate resourceServer(String id) {
|
@ProtoFactory
|
||||||
serverId = id;
|
public static InResourceServerPredicate create(String serverId) {
|
||||||
return this;
|
return new InResourceServerPredicate(serverId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtoField(1)
|
||||||
|
String getServerId() {
|
||||||
|
return serverId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean test(Map.Entry<String, Revisioned> entry) {
|
public boolean test(Map.Entry<String, Revisioned> entry) {
|
||||||
Object value = entry.getValue();
|
return entry.getValue() instanceof InResourceServer inResourceServer && serverId.equals(inResourceServer.getResourceServerId());
|
||||||
if (value == null) return false;
|
|
||||||
if (!(value instanceof InResourceServer)) return false;
|
|
||||||
|
|
||||||
return serverId.equals(((InResourceServer)value).getResourceServerId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<InResourceServerPredicate> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, InResourceServerPredicate obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.serverId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InResourceServerPredicate readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public InResourceServerPredicate readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
InResourceServerPredicate res = new InResourceServerPredicate();
|
|
||||||
res.serverId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,70 +1,41 @@
|
||||||
package org.keycloak.models.cache.infinispan.authorization.stream;
|
package org.keycloak.models.cache.infinispan.authorization.stream;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.authorization.entities.InScope;
|
import org.keycloak.models.cache.infinispan.authorization.entities.InScope;
|
||||||
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 $
|
||||||
*/
|
*/
|
||||||
@SerializeWith(InScopePredicate.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.IN_SCOPE_PREDICATE)
|
||||||
public class InScopePredicate implements Predicate<Map.Entry<String, Revisioned>>, Serializable {
|
public class InScopePredicate implements Predicate<Map.Entry<String, Revisioned>> {
|
||||||
private String scopeId;
|
private final String scopeId;
|
||||||
|
|
||||||
public static InScopePredicate create() {
|
private InScopePredicate(String scopeId) {
|
||||||
return new InScopePredicate();
|
this.scopeId = Objects.requireNonNull(scopeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InScopePredicate scope(String id) {
|
@ProtoFactory
|
||||||
scopeId = id;
|
public static InScopePredicate create(String scopeId) {
|
||||||
return this;
|
return new InScopePredicate(scopeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtoField(1)
|
||||||
|
String getScopeId() {
|
||||||
|
return scopeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean test(Map.Entry<String, Revisioned> entry) {
|
public boolean test(Map.Entry<String, Revisioned> entry) {
|
||||||
Object value = entry.getValue();
|
return entry.getValue() instanceof InScope inScope && scopeId.equals(inScope.getScopeId());
|
||||||
if (value == null) return false;
|
|
||||||
if (!(value instanceof InScope)) return false;
|
|
||||||
|
|
||||||
return scopeId.equals(((InScope)value).getScopeId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<InScopePredicate> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, InScopePredicate obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.scopeId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InScopePredicate readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public InScopePredicate readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
InScopePredicate res = new InScopePredicate();
|
|
||||||
res.scopeId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ import java.io.Serializable;
|
||||||
* @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 class AbstractRevisioned implements Revisioned, Serializable, CachedObject {
|
public class AbstractRevisioned implements Revisioned, CachedObject {
|
||||||
private String id;
|
private final String id;
|
||||||
private Long revision;
|
private Long revision;
|
||||||
private final long cacheTimestamp = Time.currentTimeMillis();
|
private final long cacheTimestamp = Time.currentTimeMillis();
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,9 @@ import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.keycloak.common.enums.SslRequired;
|
import org.keycloak.common.enums.SslRequired;
|
||||||
|
import org.keycloak.common.util.ConcurrentMultivaluedHashMap;
|
||||||
import org.keycloak.common.util.MultivaluedHashMap;
|
import org.keycloak.common.util.MultivaluedHashMap;
|
||||||
|
import org.keycloak.common.util.MultivaluedMap;
|
||||||
import org.keycloak.component.ComponentModel;
|
import org.keycloak.component.ComponentModel;
|
||||||
import org.keycloak.models.AuthenticationExecutionModel;
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
import org.keycloak.models.AuthenticationFlowModel;
|
import org.keycloak.models.AuthenticationFlowModel;
|
||||||
|
@ -122,8 +124,8 @@ public class CachedRealm extends AbstractExtendableRevisioned {
|
||||||
protected String masterAdminClient;
|
protected String masterAdminClient;
|
||||||
|
|
||||||
protected List<RequiredCredentialModel> requiredCredentials;
|
protected List<RequiredCredentialModel> requiredCredentials;
|
||||||
protected MultivaluedHashMap<String, ComponentModel> componentsByParent = new MultivaluedHashMap<>();
|
protected MultivaluedMap<String, ComponentModel> componentsByParent = new MultivaluedHashMap<>();
|
||||||
protected MultivaluedHashMap<String, ComponentModel> componentsByParentAndType = new MultivaluedHashMap<>();
|
protected MultivaluedMap<String, ComponentModel> componentsByParentAndType = new ConcurrentMultivaluedHashMap<>();
|
||||||
protected Map<String, ComponentModel> components;
|
protected Map<String, ComponentModel> components;
|
||||||
protected List<IdentityProviderModel> identityProviders;
|
protected List<IdentityProviderModel> identityProviders;
|
||||||
|
|
||||||
|
@ -723,11 +725,11 @@ public class CachedRealm extends AbstractExtendableRevisioned {
|
||||||
return requiredActionProviderList;
|
return requiredActionProviderList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MultivaluedHashMap<String, ComponentModel> getComponentsByParent() {
|
public MultivaluedMap<String, ComponentModel> getComponentsByParent() {
|
||||||
return componentsByParent;
|
return componentsByParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MultivaluedHashMap<String, ComponentModel> getComponentsByParentAndType() {
|
public MultivaluedMap<String, ComponentModel> getComponentsByParentAndType() {
|
||||||
return componentsByParentAndType;
|
return componentsByParentAndType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,115 +16,80 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.cache.infinispan.events;
|
package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
import org.keycloak.cluster.ClusterEvent;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.cluster.ClusterEvent;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author hmlnarik
|
* @author hmlnarik
|
||||||
*/
|
*/
|
||||||
@SerializeWith(AuthenticationSessionAuthNoteUpdateEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.AUTHENTICATION_SESSION_AUTH_NOTE_UPDATE_EVENT)
|
||||||
public class AuthenticationSessionAuthNoteUpdateEvent implements ClusterEvent {
|
public class AuthenticationSessionAuthNoteUpdateEvent implements ClusterEvent {
|
||||||
|
|
||||||
private String authSessionId;
|
private final String authSessionId;
|
||||||
private String tabId;
|
private final String tabId;
|
||||||
private String clientUUID;
|
private final Map<String, String> authNotesFragment;
|
||||||
|
|
||||||
private Map<String, String> authNotesFragment;
|
private AuthenticationSessionAuthNoteUpdateEvent(Map<String, String> authNotesFragment, String authSessionId, String tabId) {
|
||||||
|
this.authNotesFragment = Objects.requireNonNull(authNotesFragment);
|
||||||
|
this.authSessionId = Objects.requireNonNull(authSessionId);
|
||||||
|
this.tabId = Objects.requireNonNull(tabId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of the event.
|
* Creates an instance of the event.
|
||||||
* @param authSessionId
|
*
|
||||||
* @param authNotesFragment
|
|
||||||
* @return Event. Note that {@code authNotesFragment} property is not thread safe which is fine for now.
|
* @return Event. Note that {@code authNotesFragment} property is not thread safe which is fine for now.
|
||||||
*/
|
*/
|
||||||
public static AuthenticationSessionAuthNoteUpdateEvent create(String authSessionId, String tabId, String clientUUID, Map<String, String> authNotesFragment) {
|
@ProtoFactory
|
||||||
AuthenticationSessionAuthNoteUpdateEvent event = new AuthenticationSessionAuthNoteUpdateEvent();
|
public static AuthenticationSessionAuthNoteUpdateEvent create(String authSessionId, String tabId, Map<String, String> authNotesFragment) {
|
||||||
event.authSessionId = authSessionId;
|
return new AuthenticationSessionAuthNoteUpdateEvent(authNotesFragment, authSessionId, tabId);
|
||||||
event.tabId = tabId;
|
|
||||||
event.clientUUID = clientUUID;
|
|
||||||
event.authNotesFragment = new LinkedHashMap<>(authNotesFragment);
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(1)
|
||||||
public String getAuthSessionId() {
|
public String getAuthSessionId() {
|
||||||
return authSessionId;
|
return authSessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
public String getTabId() {
|
public String getTabId() {
|
||||||
return tabId;
|
return tabId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClientUUID() {
|
@ProtoField(value = 3, mapImplementation = LinkedHashMap.class)
|
||||||
return clientUUID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getAuthNotesFragment() {
|
public Map<String, String> getAuthNotesFragment() {
|
||||||
return authNotesFragment;
|
return authNotesFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) {
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
AuthenticationSessionAuthNoteUpdateEvent that = (AuthenticationSessionAuthNoteUpdateEvent) o;
|
AuthenticationSessionAuthNoteUpdateEvent that = (AuthenticationSessionAuthNoteUpdateEvent) o;
|
||||||
return Objects.equals(authSessionId, that.authSessionId) && Objects.equals(tabId, that.tabId) && Objects.equals(clientUUID, that.clientUUID);
|
return Objects.equals(authSessionId, that.authSessionId) && Objects.equals(tabId, that.tabId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(authSessionId, tabId, clientUUID);
|
return Objects.hash(authSessionId, tabId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("AuthenticationSessionAuthNoteUpdateEvent [ authSessionId=%s, tabId=%s, clientUUID=%s, authNotesFragment=%s ]",
|
return String.format("AuthenticationSessionAuthNoteUpdateEvent [ authSessionId=%s, tabId=%s, authNotesFragment=%s ]",
|
||||||
authSessionId, clientUUID, authNotesFragment);
|
authSessionId, tabId, authNotesFragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<AuthenticationSessionAuthNoteUpdateEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, AuthenticationSessionAuthNoteUpdateEvent value) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(value.authSessionId, output);
|
|
||||||
MarshallUtil.marshallString(value.tabId, output);
|
|
||||||
MarshallUtil.marshallString(value.clientUUID, output);
|
|
||||||
MarshallUtil.marshallMap(value.authNotesFragment, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthenticationSessionAuthNoteUpdateEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthenticationSessionAuthNoteUpdateEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
return create(
|
|
||||||
MarshallUtil.unmarshallString(input),
|
|
||||||
MarshallUtil.unmarshallString(input),
|
|
||||||
MarshallUtil.unmarshallString(input),
|
|
||||||
MarshallUtil.<String, String, Map<String, String>>unmarshallMap(input, HashMap::new)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
55
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/events/BaseClientEvent.java
vendored
Normal file
55
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/events/BaseClientEvent.java
vendored
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
|
||||||
|
abstract class BaseClientEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
|
final String realmId;
|
||||||
|
|
||||||
|
BaseClientEvent(String clientUuid, String realmId) {
|
||||||
|
super(clientUuid);
|
||||||
|
this.realmId = Objects.requireNonNull(realmId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
BaseClientEvent that = (BaseClientEvent) o;
|
||||||
|
return realmId.equals(that.realmId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + realmId.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s [ realmId=%s, clientUuid=%s ]", getClass().getSimpleName(), realmId, getId());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
|
||||||
|
abstract class BaseClientScopeEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
|
final String realmId;
|
||||||
|
|
||||||
|
BaseClientScopeEvent(String clientScopeId, String realmId) {
|
||||||
|
super(clientScopeId);
|
||||||
|
this.realmId = Objects.requireNonNull(realmId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
BaseClientScopeEvent that = (BaseClientScopeEvent) o;
|
||||||
|
return realmId.equals(that.realmId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + realmId.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s [ clientScopeId=%s, realmId=%s ]", getClass().getSimpleName(), getId(), realmId);
|
||||||
|
}
|
||||||
|
}
|
55
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/events/BaseRealmEvent.java
vendored
Normal file
55
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/events/BaseRealmEvent.java
vendored
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
|
||||||
|
abstract class BaseRealmEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
|
final String realmName;
|
||||||
|
|
||||||
|
BaseRealmEvent(String realmId, String realmName) {
|
||||||
|
super(realmId);
|
||||||
|
this.realmName = Objects.requireNonNull(realmName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
BaseRealmEvent that = (BaseRealmEvent) o;
|
||||||
|
return realmName.equals(that.realmName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + realmName.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s [ realmId=%s, realmName=%s ]", getClass().getSimpleName(), getId(), realmName);
|
||||||
|
}
|
||||||
|
}
|
55
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/events/BaseRoleEvent.java
vendored
Normal file
55
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/events/BaseRoleEvent.java
vendored
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
|
||||||
|
abstract class BaseRoleEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
|
final String containerId;
|
||||||
|
|
||||||
|
BaseRoleEvent(String roleId, String containerId) {
|
||||||
|
super(roleId);
|
||||||
|
this.containerId = Objects.requireNonNull(containerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
BaseRoleEvent that = (BaseRoleEvent) o;
|
||||||
|
return containerId.equals(that.containerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + containerId.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s [ roleId=%s, containerId=%s ]", getClass().getSimpleName(), getId(), containerId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,94 +17,30 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.events;
|
package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(ClientAddedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.CLIENT_ADDED_EVENT)
|
||||||
public class ClientAddedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
public class ClientAddedEvent extends BaseClientEvent {
|
||||||
|
|
||||||
private String clientUuid;
|
@ProtoFactory
|
||||||
private String clientId;
|
ClientAddedEvent(String id, String realmId) {
|
||||||
private String realmId;
|
super(id, realmId);
|
||||||
|
|
||||||
public static ClientAddedEvent create(String clientUuid, String clientId, String realmId) {
|
|
||||||
ClientAddedEvent event = new ClientAddedEvent();
|
|
||||||
event.clientUuid = clientUuid;
|
|
||||||
event.clientId = clientId;
|
|
||||||
event.realmId = realmId;
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static ClientAddedEvent create(String clientUuid, String realmId) {
|
||||||
public String getId() {
|
return new ClientAddedEvent(clientUuid, realmId);
|
||||||
return clientUuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("ClientAddedEvent [ realmId=%s, clientUuid=%s, clientId=%s ]", realmId, clientUuid, clientId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
||||||
realmCache.clientAdded(realmId, invalidations);
|
realmCache.clientAdded(realmId, invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
ClientAddedEvent that = (ClientAddedEvent) o;
|
|
||||||
return Objects.equals(clientUuid, that.clientUuid) && Objects.equals(clientId, that.clientId) && Objects.equals(realmId, that.realmId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), clientUuid, clientId, realmId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<ClientAddedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, ClientAddedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.clientUuid, output);
|
|
||||||
MarshallUtil.marshallString(obj.clientId, output);
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClientAddedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClientAddedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
ClientAddedEvent res = new ClientAddedEvent();
|
|
||||||
res.clientUuid = MarshallUtil.unmarshallString(input);
|
|
||||||
res.clientId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,73 +20,56 @@ package org.keycloak.models.cache.infinispan.events;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
import org.keycloak.models.sessions.infinispan.util.KeycloakMarshallUtil;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(ClientRemovedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.CLIENT_REMOVED_EVENT)
|
||||||
public class ClientRemovedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
public class ClientRemovedEvent extends BaseClientEvent {
|
||||||
|
|
||||||
private String clientUuid;
|
@ProtoField(3)
|
||||||
private String clientId;
|
final String clientId;
|
||||||
private String realmId;
|
|
||||||
// roleId -> roleName
|
// roleId -> roleName
|
||||||
private Map<String, String> clientRoles;
|
@ProtoField(4)
|
||||||
private static final Logger log = Logger.getLogger(ClientRemovedEvent.class);
|
final Map<String, String> clientRoles;
|
||||||
|
|
||||||
|
@ProtoFactory
|
||||||
|
ClientRemovedEvent(String id, String realmId, String clientId, Map<String, String> clientRoles) {
|
||||||
|
super(id, realmId);
|
||||||
|
this.clientId = Objects.requireNonNull(clientId);
|
||||||
|
this.clientRoles = Objects.requireNonNull(clientRoles);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static ClientRemovedEvent create(ClientModel client) {
|
public static ClientRemovedEvent create(ClientModel client) {
|
||||||
log.tracev("Created; clientId={0}", client.getClientId());
|
var clientRoles = client.getRolesStream().collect(Collectors.toMap(RoleModel::getId, RoleModel::getName));
|
||||||
|
return new ClientRemovedEvent(client.getId(), client.getClientId(), client.getRealm().getId(), clientRoles);
|
||||||
ClientRemovedEvent event = new ClientRemovedEvent();
|
|
||||||
|
|
||||||
event.realmId = client.getRealm().getId();
|
|
||||||
event.clientUuid = client.getId();
|
|
||||||
event.clientId = client.getClientId();
|
|
||||||
event.clientRoles = client.getRolesStream().collect(Collectors.toMap(RoleModel::getId, RoleModel::getName));
|
|
||||||
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
log.tracev("Finalized; clientId={0}", clientId);
|
|
||||||
super.finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return clientUuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("ClientRemovedEvent [ realmId=%s, clientUuid=%s, clientId=%s, clientRoleIds=%s ]", realmId, clientUuid, clientId, clientRoles);
|
return String.format("ClientRemovedEvent [ realmId=%s, clientUuid=%s, clientId=%s, clientRoleIds=%s ]", realmId, getId(), clientId, clientRoles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
||||||
realmCache.clientRemoval(realmId, clientUuid, clientId, invalidations);
|
realmCache.clientRemoval(realmId, getId(), clientId, invalidations);
|
||||||
|
|
||||||
// Separate iteration for all client roles to invalidate records dependent on them
|
// Separate iteration for all client roles to invalidate records dependent on them
|
||||||
for (Map.Entry<String, String> clientRole : clientRoles.entrySet()) {
|
for (Map.Entry<String, String> clientRole : clientRoles.entrySet()) {
|
||||||
String roleId = clientRole.getKey();
|
String roleId = clientRole.getKey();
|
||||||
String roleName = clientRole.getValue();
|
String roleName = clientRole.getValue();
|
||||||
realmCache.roleRemoval(roleId, roleName, clientUuid, invalidations);
|
realmCache.roleRemoval(roleId, roleName, getId(), invalidations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,56 +79,15 @@ public class ClientRemovedEvent extends InvalidationEvent implements RealmCacheI
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
if (!super.equals(o)) return false;
|
if (!super.equals(o)) return false;
|
||||||
ClientRemovedEvent that = (ClientRemovedEvent) o;
|
ClientRemovedEvent that = (ClientRemovedEvent) o;
|
||||||
boolean equals = Objects.equals(clientUuid, that.clientUuid) &&
|
return clientId.equals(that.clientId) &&
|
||||||
Objects.equals(clientId, that.clientId) &&
|
clientRoles.equals(that.clientRoles);
|
||||||
Objects.equals(realmId, that.realmId) &&
|
|
||||||
Objects.equals(clientRoles, that.clientRoles);
|
|
||||||
log.tracev("Equals; clientId={0}, equals={1}", clientId, equals);
|
|
||||||
return equals;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(super.hashCode(), clientUuid, clientId, realmId, clientRoles);
|
int result = super.hashCode();
|
||||||
}
|
result = 31 * result + clientId.hashCode();
|
||||||
|
result = 31 * result + clientRoles.hashCode();
|
||||||
public static class ExternalizerImpl implements Externalizer<ClientRemovedEvent> {
|
return result;
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, ClientRemovedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.clientUuid, output);
|
|
||||||
MarshallUtil.marshallString(obj.clientId, output);
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
KeycloakMarshallUtil.writeMap(obj.clientRoles, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
|
|
||||||
log.tracev("Write; clientId={0}", obj.clientId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClientRemovedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClientRemovedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
ClientRemovedEvent res = new ClientRemovedEvent();
|
|
||||||
res.clientUuid = MarshallUtil.unmarshallString(input);
|
|
||||||
res.clientId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.clientRoles = KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT,
|
|
||||||
size -> new ConcurrentHashMap<>(size));
|
|
||||||
|
|
||||||
log.tracev("Read; clientId={0}", res.clientId);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,87 +17,27 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.events;
|
package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
@SerializeWith(ClientScopeAddedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.CLIENT_SCOPE_ADDED_EVENT)
|
||||||
public class ClientScopeAddedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
public class ClientScopeAddedEvent extends BaseClientScopeEvent {
|
||||||
|
|
||||||
private String clientScopeId;
|
@ProtoFactory
|
||||||
private String realmId;
|
ClientScopeAddedEvent(String id, String realmId) {
|
||||||
|
super(id, realmId);
|
||||||
|
}
|
||||||
|
|
||||||
public static ClientScopeAddedEvent create(String clientScopeId, String realmId) {
|
public static ClientScopeAddedEvent create(String clientScopeId, String realmId) {
|
||||||
ClientScopeAddedEvent event = new ClientScopeAddedEvent();
|
return new ClientScopeAddedEvent(clientScopeId, realmId);
|
||||||
event.clientScopeId = clientScopeId;
|
|
||||||
event.realmId = realmId;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return clientScopeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
ClientScopeAddedEvent that = (ClientScopeAddedEvent) o;
|
|
||||||
return Objects.equals(clientScopeId, that.clientScopeId) && Objects.equals(realmId, that.realmId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), clientScopeId, realmId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("ClientScopeAddedEvent [ clientScopeId=%s, realmId=%s ]", clientScopeId, realmId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
||||||
realmCache.clientScopeAdded(realmId, invalidations);
|
realmCache.clientScopeAdded(realmId, invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<ClientScopeAddedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, ClientScopeAddedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.clientScopeId, output);
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClientScopeAddedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClientScopeAddedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
ClientScopeAddedEvent res = new ClientScopeAddedEvent();
|
|
||||||
res.clientScopeId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,88 +17,27 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.events;
|
package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
@ProtoTypeId(Marshalling.CLIENT_SCOPE_REMOVED_EVENT)
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
public class ClientScopeRemovedEvent extends BaseClientScopeEvent {
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
@SerializeWith(ClientScopeRemovedEvent.ExternalizerImpl.class)
|
@ProtoFactory
|
||||||
public class ClientScopeRemovedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
ClientScopeRemovedEvent(String id, String realmId) {
|
||||||
|
super(id, realmId);
|
||||||
private String clientScopeId;
|
}
|
||||||
private String realmId;
|
|
||||||
|
|
||||||
public static ClientScopeRemovedEvent create(String clientScopeId, String realmId) {
|
public static ClientScopeRemovedEvent create(String clientScopeId, String realmId) {
|
||||||
ClientScopeRemovedEvent event = new ClientScopeRemovedEvent();
|
return new ClientScopeRemovedEvent(clientScopeId, realmId);
|
||||||
event.clientScopeId = clientScopeId;
|
|
||||||
event.realmId = realmId;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return clientScopeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
ClientScopeRemovedEvent that = (ClientScopeRemovedEvent) o;
|
|
||||||
return Objects.equals(clientScopeId, that.clientScopeId) && Objects.equals(realmId, that.realmId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), clientScopeId, realmId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("ClientScopeRemovedEvent [ clientScopeId=%s, realmId=%s ]", clientScopeId, realmId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
||||||
realmCache.clientScopeRemoval(realmId, invalidations);
|
realmCache.clientScopeRemoval(realmId, invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<ClientScopeRemovedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, ClientScopeRemovedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.clientScopeId, output);
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClientScopeRemovedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClientScopeRemovedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
ClientScopeRemovedEvent res = new ClientScopeRemovedEvent();
|
|
||||||
res.clientScopeId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.events;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO Leave the name ClientTemplateEvent just due the backwards compatibility of infinispan migration. See if can be renamed based on
|
|
||||||
* rolling upgrades plan...
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
@SerializeWith(ClientTemplateEvent.ExternalizerImpl.class)
|
|
||||||
public class ClientTemplateEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
|
||||||
|
|
||||||
private String clientTemplateId;
|
|
||||||
|
|
||||||
public static ClientTemplateEvent create(String clientTemplateId) {
|
|
||||||
ClientTemplateEvent event = new ClientTemplateEvent();
|
|
||||||
event.clientTemplateId = clientTemplateId;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return clientTemplateId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ClientTemplateEvent [ " + clientTemplateId + " ]";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
|
||||||
// Nothing. ID was already invalidated
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
ClientTemplateEvent that = (ClientTemplateEvent) o;
|
|
||||||
return Objects.equals(clientTemplateId, that.clientTemplateId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), clientTemplateId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<ClientTemplateEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, ClientTemplateEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.clientTemplateId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClientTemplateEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClientTemplateEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
ClientTemplateEvent res = new ClientTemplateEvent();
|
|
||||||
res.clientTemplateId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,94 +17,40 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.events;
|
package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(ClientUpdatedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.CLIENT_UPDATED_EVENT)
|
||||||
public class ClientUpdatedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
public class ClientUpdatedEvent extends BaseClientEvent {
|
||||||
|
|
||||||
private String clientUuid;
|
@ProtoField(3)
|
||||||
private String clientId;
|
final String clientId;
|
||||||
private String realmId;
|
|
||||||
|
|
||||||
public static ClientUpdatedEvent create(String clientUuid, String clientId, String realmId) {
|
@ProtoFactory
|
||||||
ClientUpdatedEvent event = new ClientUpdatedEvent();
|
ClientUpdatedEvent(String id, String realmId, String clientId) {
|
||||||
event.clientUuid = clientUuid;
|
super(id, realmId);
|
||||||
event.clientId = clientId;
|
this.clientId = clientId;
|
||||||
event.realmId = realmId;
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static ClientUpdatedEvent create(String clientUuid, String clientId, String realmId) {
|
||||||
public String getId() {
|
return new ClientUpdatedEvent(clientUuid, realmId, clientId);
|
||||||
return clientUuid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("ClientUpdatedEvent [ realmId=%s, clientUuid=%s, clientId=%s ]", realmId, clientUuid, clientId);
|
return String.format("ClientUpdatedEvent [ realmId=%s, clientUuid=%s, clientId=%s ]", realmId, getId(), clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
||||||
realmCache.clientUpdated(realmId, clientUuid, clientId, invalidations);
|
realmCache.clientUpdated(realmId, getId(), clientId, invalidations);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
ClientUpdatedEvent that = (ClientUpdatedEvent) o;
|
|
||||||
return Objects.equals(clientUuid, that.clientUuid) && Objects.equals(clientId, that.clientId) && Objects.equals(realmId, that.realmId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), clientUuid, clientId, realmId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<ClientUpdatedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, ClientUpdatedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.clientUuid, output);
|
|
||||||
MarshallUtil.marshallString(obj.clientId, output);
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClientUpdatedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClientUpdatedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
ClientUpdatedEvent res = new ClientUpdatedEvent();
|
|
||||||
res.clientUuid = MarshallUtil.unmarshallString(input);
|
|
||||||
res.clientId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,41 +20,42 @@ package org.keycloak.models.cache.infinispan.events;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(GroupAddedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.GROUP_ADDED_EVENT)
|
||||||
public class GroupAddedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
public class GroupAddedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
||||||
|
|
||||||
private String groupId;
|
@ProtoField(2)
|
||||||
private String realmId;
|
final String realmId;
|
||||||
private String parentId;
|
@ProtoField(3)
|
||||||
|
final String parentId; //parentId may be null
|
||||||
|
|
||||||
public static GroupAddedEvent create(String groupId, String parentId, String realmId) {
|
private GroupAddedEvent(String groupId, String realmId, String parentId) {
|
||||||
GroupAddedEvent event = new GroupAddedEvent();
|
super(groupId);
|
||||||
event.realmId = realmId;
|
this.realmId = Objects.requireNonNull(realmId);
|
||||||
event.parentId = parentId;
|
this.parentId = parentId;
|
||||||
event.groupId = groupId;
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@ProtoFactory
|
||||||
public String getId() {
|
static GroupAddedEvent protoFactory(String id, String realmId, String parentId) {
|
||||||
return groupId;
|
return new GroupAddedEvent(id, realmId, Marshalling.emptyStringToNull(parentId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupAddedEvent create(String groupId, String parentId, String realmId) {
|
||||||
|
return new GroupAddedEvent(groupId, realmId, parentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("GroupAddedEvent [ realmId=%s, groupId=%s ]", realmId, groupId);
|
return String.format("GroupAddedEvent [ realmId=%s, groupId=%s ]", realmId, getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -70,56 +71,16 @@ public class GroupAddedEvent extends InvalidationEvent implements RealmCacheInva
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
if (!super.equals(o)) return false;
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
GroupAddedEvent that = (GroupAddedEvent) o;
|
GroupAddedEvent that = (GroupAddedEvent) o;
|
||||||
return Objects.equals(groupId, that.groupId) && Objects.equals(realmId, that.realmId) && Objects.equals(parentId, that.parentId);
|
return realmId.equals(that.realmId) && Objects.equals(parentId, that.parentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(super.hashCode(), groupId, realmId, parentId);
|
int result = super.hashCode();
|
||||||
}
|
result = 31 * result + realmId.hashCode();
|
||||||
|
result = 31 * result + Objects.hashCode(parentId);
|
||||||
public static class ExternalizerImpl implements Externalizer<GroupAddedEvent> {
|
return result;
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
private static final int VERSION_2 = 2;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, GroupAddedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_2);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.groupId, output);
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
MarshallUtil.marshallString(obj.parentId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupAddedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
case VERSION_2:
|
|
||||||
return readObjectVersion2(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GroupAddedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
GroupAddedEvent res = new GroupAddedEvent();
|
|
||||||
res.groupId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GroupAddedEvent readObjectVersion2(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
GroupAddedEvent res = new GroupAddedEvent();
|
|
||||||
res.groupId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.parentId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,49 +20,51 @@ package org.keycloak.models.cache.infinispan.events;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.GroupModel;
|
import org.keycloak.models.GroupModel;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(GroupMovedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.GROUP_MOVED_EVENT)
|
||||||
public class GroupMovedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
public class GroupMovedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
||||||
|
|
||||||
private String groupId;
|
@ProtoField(2)
|
||||||
private String newParentId; // null if moving to top-level
|
final String newParentId; // null if moving to top-level
|
||||||
private String oldParentId; // null if moving from top-level
|
@ProtoField(3)
|
||||||
private String realmId;
|
final String oldParentId; // null if moving from top-level
|
||||||
|
@ProtoField(4)
|
||||||
|
final String realmId;
|
||||||
|
|
||||||
public static GroupMovedEvent create(GroupModel group, GroupModel toParent, String realmId) {
|
private GroupMovedEvent(String groupId, String newParentId, String oldParentId, String realmId) {
|
||||||
GroupMovedEvent event = new GroupMovedEvent();
|
super(groupId);
|
||||||
event.realmId = realmId;
|
this.newParentId = newParentId;
|
||||||
event.groupId = group.getId();
|
this.oldParentId = oldParentId;
|
||||||
event.oldParentId = group.getParentId();
|
this.realmId = Objects.requireNonNull(realmId);
|
||||||
event.newParentId = toParent==null ? null : toParent.getId();
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@ProtoFactory
|
||||||
public String getId() {
|
static GroupMovedEvent protoFactory(String id, String newParentId, String oldParentId, String realmId) {
|
||||||
return groupId;
|
return new GroupMovedEvent(id, Marshalling.emptyStringToNull(newParentId), Marshalling.emptyStringToNull(oldParentId), realmId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupMovedEvent create(GroupModel group, GroupModel toParent, String realmId) {
|
||||||
|
return new GroupMovedEvent(group.getId(), group.getId(), toParent == null ? null : toParent.getId(), realmId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("GroupMovedEvent [ realmId=%s, groupId=%s, newParentId=%s, oldParentId=%s ]", realmId, groupId, newParentId, oldParentId);
|
return String.format("GroupMovedEvent [ realmId=%s, groupId=%s, newParentId=%s, oldParentId=%s ]", realmId, getId(), newParentId, oldParentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
||||||
realmCache.groupQueriesInvalidations(realmId, invalidations);
|
realmCache.groupQueriesInvalidations(realmId, invalidations);
|
||||||
realmCache.groupNameInvalidations(groupId, invalidations);
|
realmCache.groupNameInvalidations(getId(), invalidations);
|
||||||
if (newParentId != null) {
|
if (newParentId != null) {
|
||||||
invalidations.add(newParentId);
|
invalidations.add(newParentId);
|
||||||
}
|
}
|
||||||
|
@ -76,47 +78,19 @@ public class GroupMovedEvent extends InvalidationEvent implements RealmCacheInva
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
if (!super.equals(o)) return false;
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
GroupMovedEvent that = (GroupMovedEvent) o;
|
GroupMovedEvent that = (GroupMovedEvent) o;
|
||||||
return Objects.equals(groupId, that.groupId) && Objects.equals(newParentId, that.newParentId) && Objects.equals(oldParentId, that.oldParentId) && Objects.equals(realmId, that.realmId);
|
return Objects.equals(newParentId, that.newParentId) &&
|
||||||
|
Objects.equals(oldParentId, that.oldParentId) &&
|
||||||
|
realmId.equals(that.realmId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(super.hashCode(), groupId, newParentId, oldParentId, realmId);
|
int result = super.hashCode();
|
||||||
}
|
result = 31 * result + Objects.hashCode(newParentId);
|
||||||
|
result = 31 * result + Objects.hashCode(oldParentId);
|
||||||
public static class ExternalizerImpl implements Externalizer<GroupMovedEvent> {
|
result = 31 * result + realmId.hashCode();
|
||||||
|
return result;
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, GroupMovedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.groupId, output);
|
|
||||||
MarshallUtil.marshallString(obj.newParentId, output);
|
|
||||||
MarshallUtil.marshallString(obj.oldParentId, output);
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupMovedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GroupMovedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
GroupMovedEvent res = new GroupMovedEvent();
|
|
||||||
res.groupId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.newParentId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.oldParentId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,47 +20,48 @@ package org.keycloak.models.cache.infinispan.events;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.GroupModel;
|
import org.keycloak.models.GroupModel;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(GroupRemovedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.GROUP_REMOVED_EVENT)
|
||||||
public class GroupRemovedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
public class GroupRemovedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
||||||
|
|
||||||
private String groupId;
|
@ProtoField(2)
|
||||||
private String parentId;
|
final String realmId;
|
||||||
private String realmId;
|
@ProtoField(3)
|
||||||
|
final String parentId;
|
||||||
|
|
||||||
public static GroupRemovedEvent create(GroupModel group, String realmId) {
|
public GroupRemovedEvent(String groupId, String realmId, String parentId) {
|
||||||
GroupRemovedEvent event = new GroupRemovedEvent();
|
super(groupId);
|
||||||
event.realmId = realmId;
|
this.realmId = Objects.requireNonNull(realmId);
|
||||||
event.groupId = group.getId();
|
this.parentId = parentId;
|
||||||
event.parentId = group.getParentId();
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@ProtoFactory
|
||||||
public String getId() {
|
static GroupRemovedEvent protoFactory(String id, String realmId, String parentId) {
|
||||||
return groupId;
|
return new GroupRemovedEvent(id, realmId, Marshalling.emptyStringToNull(parentId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupRemovedEvent create(GroupModel group, String realmId) {
|
||||||
|
return new GroupRemovedEvent(group.getId(), realmId, group.getParentId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("GroupRemovedEvent [ realmId=%s, groupId=%s, parentId=%s ]", realmId, groupId, parentId);
|
return String.format("GroupRemovedEvent [ realmId=%s, groupId=%s, parentId=%s ]", realmId, getId(), parentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
||||||
realmCache.groupQueriesInvalidations(realmId, invalidations);
|
realmCache.groupQueriesInvalidations(realmId, invalidations);
|
||||||
realmCache.groupNameInvalidations(groupId, invalidations);
|
realmCache.groupNameInvalidations(getId(), invalidations);
|
||||||
if (parentId != null) {
|
if (parentId != null) {
|
||||||
invalidations.add(parentId);
|
invalidations.add(parentId);
|
||||||
}
|
}
|
||||||
|
@ -71,45 +72,16 @@ public class GroupRemovedEvent extends InvalidationEvent implements RealmCacheIn
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
if (!super.equals(o)) return false;
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
GroupRemovedEvent that = (GroupRemovedEvent) o;
|
GroupRemovedEvent that = (GroupRemovedEvent) o;
|
||||||
return Objects.equals(groupId, that.groupId) && Objects.equals(parentId, that.parentId) && Objects.equals(realmId, that.realmId);
|
return realmId.equals(that.realmId) && Objects.equals(parentId, that.parentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(super.hashCode(), groupId, parentId, realmId);
|
int result = super.hashCode();
|
||||||
}
|
result = 31 * result + realmId.hashCode();
|
||||||
|
result = 31 * result + Objects.hashCode(parentId);
|
||||||
public static class ExternalizerImpl implements Externalizer<GroupRemovedEvent> {
|
return result;
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, GroupRemovedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
MarshallUtil.marshallString(obj.groupId, output);
|
|
||||||
MarshallUtil.marshallString(obj.parentId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupRemovedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GroupRemovedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
GroupRemovedEvent res = new GroupRemovedEvent();
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.groupId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.parentId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,70 +19,34 @@ package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(GroupUpdatedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.GROUP_UPDATED_EVENT)
|
||||||
public class GroupUpdatedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
public class GroupUpdatedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
||||||
|
|
||||||
private String groupId;
|
@ProtoFactory
|
||||||
|
GroupUpdatedEvent(String id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
public static GroupUpdatedEvent create(String groupId) {
|
public static GroupUpdatedEvent create(String groupId) {
|
||||||
GroupUpdatedEvent event = new GroupUpdatedEvent();
|
return new GroupUpdatedEvent(groupId);
|
||||||
event.groupId = groupId;
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return groupId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "GroupUpdatedEvent [ " + groupId + " ]";
|
return "GroupUpdatedEvent [ " + getId() + " ]";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
||||||
realmCache.groupNameInvalidations(groupId, invalidations);
|
realmCache.groupNameInvalidations(getId(), invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<GroupUpdatedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, GroupUpdatedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.groupId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupUpdatedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GroupUpdatedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
GroupUpdatedEvent res = new GroupUpdatedEvent();
|
|
||||||
res.groupId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.events;
|
package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
import org.keycloak.cluster.ClusterEvent;
|
import org.keycloak.cluster.ClusterEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,7 +27,16 @@ import org.keycloak.cluster.ClusterEvent;
|
||||||
*/
|
*/
|
||||||
public abstract class InvalidationEvent implements ClusterEvent {
|
public abstract class InvalidationEvent implements ClusterEvent {
|
||||||
|
|
||||||
public abstract String getId();
|
private final String id;
|
||||||
|
|
||||||
|
protected InvalidationEvent(String id) {
|
||||||
|
this.id = Objects.requireNonNull(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtoField(1)
|
||||||
|
public final String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
|
@ -37,7 +49,6 @@ public abstract class InvalidationEvent implements ClusterEvent {
|
||||||
if (!obj.getClass().equals(this.getClass())) return false;
|
if (!obj.getClass().equals(this.getClass())) return false;
|
||||||
|
|
||||||
InvalidationEvent that = (InvalidationEvent) obj;
|
InvalidationEvent that = (InvalidationEvent) obj;
|
||||||
if (!that.getId().equals(getId())) return false;
|
return that.getId().equals(getId());
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,90 +17,30 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.events;
|
package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(RealmRemovedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.REALM_REMOVED_EVENT)
|
||||||
public class RealmRemovedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
public class RealmRemovedEvent extends BaseRealmEvent {
|
||||||
|
|
||||||
private String realmId;
|
@ProtoFactory
|
||||||
private String realmName;
|
RealmRemovedEvent(String id, String realmName) {
|
||||||
|
super(id, realmName);
|
||||||
|
}
|
||||||
|
|
||||||
public static RealmRemovedEvent create(String realmId, String realmName) {
|
public static RealmRemovedEvent create(String realmId, String realmName) {
|
||||||
RealmRemovedEvent event = new RealmRemovedEvent();
|
return new RealmRemovedEvent(realmId, realmName);
|
||||||
event.realmId = realmId;
|
|
||||||
event.realmName = realmName;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return realmId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("RealmRemovedEvent [ realmId=%s, realmName=%s ]", realmId, realmName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
||||||
realmCache.realmRemoval(realmId, realmName, invalidations);
|
realmCache.realmRemoval(getId(), realmName, invalidations);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
RealmRemovedEvent that = (RealmRemovedEvent) o;
|
|
||||||
return Objects.equals(realmId, that.realmId) && Objects.equals(realmName, that.realmName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), realmId, realmName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<RealmRemovedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, RealmRemovedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
MarshallUtil.marshallString(obj.realmName, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RealmRemovedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RealmRemovedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
RealmRemovedEvent res = new RealmRemovedEvent();
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.realmName = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,90 +17,30 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.events;
|
package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(RealmUpdatedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.REALM_UPDATED_EVENT)
|
||||||
public class RealmUpdatedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
public class RealmUpdatedEvent extends BaseRealmEvent {
|
||||||
|
|
||||||
private String realmId;
|
@ProtoFactory
|
||||||
private String realmName;
|
RealmUpdatedEvent(String id, String realmName) {
|
||||||
|
super(id, realmName);
|
||||||
|
}
|
||||||
|
|
||||||
public static RealmUpdatedEvent create(String realmId, String realmName) {
|
public static RealmUpdatedEvent create(String realmId, String realmName) {
|
||||||
RealmUpdatedEvent event = new RealmUpdatedEvent();
|
return new RealmUpdatedEvent(realmId, realmName);
|
||||||
event.realmId = realmId;
|
|
||||||
event.realmName = realmName;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return realmId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("RealmUpdatedEvent [ realmId=%s, realmName=%s ]", realmId, realmName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
||||||
realmCache.realmUpdated(realmId, realmName, invalidations);
|
realmCache.realmUpdated(getId(), realmName, invalidations);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
RealmUpdatedEvent that = (RealmUpdatedEvent) o;
|
|
||||||
return Objects.equals(realmId, that.realmId) && Objects.equals(realmName, that.realmName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), realmId, realmName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<RealmUpdatedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, RealmUpdatedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
MarshallUtil.marshallString(obj.realmName, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RealmUpdatedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RealmUpdatedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
RealmUpdatedEvent res = new RealmUpdatedEvent();
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.realmName = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,90 +17,30 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.events;
|
package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(RoleAddedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.ROLE_ADDED_EVENT)
|
||||||
public class RoleAddedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
public class RoleAddedEvent extends BaseRoleEvent {
|
||||||
|
|
||||||
private String roleId;
|
@ProtoFactory
|
||||||
private String containerId;
|
RoleAddedEvent(String id, String containerId) {
|
||||||
|
super(id, containerId);
|
||||||
|
}
|
||||||
|
|
||||||
public static RoleAddedEvent create(String roleId, String containerId) {
|
public static RoleAddedEvent create(String roleId, String containerId) {
|
||||||
RoleAddedEvent event = new RoleAddedEvent();
|
return new RoleAddedEvent(roleId, containerId);
|
||||||
event.roleId = roleId;
|
|
||||||
event.containerId = containerId;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return roleId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("RoleAddedEvent [ roleId=%s, containerId=%s ]", roleId, containerId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
||||||
realmCache.roleAdded(containerId, invalidations);
|
realmCache.roleAdded(containerId, invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
if (!super.equals(o)) return false;
|
|
||||||
RoleAddedEvent that = (RoleAddedEvent) o;
|
|
||||||
return Objects.equals(roleId, that.roleId) && Objects.equals(containerId, that.containerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), roleId, containerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<RoleAddedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, RoleAddedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.roleId, output);
|
|
||||||
MarshallUtil.marshallString(obj.containerId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RoleAddedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RoleAddedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
RoleAddedEvent res = new RoleAddedEvent();
|
|
||||||
res.roleId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.containerId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,45 +20,34 @@ package org.keycloak.models.cache.infinispan.events;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(RoleRemovedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.ROLE_REMOVED_EVENT)
|
||||||
public class RoleRemovedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
public class RoleRemovedEvent extends BaseRoleEvent {
|
||||||
|
|
||||||
private String roleId;
|
@ProtoField(3)
|
||||||
private String roleName;
|
final String roleName;
|
||||||
private String containerId;
|
|
||||||
|
@ProtoFactory
|
||||||
|
RoleRemovedEvent(String id, String containerId, String roleName) {
|
||||||
|
super(id, containerId);
|
||||||
|
this.roleName = Objects.requireNonNull(roleName);
|
||||||
|
}
|
||||||
|
|
||||||
public static RoleRemovedEvent create(String roleId, String roleName, String containerId) {
|
public static RoleRemovedEvent create(String roleId, String roleName, String containerId) {
|
||||||
RoleRemovedEvent event = new RoleRemovedEvent();
|
return new RoleRemovedEvent(roleId, containerId, roleName);
|
||||||
event.roleId = roleId;
|
|
||||||
event.roleName = roleName;
|
|
||||||
event.containerId = containerId;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return roleId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("RoleRemovedEvent [ roleId=%s, containerId=%s ]", roleId, containerId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
public void addInvalidations(RealmCacheManager realmCache, Set<String> invalidations) {
|
||||||
realmCache.roleRemoval(roleId, roleName, containerId, invalidations);
|
realmCache.roleRemoval(getId(), roleName, containerId, invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -66,45 +55,15 @@ public class RoleRemovedEvent extends InvalidationEvent implements RealmCacheInv
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
if (!super.equals(o)) return false;
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
RoleRemovedEvent that = (RoleRemovedEvent) o;
|
RoleRemovedEvent that = (RoleRemovedEvent) o;
|
||||||
return Objects.equals(roleId, that.roleId) && Objects.equals(roleName, that.roleName) && Objects.equals(containerId, that.containerId);
|
return roleName.equals(that.roleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(super.hashCode(), roleId, roleName, containerId);
|
int result = super.hashCode();
|
||||||
}
|
result = 31 * result + roleName.hashCode();
|
||||||
|
return result;
|
||||||
public static class ExternalizerImpl implements Externalizer<RoleRemovedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, RoleRemovedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.roleId, output);
|
|
||||||
MarshallUtil.marshallString(obj.roleName, output);
|
|
||||||
MarshallUtil.marshallString(obj.containerId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RoleRemovedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RoleRemovedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
RoleRemovedEvent res = new RoleRemovedEvent();
|
|
||||||
res.roleId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.roleName = MarshallUtil.unmarshallString(input);
|
|
||||||
res.containerId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,40 +20,34 @@ package org.keycloak.models.cache.infinispan.events;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
import org.keycloak.models.cache.infinispan.RealmCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(RoleUpdatedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.ROLE_UPDATED_EVENT)
|
||||||
public class RoleUpdatedEvent extends InvalidationEvent implements RealmCacheInvalidationEvent {
|
public class RoleUpdatedEvent extends BaseRoleEvent {
|
||||||
|
|
||||||
private String roleId;
|
@ProtoField(3)
|
||||||
private String roleName;
|
final String roleName;
|
||||||
private String containerId;
|
|
||||||
|
|
||||||
public static RoleUpdatedEvent create(String roleId, String roleName, String containerId) {
|
@ProtoFactory
|
||||||
RoleUpdatedEvent event = new RoleUpdatedEvent();
|
RoleUpdatedEvent(String id, String containerId, String roleName) {
|
||||||
event.roleId = roleId;
|
super(id, containerId);
|
||||||
event.roleName = roleName;
|
this.roleName = Objects.requireNonNull(roleName);
|
||||||
event.containerId = containerId;
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static RoleUpdatedEvent create(String roleId, String roleName, String containerId) {
|
||||||
public String getId() {
|
return new RoleUpdatedEvent(roleId, containerId, roleName);
|
||||||
return roleId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("RoleUpdatedEvent [ roleId=%s, roleName=%s, containerId=%s ]", roleId, roleName, containerId);
|
return String.format("RoleUpdatedEvent [ roleId=%s, roleName=%s, containerId=%s ]", getId(), roleName, containerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -66,45 +60,15 @@ public class RoleUpdatedEvent extends InvalidationEvent implements RealmCacheInv
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
if (!super.equals(o)) return false;
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
RoleUpdatedEvent that = (RoleUpdatedEvent) o;
|
RoleUpdatedEvent that = (RoleUpdatedEvent) o;
|
||||||
return Objects.equals(roleId, that.roleId) && Objects.equals(roleName, that.roleName) && Objects.equals(containerId, that.containerId);
|
return roleName.equals(that.roleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(super.hashCode(), roleId, roleName, containerId);
|
int result = super.hashCode();
|
||||||
}
|
result = 31 * result + roleName.hashCode();
|
||||||
|
return result;
|
||||||
public static class ExternalizerImpl implements Externalizer<RoleUpdatedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, RoleUpdatedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.roleId, output);
|
|
||||||
MarshallUtil.marshallString(obj.roleName, output);
|
|
||||||
MarshallUtil.marshallString(obj.containerId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RoleUpdatedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RoleUpdatedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
RoleUpdatedEvent res = new RoleUpdatedEvent();
|
|
||||||
res.roleId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.roleName = MarshallUtil.unmarshallString(input);
|
|
||||||
res.containerId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,69 +19,34 @@ package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.UserCacheManager;
|
import org.keycloak.models.cache.infinispan.UserCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(UserCacheRealmInvalidationEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.USER_CACHE_REALM_INVALIDATION_EVENT)
|
||||||
public class UserCacheRealmInvalidationEvent extends InvalidationEvent implements UserCacheInvalidationEvent {
|
public class UserCacheRealmInvalidationEvent extends InvalidationEvent implements UserCacheInvalidationEvent {
|
||||||
|
|
||||||
private String realmId;
|
private UserCacheRealmInvalidationEvent(String id) {
|
||||||
|
super(id);
|
||||||
public static UserCacheRealmInvalidationEvent create(String realmId) {
|
|
||||||
UserCacheRealmInvalidationEvent event = new UserCacheRealmInvalidationEvent();
|
|
||||||
event.realmId = realmId;
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@ProtoFactory
|
||||||
public String getId() {
|
public static UserCacheRealmInvalidationEvent create(String id) {
|
||||||
return realmId; // Just a placeholder
|
return new UserCacheRealmInvalidationEvent(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("UserCacheRealmInvalidationEvent [ realmId=%s ]", realmId);
|
return String.format("UserCacheRealmInvalidationEvent [ realmId=%s ]", getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(UserCacheManager userCache, Set<String> invalidations) {
|
public void addInvalidations(UserCacheManager userCache, Set<String> invalidations) {
|
||||||
userCache.invalidateRealmUsers(realmId, invalidations);
|
userCache.invalidateRealmUsers(getId(), invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<UserCacheRealmInvalidationEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, UserCacheRealmInvalidationEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserCacheRealmInvalidationEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserCacheRealmInvalidationEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
UserCacheRealmInvalidationEvent res = new UserCacheRealmInvalidationEvent();
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,69 +19,34 @@ package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.UserCacheManager;
|
import org.keycloak.models.cache.infinispan.UserCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(UserConsentsUpdatedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.USER_CONSENTS_UPDATED_EVENT)
|
||||||
public class UserConsentsUpdatedEvent extends InvalidationEvent implements UserCacheInvalidationEvent {
|
public class UserConsentsUpdatedEvent extends InvalidationEvent implements UserCacheInvalidationEvent {
|
||||||
|
|
||||||
private String userId;
|
private UserConsentsUpdatedEvent(String id) {
|
||||||
|
super(id);
|
||||||
public static UserConsentsUpdatedEvent create(String userId) {
|
|
||||||
UserConsentsUpdatedEvent event = new UserConsentsUpdatedEvent();
|
|
||||||
event.userId = userId;
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@ProtoFactory
|
||||||
public String getId() {
|
public static UserConsentsUpdatedEvent create(String id) {
|
||||||
return userId;
|
return new UserConsentsUpdatedEvent(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("UserConsentsUpdatedEvent [ userId=%s ]", userId);
|
return String.format("UserConsentsUpdatedEvent [ userId=%s ]", getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(UserCacheManager userCache, Set<String> invalidations) {
|
public void addInvalidations(UserCacheManager userCache, Set<String> invalidations) {
|
||||||
userCache.consentInvalidation(userId, invalidations);
|
userCache.consentInvalidation(getId(), invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<UserConsentsUpdatedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, UserConsentsUpdatedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.userId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserConsentsUpdatedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserConsentsUpdatedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
UserConsentsUpdatedEvent res = new UserConsentsUpdatedEvent();
|
|
||||||
res.userId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,62 +20,65 @@ package org.keycloak.models.cache.infinispan.events;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
import org.keycloak.models.cache.infinispan.UserCacheManager;
|
import org.keycloak.models.cache.infinispan.UserCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(UserFederationLinkRemovedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.USER_FEDERATION_LINK_REMOVED_EVENT)
|
||||||
public class UserFederationLinkRemovedEvent extends InvalidationEvent implements UserCacheInvalidationEvent {
|
public class UserFederationLinkRemovedEvent extends InvalidationEvent implements UserCacheInvalidationEvent {
|
||||||
|
|
||||||
private String userId;
|
final String realmId;
|
||||||
private String realmId;
|
final String identityProviderId;
|
||||||
private String identityProviderId;
|
final String socialUserId;
|
||||||
private String socialUserId;
|
|
||||||
|
private UserFederationLinkRemovedEvent(String id, String realmId, String identityProviderId, String socialUserId) {
|
||||||
|
super(id);
|
||||||
|
this.realmId = Objects.requireNonNull(realmId);
|
||||||
|
// may be null
|
||||||
|
this.identityProviderId = identityProviderId;
|
||||||
|
this.socialUserId = socialUserId;
|
||||||
|
}
|
||||||
|
|
||||||
public static UserFederationLinkRemovedEvent create(String userId, String realmId, FederatedIdentityModel socialLink) {
|
public static UserFederationLinkRemovedEvent create(String userId, String realmId, FederatedIdentityModel socialLink) {
|
||||||
UserFederationLinkRemovedEvent event = new UserFederationLinkRemovedEvent();
|
String identityProviderId = socialLink == null ? null : socialLink.getIdentityProvider();
|
||||||
event.userId = userId;
|
String socialUserId = socialLink == null ? null : socialLink.getUserId();
|
||||||
event.realmId = realmId;
|
return new UserFederationLinkRemovedEvent(userId, realmId, identityProviderId, socialUserId);
|
||||||
if (socialLink != null) {
|
|
||||||
event.identityProviderId = socialLink.getIdentityProvider();
|
|
||||||
event.socialUserId = socialLink.getUserId();
|
|
||||||
}
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@ProtoFactory
|
||||||
public String getId() {
|
static UserFederationLinkRemovedEvent protoFactory(String id, String realmId, String identityProviderId, String socialUserId) {
|
||||||
return userId;
|
return new UserFederationLinkRemovedEvent(id, realmId, Marshalling.emptyStringToNull(identityProviderId), Marshalling.emptyStringToNull(socialUserId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
public String getRealmId() {
|
public String getRealmId() {
|
||||||
return realmId;
|
return realmId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(3)
|
||||||
public String getIdentityProviderId() {
|
public String getIdentityProviderId() {
|
||||||
return identityProviderId;
|
return identityProviderId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(4)
|
||||||
public String getSocialUserId() {
|
public String getSocialUserId() {
|
||||||
return socialUserId;
|
return socialUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("UserFederationLinkRemovedEvent [ userId=%s, identityProviderId=%s, socialUserId=%s ]", userId, identityProviderId, socialUserId);
|
return String.format("UserFederationLinkRemovedEvent [ userId=%s, identityProviderId=%s, socialUserId=%s ]", getId(), identityProviderId, socialUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(UserCacheManager userCache, Set<String> invalidations) {
|
public void addInvalidations(UserCacheManager userCache, Set<String> invalidations) {
|
||||||
userCache.federatedIdentityLinkRemovedInvalidation(userId, realmId, identityProviderId, socialUserId, invalidations);
|
userCache.federatedIdentityLinkRemovedInvalidation(getId(), realmId, identityProviderId, socialUserId, invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -84,46 +87,12 @@ public class UserFederationLinkRemovedEvent extends InvalidationEvent implements
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
if (!super.equals(o)) return false;
|
if (!super.equals(o)) return false;
|
||||||
UserFederationLinkRemovedEvent that = (UserFederationLinkRemovedEvent) o;
|
UserFederationLinkRemovedEvent that = (UserFederationLinkRemovedEvent) o;
|
||||||
return Objects.equals(userId, that.userId) && Objects.equals(realmId, that.realmId) && Objects.equals(identityProviderId, that.identityProviderId) && Objects.equals(socialUserId, that.socialUserId);
|
return Objects.equals(realmId, that.realmId) && Objects.equals(identityProviderId, that.identityProviderId) && Objects.equals(socialUserId, that.socialUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(super.hashCode(), userId, realmId, identityProviderId, socialUserId);
|
return Objects.hash(super.hashCode(), realmId, identityProviderId, socialUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<UserFederationLinkRemovedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, UserFederationLinkRemovedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.userId, output);
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
MarshallUtil.marshallString(obj.identityProviderId, output);
|
|
||||||
MarshallUtil.marshallString(obj.socialUserId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserFederationLinkRemovedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserFederationLinkRemovedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
UserFederationLinkRemovedEvent res = new UserFederationLinkRemovedEvent();
|
|
||||||
res.userId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.identityProviderId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.socialUserId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,69 +18,34 @@ package org.keycloak.models.cache.infinispan.events;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.UserCacheManager;
|
import org.keycloak.models.cache.infinispan.UserCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(UserFederationLinkUpdatedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.USER_FEDERATION_LINK_UPDATED_EVENT)
|
||||||
public class UserFederationLinkUpdatedEvent extends InvalidationEvent implements UserCacheInvalidationEvent {
|
public class UserFederationLinkUpdatedEvent extends InvalidationEvent implements UserCacheInvalidationEvent {
|
||||||
|
|
||||||
private String userId;
|
private UserFederationLinkUpdatedEvent(String id) {
|
||||||
|
super(id);
|
||||||
public static UserFederationLinkUpdatedEvent create(String userId) {
|
|
||||||
UserFederationLinkUpdatedEvent event = new UserFederationLinkUpdatedEvent();
|
|
||||||
event.userId = userId;
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@ProtoFactory
|
||||||
public String getId() {
|
public static UserFederationLinkUpdatedEvent create(String id) {
|
||||||
return userId;
|
return new UserFederationLinkUpdatedEvent(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("UserFederationLinkUpdatedEvent [ userId=%s ]", userId);
|
return String.format("UserFederationLinkUpdatedEvent [ userId=%s ]", getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(UserCacheManager userCache, Set<String> invalidations) {
|
public void addInvalidations(UserCacheManager userCache, Set<String> invalidations) {
|
||||||
userCache.federatedIdentityLinkUpdatedInvalidation(userId, invalidations);
|
userCache.federatedIdentityLinkUpdatedInvalidation(getId(), invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<UserFederationLinkUpdatedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, UserFederationLinkUpdatedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.userId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserFederationLinkUpdatedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserFederationLinkUpdatedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
UserFederationLinkUpdatedEvent res = new UserFederationLinkUpdatedEvent();
|
|
||||||
res.userId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,54 +21,56 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
|
||||||
import org.keycloak.models.cache.infinispan.UserCacheManager;
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.KeycloakMarshallUtil;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
|
import org.keycloak.models.cache.infinispan.UserCacheManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used when user added/removed
|
* Used when user added/removed
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(UserFullInvalidationEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.USER_FULL_INVALIDATION_EVENT)
|
||||||
public class UserFullInvalidationEvent extends InvalidationEvent implements UserCacheInvalidationEvent {
|
public class UserFullInvalidationEvent extends InvalidationEvent implements UserCacheInvalidationEvent {
|
||||||
|
|
||||||
private String userId;
|
@ProtoField(2)
|
||||||
private String username;
|
final String username;
|
||||||
private String email;
|
@ProtoField(3)
|
||||||
private String realmId;
|
final String email;
|
||||||
private boolean identityFederationEnabled;
|
@ProtoField(4)
|
||||||
private Map<String, String> federatedIdentities;
|
final String realmId;
|
||||||
|
@ProtoField(5)
|
||||||
|
final boolean identityFederationEnabled;
|
||||||
|
@ProtoField(value = 6, mapImplementation = HashMap.class)
|
||||||
|
final Map<String, String> federatedIdentities;
|
||||||
|
|
||||||
|
private UserFullInvalidationEvent(String id, String username, String email, String realmId, boolean identityFederationEnabled, Map<String, String> federatedIdentities) {
|
||||||
|
super(id);
|
||||||
|
this.username = Objects.requireNonNull(username);
|
||||||
|
this.email = email;
|
||||||
|
this.realmId = Objects.requireNonNull(realmId);
|
||||||
|
this.federatedIdentities = federatedIdentities;
|
||||||
|
this.identityFederationEnabled = identityFederationEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
public static UserFullInvalidationEvent create(String userId, String username, String email, String realmId, boolean identityFederationEnabled, Stream<FederatedIdentityModel> federatedIdentities) {
|
public static UserFullInvalidationEvent create(String userId, String username, String email, String realmId, boolean identityFederationEnabled, Stream<FederatedIdentityModel> federatedIdentities) {
|
||||||
UserFullInvalidationEvent event = new UserFullInvalidationEvent();
|
Map<String, String> federatedIdentitiesMap = null;
|
||||||
event.userId = userId;
|
|
||||||
event.username = username;
|
|
||||||
event.email = email;
|
|
||||||
event.realmId = realmId;
|
|
||||||
|
|
||||||
event.identityFederationEnabled = identityFederationEnabled;
|
|
||||||
if (identityFederationEnabled) {
|
if (identityFederationEnabled) {
|
||||||
event.federatedIdentities = federatedIdentities.collect(Collectors.toMap(socialLink -> socialLink.getIdentityProvider(),
|
federatedIdentitiesMap = federatedIdentities.collect(Collectors.toMap(FederatedIdentityModel::getIdentityProvider,
|
||||||
socialLink -> socialLink.getUserId()));
|
FederatedIdentityModel::getUserId));
|
||||||
|
}
|
||||||
|
return new UserFullInvalidationEvent(userId, username, email, realmId, identityFederationEnabled, federatedIdentitiesMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
return event;
|
@ProtoFactory
|
||||||
}
|
static UserFullInvalidationEvent protoFactory(String id, String username, String email, String realmId, boolean identityFederationEnabled, Map<String, String> federatedIdentities) {
|
||||||
|
return new UserFullInvalidationEvent(id, username, Marshalling.emptyStringToNull(email), realmId, identityFederationEnabled, federatedIdentities);
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return userId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getFederatedIdentities() {
|
public Map<String, String> getFederatedIdentities() {
|
||||||
|
@ -77,12 +79,12 @@ public class UserFullInvalidationEvent extends InvalidationEvent implements User
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("UserFullInvalidationEvent [ userId=%s, username=%s, email=%s ]", userId, username, email);
|
return String.format("UserFullInvalidationEvent [ userId=%s, username=%s, email=%s ]", getId(), username, email);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(UserCacheManager userCache, Set<String> invalidations) {
|
public void addInvalidations(UserCacheManager userCache, Set<String> invalidations) {
|
||||||
userCache.fullUserInvalidation(userId, username, email, realmId, identityFederationEnabled, federatedIdentities, invalidations);
|
userCache.fullUserInvalidation(getId(), username, email, realmId, identityFederationEnabled, federatedIdentities, invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -91,50 +93,12 @@ public class UserFullInvalidationEvent extends InvalidationEvent implements User
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
if (!super.equals(o)) return false;
|
if (!super.equals(o)) return false;
|
||||||
UserFullInvalidationEvent that = (UserFullInvalidationEvent) o;
|
UserFullInvalidationEvent that = (UserFullInvalidationEvent) o;
|
||||||
return identityFederationEnabled == that.identityFederationEnabled && Objects.equals(userId, that.userId) && Objects.equals(username, that.username) && Objects.equals(email, that.email) && Objects.equals(realmId, that.realmId) && Objects.equals(federatedIdentities, that.federatedIdentities);
|
return identityFederationEnabled == that.identityFederationEnabled && Objects.equals(username, that.username) && Objects.equals(email, that.email) && Objects.equals(realmId, that.realmId) && Objects.equals(federatedIdentities, that.federatedIdentities);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(super.hashCode(), userId, username, email, realmId, identityFederationEnabled, federatedIdentities);
|
return Objects.hash(super.hashCode(), username, email, realmId, identityFederationEnabled, federatedIdentities);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<UserFullInvalidationEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, UserFullInvalidationEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.userId, output);
|
|
||||||
MarshallUtil.marshallString(obj.username, output);
|
|
||||||
MarshallUtil.marshallString(obj.email, output);
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
output.writeBoolean(obj.identityFederationEnabled);
|
|
||||||
KeycloakMarshallUtil.writeMap(obj.federatedIdentities, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserFullInvalidationEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserFullInvalidationEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
UserFullInvalidationEvent res = new UserFullInvalidationEvent();
|
|
||||||
res.userId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.username = MarshallUtil.unmarshallString(input);
|
|
||||||
res.email = MarshallUtil.unmarshallString(input);
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.identityFederationEnabled = input.readBoolean();
|
|
||||||
res.federatedIdentities = KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, HashMap::new);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,47 +20,49 @@ package org.keycloak.models.cache.infinispan.events;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.cache.infinispan.UserCacheManager;
|
import org.keycloak.models.cache.infinispan.UserCacheManager;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(UserUpdatedEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.USER_UPDATED_EVENT)
|
||||||
public class UserUpdatedEvent extends InvalidationEvent implements UserCacheInvalidationEvent {
|
public class UserUpdatedEvent extends InvalidationEvent implements UserCacheInvalidationEvent {
|
||||||
|
|
||||||
private String userId;
|
@ProtoField(2)
|
||||||
private String username;
|
final String username;
|
||||||
private String email;
|
@ProtoField(3)
|
||||||
private String realmId;
|
final String email;
|
||||||
|
@ProtoField(4)
|
||||||
|
final String realmId;
|
||||||
|
|
||||||
public static UserUpdatedEvent create(String userId, String username, String email, String realmId) {
|
private UserUpdatedEvent(String id, String username, String email, String realmId) {
|
||||||
UserUpdatedEvent event = new UserUpdatedEvent();
|
super(id);
|
||||||
event.userId = userId;
|
this.username = Objects.requireNonNull(username);
|
||||||
event.username = username;
|
this.email = email;
|
||||||
event.email = email;
|
this.realmId = Objects.requireNonNull(realmId);
|
||||||
event.realmId = realmId;
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static UserUpdatedEvent create(String id, String username, String email, String realmId) {
|
||||||
public String getId() {
|
return new UserUpdatedEvent(id, username, email, realmId);
|
||||||
return userId;
|
}
|
||||||
|
|
||||||
|
@ProtoFactory
|
||||||
|
static UserUpdatedEvent protoFactory(String id, String username, String email, String realmId) {
|
||||||
|
return new UserUpdatedEvent(id, username, Marshalling.emptyStringToNull(email), realmId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("UserUpdatedEvent [ userId=%s, username=%s, email=%s ]", userId, username, email);
|
return String.format("UserUpdatedEvent [ userId=%s, username=%s, email=%s ]", getId(), username, email);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidations(UserCacheManager userCache, Set<String> invalidations) {
|
public void addInvalidations(UserCacheManager userCache, Set<String> invalidations) {
|
||||||
userCache.userUpdatedInvalidations(userId, username, email, realmId, invalidations);
|
userCache.userUpdatedInvalidations(getId(), username, email, realmId, invalidations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -69,46 +71,12 @@ public class UserUpdatedEvent extends InvalidationEvent implements UserCacheInva
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
if (!super.equals(o)) return false;
|
if (!super.equals(o)) return false;
|
||||||
UserUpdatedEvent that = (UserUpdatedEvent) o;
|
UserUpdatedEvent that = (UserUpdatedEvent) o;
|
||||||
return Objects.equals(userId, that.userId) && Objects.equals(username, that.username) && Objects.equals(email, that.email) && Objects.equals(realmId, that.realmId);
|
return Objects.equals(username, that.username) && Objects.equals(email, that.email) && Objects.equals(realmId, that.realmId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(super.hashCode(), userId, username, email, realmId);
|
return Objects.hash(super.hashCode(), username, email, realmId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<UserUpdatedEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, UserUpdatedEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.userId, output);
|
|
||||||
MarshallUtil.marshallString(obj.username, output);
|
|
||||||
MarshallUtil.marshallString(obj.email, output);
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserUpdatedEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserUpdatedEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
UserUpdatedEvent res = new UserUpdatedEvent();
|
|
||||||
res.userId = MarshallUtil.unmarshallString(input);
|
|
||||||
res.username = MarshallUtil.unmarshallString(input);
|
|
||||||
res.email = MarshallUtil.unmarshallString(input);
|
|
||||||
res.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,20 @@
|
||||||
package org.keycloak.models.cache.infinispan.stream;
|
package org.keycloak.models.cache.infinispan.stream;
|
||||||
|
|
||||||
import org.keycloak.models.cache.infinispan.entities.GroupListQuery;
|
|
||||||
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.GroupListQuery;
|
||||||
|
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 $
|
||||||
*/
|
*/
|
||||||
@SerializeWith(GroupListPredicate.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.GROUP_LIST_PREDICATE)
|
||||||
public class GroupListPredicate implements Predicate<Map.Entry<String, Revisioned>>, Serializable {
|
public class GroupListPredicate implements Predicate<Map.Entry<String, Revisioned>> {
|
||||||
private String realm;
|
private String realm;
|
||||||
|
|
||||||
public static GroupListPredicate create() {
|
public static GroupListPredicate create() {
|
||||||
|
@ -30,43 +26,18 @@ public class GroupListPredicate implements Predicate<Map.Entry<String, Revisione
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(1)
|
||||||
|
String getRealm() {
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRealm(String realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean test(Map.Entry<String, Revisioned> entry) {
|
public boolean test(Map.Entry<String, Revisioned> entry) {
|
||||||
Object value = entry.getValue();
|
return entry.getValue() instanceof GroupListQuery groupList && groupList.getRealm().equals(realm);
|
||||||
if (value == null) return false;
|
|
||||||
if (value instanceof GroupListQuery) {
|
|
||||||
GroupListQuery groupList = (GroupListQuery)value;
|
|
||||||
if (groupList.getRealm().equals(realm)) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<GroupListPredicate> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, GroupListPredicate obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.realm, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupListPredicate readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GroupListPredicate readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
GroupListPredicate res = new GroupListPredicate();
|
|
||||||
res.realm = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,25 @@
|
||||||
package org.keycloak.models.cache.infinispan.stream;
|
package org.keycloak.models.cache.infinispan.stream;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import org.keycloak.models.cache.infinispan.entities.CachedClient;
|
import org.keycloak.models.cache.infinispan.entities.CachedClient;
|
||||||
import org.keycloak.models.cache.infinispan.entities.CachedClientScope;
|
import org.keycloak.models.cache.infinispan.entities.CachedClientScope;
|
||||||
import org.keycloak.models.cache.infinispan.entities.CachedGroup;
|
import org.keycloak.models.cache.infinispan.entities.CachedGroup;
|
||||||
import org.keycloak.models.cache.infinispan.entities.CachedRole;
|
import org.keycloak.models.cache.infinispan.entities.CachedRole;
|
||||||
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
||||||
import org.keycloak.models.cache.infinispan.entities.RoleQuery;
|
import org.keycloak.models.cache.infinispan.entities.RoleQuery;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 $
|
||||||
*/
|
*/
|
||||||
@SerializeWith(HasRolePredicate.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.HAS_ROLE_PREDICATE)
|
||||||
public class HasRolePredicate implements Predicate<Map.Entry<String, Revisioned>>, Serializable {
|
public class HasRolePredicate implements Predicate<Map.Entry<String, Revisioned>> {
|
||||||
private String role;
|
private String role;
|
||||||
|
|
||||||
public static HasRolePredicate create() {
|
public static HasRolePredicate create() {
|
||||||
|
@ -34,61 +31,23 @@ public class HasRolePredicate implements Predicate<Map.Entry<String, Revisioned>
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(1)
|
||||||
|
String getRole() {
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRole(String role) {
|
||||||
|
this.role = role;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean test(Map.Entry<String, Revisioned> entry) {
|
public boolean test(Map.Entry<String, Revisioned> entry) {
|
||||||
Object value = entry.getValue();
|
Object value = entry.getValue();
|
||||||
if (value == null) return false;
|
return (value instanceof CachedRole cachedRole && cachedRole.getComposites().contains(role)) ||
|
||||||
if (value instanceof CachedRole) {
|
(value instanceof CachedGroup cachedGroup && cachedGroup.getRoleMappings(null).contains(role)) ||
|
||||||
CachedRole cachedRole = (CachedRole)value;
|
(value instanceof RoleQuery roleQuery && roleQuery.getRoles().contains(role)) ||
|
||||||
if (cachedRole.getComposites().contains(role)) return true;
|
(value instanceof CachedClient cachedClient && cachedClient.getScope().contains(role)) ||
|
||||||
}
|
(value instanceof CachedClientScope cachedClientScope && cachedClientScope.getScope().contains(role));
|
||||||
if (value instanceof CachedGroup) {
|
|
||||||
CachedGroup cachedRole = (CachedGroup)value;
|
|
||||||
if (cachedRole.getRoleMappings(null).contains(role)) return true;
|
|
||||||
}
|
|
||||||
if (value instanceof RoleQuery) {
|
|
||||||
RoleQuery roleQuery = (RoleQuery)value;
|
|
||||||
if (roleQuery.getRoles().contains(role)) return true;
|
|
||||||
}
|
|
||||||
if (value instanceof CachedClient) {
|
|
||||||
CachedClient cachedClient = (CachedClient)value;
|
|
||||||
if (cachedClient.getScope().contains(role)) return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
if (value instanceof CachedClientScope) {
|
|
||||||
CachedClientScope cachedClientScope = (CachedClientScope)value;
|
|
||||||
if (cachedClientScope.getScope().contains(role)) return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<HasRolePredicate> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, HasRolePredicate obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.role, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HasRolePredicate readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public HasRolePredicate readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
HasRolePredicate res = new HasRolePredicate();
|
|
||||||
res.role = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,21 @@
|
||||||
package org.keycloak.models.cache.infinispan.stream;
|
package org.keycloak.models.cache.infinispan.stream;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import org.keycloak.models.cache.infinispan.entities.InClient;
|
import org.keycloak.models.cache.infinispan.entities.InClient;
|
||||||
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 $
|
||||||
*/
|
*/
|
||||||
@SerializeWith(InClientPredicate.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.IN_CLIENT_PREDICATE)
|
||||||
public class InClientPredicate implements Predicate<Map.Entry<String, Revisioned>>, Serializable {
|
public class InClientPredicate implements Predicate<Map.Entry<String, Revisioned>> {
|
||||||
private String clientId;
|
private String clientId;
|
||||||
|
|
||||||
public static InClientPredicate create() {
|
public static InClientPredicate create() {
|
||||||
|
@ -30,41 +27,18 @@ public class InClientPredicate implements Predicate<Map.Entry<String, Revisioned
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(1)
|
||||||
|
String getClientId() {
|
||||||
|
return clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setClientId(String clientId) {
|
||||||
|
this.clientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean test(Map.Entry<String, Revisioned> entry) {
|
public boolean test(Map.Entry<String, Revisioned> entry) {
|
||||||
Object value = entry.getValue();
|
return entry.getValue() instanceof InClient inClient && clientId.equals(inClient.getClientId());
|
||||||
if (value == null) return false;
|
|
||||||
if (!(value instanceof InClient)) return false;
|
|
||||||
|
|
||||||
return clientId.equals(((InClient)value).getClientId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<InClientPredicate> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, InClientPredicate obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.clientId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InClientPredicate readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public InClientPredicate readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
InClientPredicate res = new InClientPredicate();
|
|
||||||
res.clientId = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,21 +17,18 @@
|
||||||
|
|
||||||
package org.keycloak.models.cache.infinispan.stream;
|
package org.keycloak.models.cache.infinispan.stream;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import org.keycloak.models.cache.infinispan.entities.GroupNameQuery;
|
import org.keycloak.models.cache.infinispan.entities.GroupNameQuery;
|
||||||
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
@SerializeWith(InGroupPredicate.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.IN_GROUP_PREDICATE)
|
||||||
public class InGroupPredicate implements Predicate<Map.Entry<String, Revisioned>>, Serializable {
|
public class InGroupPredicate implements Predicate<Map.Entry<String, Revisioned>> {
|
||||||
private String group;
|
private String group;
|
||||||
|
|
||||||
public static InGroupPredicate create() {
|
public static InGroupPredicate create() {
|
||||||
|
@ -43,41 +40,19 @@ public class InGroupPredicate implements Predicate<Map.Entry<String, Revisioned>
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(1)
|
||||||
|
String getGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setGroup(String group) {
|
||||||
|
this.group = group;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean test(Map.Entry<String, Revisioned> entry) {
|
public boolean test(Map.Entry<String, Revisioned> entry) {
|
||||||
Object value = entry.getValue();
|
return entry.getValue() instanceof GroupNameQuery groupNameQuery && group.equals(groupNameQuery.getGroupId());
|
||||||
if (value == null) return false;
|
|
||||||
if (!(value instanceof GroupNameQuery)) return false;
|
|
||||||
|
|
||||||
return group.equals(((GroupNameQuery)value).getGroupId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<InGroupPredicate> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, InGroupPredicate obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.group, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InGroupPredicate readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public InGroupPredicate readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
InGroupPredicate res = new InGroupPredicate();
|
|
||||||
res.group = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,24 +1,20 @@
|
||||||
package org.keycloak.models.cache.infinispan.stream;
|
package org.keycloak.models.cache.infinispan.stream;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import org.keycloak.models.cache.infinispan.entities.InIdentityProvider;
|
import org.keycloak.models.cache.infinispan.entities.InIdentityProvider;
|
||||||
import org.keycloak.models.cache.infinispan.entities.InRealm;
|
|
||||||
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(InIdentityProviderPredicate.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.IN_IDENTITY_PROVIDER_PREDICATE)
|
||||||
public class InIdentityProviderPredicate implements Predicate<Map.Entry<String, Revisioned>>, Serializable {
|
public class InIdentityProviderPredicate implements Predicate<Map.Entry<String, Revisioned>> {
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
public static InIdentityProviderPredicate create() {
|
public static InIdentityProviderPredicate create() {
|
||||||
|
@ -30,41 +26,18 @@ public class InIdentityProviderPredicate implements Predicate<Map.Entry<String,
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(1)
|
||||||
|
String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean test(Map.Entry<String, Revisioned> entry) {
|
public boolean test(Map.Entry<String, Revisioned> entry) {
|
||||||
Object value = entry.getValue();
|
return entry.getValue() instanceof InIdentityProvider provider && provider.contains(id);
|
||||||
if (value == null) return false;
|
|
||||||
if (!(value instanceof InIdentityProvider)) return false;
|
|
||||||
|
|
||||||
return ((InIdentityProvider)value).contains(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<InIdentityProviderPredicate> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, InIdentityProviderPredicate obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.id, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InIdentityProviderPredicate readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public InIdentityProviderPredicate readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
InIdentityProviderPredicate res = new InIdentityProviderPredicate();
|
|
||||||
res.id = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,21 @@
|
||||||
package org.keycloak.models.cache.infinispan.stream;
|
package org.keycloak.models.cache.infinispan.stream;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import org.keycloak.models.cache.infinispan.entities.InRealm;
|
import org.keycloak.models.cache.infinispan.entities.InRealm;
|
||||||
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
import org.keycloak.models.cache.infinispan.entities.Revisioned;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 $
|
||||||
*/
|
*/
|
||||||
@SerializeWith(InRealmPredicate.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.IN_REALM_PREDICATE)
|
||||||
public class InRealmPredicate implements Predicate<Map.Entry<String, Revisioned>>, Serializable {
|
public class InRealmPredicate implements Predicate<Map.Entry<String, Revisioned>> {
|
||||||
private String realm;
|
private String realm;
|
||||||
|
|
||||||
public static InRealmPredicate create() {
|
public static InRealmPredicate create() {
|
||||||
|
@ -30,41 +27,19 @@ public class InRealmPredicate implements Predicate<Map.Entry<String, Revisioned>
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(1)
|
||||||
|
String getRealm() {
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRealm(String realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean test(Map.Entry<String, Revisioned> entry) {
|
public boolean test(Map.Entry<String, Revisioned> entry) {
|
||||||
Object value = entry.getValue();
|
return entry.getValue() instanceof InRealm inRealm && realm.equals(inRealm.getRealm());
|
||||||
if (value == null) return false;
|
|
||||||
if (!(value instanceof InRealm)) return false;
|
|
||||||
|
|
||||||
return realm.equals(((InRealm)value).getRealm());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<InRealmPredicate> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, InRealmPredicate obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(obj.realm, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InRealmPredicate readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public InRealmPredicate readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
InRealmPredicate res = new InRealmPredicate();
|
|
||||||
res.realm = MarshallUtil.unmarshallString(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.common.util.Base64Url;
|
import org.keycloak.common.util.Base64Url;
|
||||||
import org.keycloak.common.util.SecretGenerator;
|
import org.keycloak.common.util.SecretGenerator;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
|
@ -34,7 +33,7 @@ import org.keycloak.models.cache.infinispan.events.AuthenticationSessionAuthNote
|
||||||
import org.keycloak.models.sessions.infinispan.entities.RootAuthenticationSessionEntity;
|
import org.keycloak.models.sessions.infinispan.entities.RootAuthenticationSessionEntity;
|
||||||
import org.keycloak.models.sessions.infinispan.events.RealmRemovedSessionEvent;
|
import org.keycloak.models.sessions.infinispan.events.RealmRemovedSessionEvent;
|
||||||
import org.keycloak.models.sessions.infinispan.events.SessionEventsSenderTransaction;
|
import org.keycloak.models.sessions.infinispan.events.SessionEventsSenderTransaction;
|
||||||
import org.keycloak.models.sessions.infinispan.stream.RootAuthenticationSessionPredicate;
|
import org.keycloak.models.sessions.infinispan.stream.SessionPredicate;
|
||||||
import org.keycloak.models.sessions.infinispan.util.InfinispanKeyGenerator;
|
import org.keycloak.models.sessions.infinispan.util.InfinispanKeyGenerator;
|
||||||
import org.keycloak.models.utils.SessionExpiration;
|
import org.keycloak.models.utils.SessionExpiration;
|
||||||
import org.keycloak.sessions.AuthenticationSessionCompoundId;
|
import org.keycloak.sessions.AuthenticationSessionCompoundId;
|
||||||
|
@ -120,7 +119,7 @@ public class InfinispanAuthenticationSessionProvider implements AuthenticationSe
|
||||||
Iterator<Map.Entry<String, RootAuthenticationSessionEntity>> itr = CacheDecorators.localCache(cache)
|
Iterator<Map.Entry<String, RootAuthenticationSessionEntity>> itr = CacheDecorators.localCache(cache)
|
||||||
.entrySet()
|
.entrySet()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(RootAuthenticationSessionPredicate.create(realmId))
|
.filter(SessionPredicate.create(realmId))
|
||||||
.iterator();
|
.iterator();
|
||||||
|
|
||||||
while (itr.hasNext()) {
|
while (itr.hasNext()) {
|
||||||
|
@ -149,7 +148,7 @@ public class InfinispanAuthenticationSessionProvider implements AuthenticationSe
|
||||||
ClusterProvider cluster = session.getProvider(ClusterProvider.class);
|
ClusterProvider cluster = session.getProvider(ClusterProvider.class);
|
||||||
cluster.notify(
|
cluster.notify(
|
||||||
InfinispanAuthenticationSessionProviderFactory.AUTHENTICATION_SESSION_EVENTS,
|
InfinispanAuthenticationSessionProviderFactory.AUTHENTICATION_SESSION_EVENTS,
|
||||||
AuthenticationSessionAuthNoteUpdateEvent.create(compoundId.getRootSessionId(), compoundId.getTabId(), compoundId.getClientUUID(), authNotesFragment),
|
AuthenticationSessionAuthNoteUpdateEvent.create(compoundId.getRootSessionId(), compoundId.getTabId(), authNotesFragment),
|
||||||
true,
|
true,
|
||||||
ClusterProvider.DCNotify.ALL_BUT_LOCAL_DC
|
ClusterProvider.DCNotify.ALL_BUT_LOCAL_DC
|
||||||
);
|
);
|
||||||
|
|
|
@ -35,7 +35,7 @@ import org.keycloak.models.sessions.infinispan.events.RemoveAllUserLoginFailures
|
||||||
import org.keycloak.models.sessions.infinispan.events.SessionEventsSenderTransaction;
|
import org.keycloak.models.sessions.infinispan.events.SessionEventsSenderTransaction;
|
||||||
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheInvoker;
|
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheInvoker;
|
||||||
import org.keycloak.models.sessions.infinispan.stream.Mappers;
|
import org.keycloak.models.sessions.infinispan.stream.Mappers;
|
||||||
import org.keycloak.models.sessions.infinispan.stream.UserLoginFailurePredicate;
|
import org.keycloak.models.sessions.infinispan.stream.SessionWrapperPredicate;
|
||||||
import org.keycloak.models.sessions.infinispan.util.FuturesHelper;
|
import org.keycloak.models.sessions.infinispan.util.FuturesHelper;
|
||||||
import org.keycloak.models.sessions.infinispan.util.SessionTimeouts;
|
import org.keycloak.models.sessions.infinispan.util.SessionTimeouts;
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ public class InfinispanUserLoginFailureProvider implements UserLoginFailureProvi
|
||||||
localCacheStoreIgnore
|
localCacheStoreIgnore
|
||||||
.entrySet()
|
.entrySet()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(UserLoginFailurePredicate.create(realmId))
|
.filter(SessionWrapperPredicate.create(realmId))
|
||||||
.map(Mappers.loginFailureId())
|
.map(Mappers.loginFailureId())
|
||||||
.forEach(loginFailureKey -> {
|
.forEach(loginFailureKey -> {
|
||||||
// Remove loginFailure from remoteCache too. Use removeAsync for better perf
|
// Remove loginFailure from remoteCache too. Use removeAsync for better perf
|
||||||
|
|
|
@ -24,12 +24,13 @@ import org.keycloak.Config;
|
||||||
import org.keycloak.cluster.ClusterProvider;
|
import org.keycloak.cluster.ClusterProvider;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||||
|
import org.keycloak.connections.infinispan.InfinispanUtil;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.models.KeycloakSessionTask;
|
import org.keycloak.models.KeycloakSessionTask;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserLoginFailureProvider;
|
import org.keycloak.models.UserLoginFailureProvider;
|
||||||
import org.keycloak.models.UserLoginFailureProviderFactory;
|
import org.keycloak.models.UserLoginFailureProviderFactory;
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.sessions.infinispan.changes.SerializeExecutionsByKey;
|
import org.keycloak.models.sessions.infinispan.changes.SerializeExecutionsByKey;
|
||||||
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
||||||
|
@ -40,15 +41,14 @@ import org.keycloak.models.sessions.infinispan.events.AbstractUserSessionCluster
|
||||||
import org.keycloak.models.sessions.infinispan.events.RealmRemovedSessionEvent;
|
import org.keycloak.models.sessions.infinispan.events.RealmRemovedSessionEvent;
|
||||||
import org.keycloak.models.sessions.infinispan.events.RemoveAllUserLoginFailuresEvent;
|
import org.keycloak.models.sessions.infinispan.events.RemoveAllUserLoginFailuresEvent;
|
||||||
import org.keycloak.models.sessions.infinispan.initializer.InfinispanCacheInitializer;
|
import org.keycloak.models.sessions.infinispan.initializer.InfinispanCacheInitializer;
|
||||||
|
import org.keycloak.models.sessions.infinispan.initializer.InitializerState;
|
||||||
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheInvoker;
|
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheInvoker;
|
||||||
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheSessionListener;
|
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheSessionListener;
|
||||||
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheSessionsLoader;
|
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheSessionsLoader;
|
||||||
import org.keycloak.connections.infinispan.InfinispanUtil;
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.SessionTimeouts;
|
import org.keycloak.models.sessions.infinispan.util.SessionTimeouts;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
import org.keycloak.models.utils.PostMigrationEvent;
|
import org.keycloak.models.utils.PostMigrationEvent;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.keycloak.models.sessions.infinispan.InfinispanAuthenticationSessionProviderFactory.PROVIDER_PRIORITY;
|
import static org.keycloak.models.sessions.infinispan.InfinispanAuthenticationSessionProviderFactory.PROVIDER_PRIORITY;
|
||||||
|
@ -195,7 +195,7 @@ public class InfinispanUserLoginFailureProviderFactory implements UserLoginFailu
|
||||||
@Override
|
@Override
|
||||||
public void run(KeycloakSession session) {
|
public void run(KeycloakSession session) {
|
||||||
InfinispanConnectionProvider connections = session.getProvider(InfinispanConnectionProvider.class);
|
InfinispanConnectionProvider connections = session.getProvider(InfinispanConnectionProvider.class);
|
||||||
Cache<String, Serializable> workCache = connections.getCache(InfinispanConnectionProvider.WORK_CACHE_NAME);
|
Cache<String, InitializerState> workCache = connections.getCache(InfinispanConnectionProvider.WORK_CACHE_NAME);
|
||||||
int defaultStateTransferTimeout = (int) (connections.getCache(InfinispanConnectionProvider.LOGIN_FAILURE_CACHE_NAME)
|
int defaultStateTransferTimeout = (int) (connections.getCache(InfinispanConnectionProvider.LOGIN_FAILURE_CACHE_NAME)
|
||||||
.getCacheConfiguration().clustering().stateTransfer().timeout() / 1000);
|
.getCacheConfiguration().clustering().stateTransfer().timeout() / 1000);
|
||||||
|
|
||||||
|
|
|
@ -17,53 +17,6 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan;
|
package org.keycloak.models.sessions.infinispan;
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
|
||||||
import org.infinispan.client.hotrod.RemoteCache;
|
|
||||||
import org.infinispan.client.hotrod.exceptions.HotRodClientException;
|
|
||||||
import org.infinispan.commons.api.BasicCache;
|
|
||||||
import org.infinispan.context.Flag;
|
|
||||||
import org.infinispan.stream.CacheCollectors;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.cluster.ClusterProvider;
|
|
||||||
import org.keycloak.common.Profile;
|
|
||||||
import org.keycloak.common.Profile.Feature;
|
|
||||||
import org.keycloak.common.util.Retry;
|
|
||||||
import org.keycloak.common.util.Time;
|
|
||||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
|
||||||
import org.keycloak.models.ClientModel;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.ModelException;
|
|
||||||
import org.keycloak.models.OfflineUserSessionModel;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.models.UserModel;
|
|
||||||
import org.keycloak.models.UserProvider;
|
|
||||||
import org.keycloak.models.UserSessionModel;
|
|
||||||
import org.keycloak.models.UserSessionProvider;
|
|
||||||
import org.keycloak.models.session.UserSessionPersisterProvider;
|
|
||||||
import org.keycloak.models.sessions.infinispan.changes.SerializeExecutionsByKey;
|
|
||||||
import org.keycloak.models.sessions.infinispan.changes.Tasks;
|
|
||||||
import org.keycloak.models.sessions.infinispan.changes.sessions.CrossDCLastSessionRefreshStore;
|
|
||||||
import org.keycloak.models.sessions.infinispan.changes.sessions.PersisterLastSessionRefreshStore;
|
|
||||||
import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
|
|
||||||
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheInvoker;
|
|
||||||
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
|
||||||
import org.keycloak.models.sessions.infinispan.changes.InfinispanChangelogBasedTransaction;
|
|
||||||
import org.keycloak.models.sessions.infinispan.changes.SessionUpdateTask;
|
|
||||||
import org.keycloak.models.sessions.infinispan.entities.AuthenticatedClientSessionEntity;
|
|
||||||
import org.keycloak.models.sessions.infinispan.entities.AuthenticatedClientSessionStore;
|
|
||||||
import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
|
|
||||||
import org.keycloak.models.sessions.infinispan.events.RealmRemovedSessionEvent;
|
|
||||||
import org.keycloak.models.sessions.infinispan.events.RemoveUserSessionsEvent;
|
|
||||||
import org.keycloak.models.sessions.infinispan.events.SessionEventsSenderTransaction;
|
|
||||||
import org.keycloak.models.sessions.infinispan.stream.Mappers;
|
|
||||||
import org.keycloak.models.sessions.infinispan.stream.SessionPredicate;
|
|
||||||
import org.keycloak.models.sessions.infinispan.stream.UserSessionPredicate;
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.FuturesHelper;
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.InfinispanKeyGenerator;
|
|
||||||
import org.keycloak.connections.infinispan.InfinispanUtil;
|
|
||||||
import org.keycloak.models.light.LightweightUserAdapter;
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.SessionTimeouts;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -85,6 +38,55 @@ import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
import org.infinispan.Cache;
|
||||||
|
import org.infinispan.client.hotrod.RemoteCache;
|
||||||
|
import org.infinispan.client.hotrod.exceptions.HotRodClientException;
|
||||||
|
import org.infinispan.commons.api.BasicCache;
|
||||||
|
import org.infinispan.commons.util.concurrent.CompletionStages;
|
||||||
|
import org.infinispan.context.Flag;
|
||||||
|
import org.infinispan.stream.CacheCollectors;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.cluster.ClusterProvider;
|
||||||
|
import org.keycloak.common.Profile;
|
||||||
|
import org.keycloak.common.Profile.Feature;
|
||||||
|
import org.keycloak.common.util.Retry;
|
||||||
|
import org.keycloak.common.util.Time;
|
||||||
|
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||||
|
import org.keycloak.connections.infinispan.InfinispanUtil;
|
||||||
|
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.ModelException;
|
||||||
|
import org.keycloak.models.OfflineUserSessionModel;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.UserProvider;
|
||||||
|
import org.keycloak.models.UserSessionModel;
|
||||||
|
import org.keycloak.models.UserSessionProvider;
|
||||||
|
import org.keycloak.models.light.LightweightUserAdapter;
|
||||||
|
import org.keycloak.models.session.UserSessionPersisterProvider;
|
||||||
|
import org.keycloak.models.sessions.infinispan.changes.InfinispanChangelogBasedTransaction;
|
||||||
|
import org.keycloak.models.sessions.infinispan.changes.SerializeExecutionsByKey;
|
||||||
|
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
||||||
|
import org.keycloak.models.sessions.infinispan.changes.SessionUpdateTask;
|
||||||
|
import org.keycloak.models.sessions.infinispan.changes.Tasks;
|
||||||
|
import org.keycloak.models.sessions.infinispan.changes.sessions.CrossDCLastSessionRefreshStore;
|
||||||
|
import org.keycloak.models.sessions.infinispan.changes.sessions.PersisterLastSessionRefreshStore;
|
||||||
|
import org.keycloak.models.sessions.infinispan.entities.AuthenticatedClientSessionEntity;
|
||||||
|
import org.keycloak.models.sessions.infinispan.entities.AuthenticatedClientSessionStore;
|
||||||
|
import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
|
||||||
|
import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
|
||||||
|
import org.keycloak.models.sessions.infinispan.events.RealmRemovedSessionEvent;
|
||||||
|
import org.keycloak.models.sessions.infinispan.events.RemoveUserSessionsEvent;
|
||||||
|
import org.keycloak.models.sessions.infinispan.events.SessionEventsSenderTransaction;
|
||||||
|
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheInvoker;
|
||||||
|
import org.keycloak.models.sessions.infinispan.stream.Mappers;
|
||||||
|
import org.keycloak.models.sessions.infinispan.stream.SessionWrapperPredicate;
|
||||||
|
import org.keycloak.models.sessions.infinispan.stream.UserSessionPredicate;
|
||||||
|
import org.keycloak.models.sessions.infinispan.util.FuturesHelper;
|
||||||
|
import org.keycloak.models.sessions.infinispan.util.InfinispanKeyGenerator;
|
||||||
|
import org.keycloak.models.sessions.infinispan.util.SessionTimeouts;
|
||||||
|
|
||||||
import static org.keycloak.models.Constants.SESSION_NOTE_LIGHTWEIGHT_USER;
|
import static org.keycloak.models.Constants.SESSION_NOTE_LIGHTWEIGHT_USER;
|
||||||
import static org.keycloak.utils.StreamsUtil.paginatedStream;
|
import static org.keycloak.utils.StreamsUtil.paginatedStream;
|
||||||
|
|
||||||
|
@ -270,6 +272,16 @@ public class InfinispanUserSessionProvider implements UserSessionProvider, Sessi
|
||||||
return getUserSession(realm, id, false);
|
return getUserSession(realm, id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void migrate(String modelVersion) {
|
||||||
|
// Changed encoding from JBoss Marshalling to ProtoStream.
|
||||||
|
// Unable to read the cached data.
|
||||||
|
if ("26.0.0".equals(modelVersion)) {
|
||||||
|
log.debug("Clear caches to migrate to Infinispan Protostream");
|
||||||
|
CompletionStages.join(session.getProvider(InfinispanConnectionProvider.class).migrateToProtostream());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected UserSessionAdapter getUserSession(RealmModel realm, String id, boolean offline) {
|
protected UserSessionAdapter getUserSession(RealmModel realm, String id, boolean offline) {
|
||||||
|
|
||||||
UserSessionEntity userSessionEntityFromCache = getUserSessionEntity(realm, id, offline);
|
UserSessionEntity userSessionEntityFromCache = getUserSessionEntity(realm, id, offline);
|
||||||
|
@ -660,7 +672,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider, Sessi
|
||||||
localCacheStoreIgnore
|
localCacheStoreIgnore
|
||||||
.entrySet()
|
.entrySet()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(SessionPredicate.create(realmId))
|
.filter(SessionWrapperPredicate.create(realmId))
|
||||||
.map(Mappers.userSessionEntity())
|
.map(Mappers.userSessionEntity())
|
||||||
.forEach(new Consumer<UserSessionEntity>() {
|
.forEach(new Consumer<UserSessionEntity>() {
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,14 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan;
|
package org.keycloak.models.sessions.infinispan;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.infinispan.client.hotrod.RemoteCache;
|
import org.infinispan.client.hotrod.RemoteCache;
|
||||||
import org.infinispan.persistence.remote.RemoteStore;
|
import org.infinispan.persistence.remote.RemoteStore;
|
||||||
|
@ -27,6 +35,7 @@ import org.keycloak.common.Profile;
|
||||||
import org.keycloak.common.util.Environment;
|
import org.keycloak.common.util.Environment;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||||
|
import org.keycloak.connections.infinispan.InfinispanUtil;
|
||||||
import org.keycloak.models.ClientModel;
|
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;
|
||||||
|
@ -35,15 +44,14 @@ import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionProvider;
|
import org.keycloak.models.UserSessionProvider;
|
||||||
import org.keycloak.models.UserSessionProviderFactory;
|
import org.keycloak.models.UserSessionProviderFactory;
|
||||||
|
import org.keycloak.models.sessions.infinispan.changes.PersistentSessionsWorker;
|
||||||
import org.keycloak.models.sessions.infinispan.changes.PersistentUpdate;
|
import org.keycloak.models.sessions.infinispan.changes.PersistentUpdate;
|
||||||
import org.keycloak.models.sessions.infinispan.changes.SerializeExecutionsByKey;
|
import org.keycloak.models.sessions.infinispan.changes.SerializeExecutionsByKey;
|
||||||
import org.keycloak.models.sessions.infinispan.changes.PersistentSessionsWorker;
|
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
||||||
import org.keycloak.models.sessions.infinispan.changes.sessions.CrossDCLastSessionRefreshStore;
|
import org.keycloak.models.sessions.infinispan.changes.sessions.CrossDCLastSessionRefreshStore;
|
||||||
import org.keycloak.models.sessions.infinispan.changes.sessions.CrossDCLastSessionRefreshStoreFactory;
|
import org.keycloak.models.sessions.infinispan.changes.sessions.CrossDCLastSessionRefreshStoreFactory;
|
||||||
import org.keycloak.models.sessions.infinispan.changes.sessions.PersisterLastSessionRefreshStore;
|
import org.keycloak.models.sessions.infinispan.changes.sessions.PersisterLastSessionRefreshStore;
|
||||||
import org.keycloak.models.sessions.infinispan.changes.sessions.PersisterLastSessionRefreshStoreFactory;
|
import org.keycloak.models.sessions.infinispan.changes.sessions.PersisterLastSessionRefreshStoreFactory;
|
||||||
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheInvoker;
|
|
||||||
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
|
||||||
import org.keycloak.models.sessions.infinispan.entities.AuthenticatedClientSessionEntity;
|
import org.keycloak.models.sessions.infinispan.entities.AuthenticatedClientSessionEntity;
|
||||||
import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
|
import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
|
||||||
import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
|
import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
|
||||||
|
@ -51,10 +59,11 @@ import org.keycloak.models.sessions.infinispan.events.AbstractUserSessionCluster
|
||||||
import org.keycloak.models.sessions.infinispan.events.RealmRemovedSessionEvent;
|
import org.keycloak.models.sessions.infinispan.events.RealmRemovedSessionEvent;
|
||||||
import org.keycloak.models.sessions.infinispan.events.RemoveUserSessionsEvent;
|
import org.keycloak.models.sessions.infinispan.events.RemoveUserSessionsEvent;
|
||||||
import org.keycloak.models.sessions.infinispan.initializer.InfinispanCacheInitializer;
|
import org.keycloak.models.sessions.infinispan.initializer.InfinispanCacheInitializer;
|
||||||
|
import org.keycloak.models.sessions.infinispan.initializer.InitializerState;
|
||||||
|
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheInvoker;
|
||||||
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheSessionListener;
|
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheSessionListener;
|
||||||
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheSessionsLoader;
|
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheSessionsLoader;
|
||||||
import org.keycloak.models.sessions.infinispan.util.InfinispanKeyGenerator;
|
import org.keycloak.models.sessions.infinispan.util.InfinispanKeyGenerator;
|
||||||
import org.keycloak.connections.infinispan.InfinispanUtil;
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.SessionTimeouts;
|
import org.keycloak.models.sessions.infinispan.util.SessionTimeouts;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
import org.keycloak.models.utils.PostMigrationEvent;
|
import org.keycloak.models.utils.PostMigrationEvent;
|
||||||
|
@ -65,15 +74,6 @@ import org.keycloak.provider.ProviderEvent;
|
||||||
import org.keycloak.provider.ProviderEventListener;
|
import org.keycloak.provider.ProviderEventListener;
|
||||||
import org.keycloak.provider.ServerInfoAwareProviderFactory;
|
import org.keycloak.provider.ServerInfoAwareProviderFactory;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import static org.keycloak.models.sessions.infinispan.InfinispanAuthenticationSessionProviderFactory.PROVIDER_PRIORITY;
|
import static org.keycloak.models.sessions.infinispan.InfinispanAuthenticationSessionProviderFactory.PROVIDER_PRIORITY;
|
||||||
|
|
||||||
public class InfinispanUserSessionProviderFactory implements UserSessionProviderFactory, ServerInfoAwareProviderFactory {
|
public class InfinispanUserSessionProviderFactory implements UserSessionProviderFactory, ServerInfoAwareProviderFactory {
|
||||||
|
@ -398,7 +398,7 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider
|
||||||
@Override
|
@Override
|
||||||
public void run(KeycloakSession session) {
|
public void run(KeycloakSession session) {
|
||||||
InfinispanConnectionProvider connections = session.getProvider(InfinispanConnectionProvider.class);
|
InfinispanConnectionProvider connections = session.getProvider(InfinispanConnectionProvider.class);
|
||||||
Cache<String, Serializable> workCache = connections.getCache(InfinispanConnectionProvider.WORK_CACHE_NAME);
|
Cache<String, InitializerState> workCache = connections.getCache(InfinispanConnectionProvider.WORK_CACHE_NAME);
|
||||||
int defaultStateTransferTimeout = (int) (connections.getCache(InfinispanConnectionProvider.USER_SESSION_CACHE_NAME)
|
int defaultStateTransferTimeout = (int) (connections.getCache(InfinispanConnectionProvider.USER_SESSION_CACHE_NAME)
|
||||||
.getCacheConfiguration().clustering().stateTransfer().timeout() / 1000);
|
.getCacheConfiguration().clustering().stateTransfer().timeout() / 1000);
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,31 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan;
|
package org.keycloak.models.sessions.infinispan;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.core.Flowable;
|
import io.reactivex.rxjava3.core.Flowable;
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.infinispan.client.hotrod.RemoteCache;
|
import org.infinispan.client.hotrod.RemoteCache;
|
||||||
import org.infinispan.client.hotrod.exceptions.HotRodClientException;
|
import org.infinispan.client.hotrod.exceptions.HotRodClientException;
|
||||||
import org.infinispan.commons.api.BasicCache;
|
import org.infinispan.commons.api.BasicCache;
|
||||||
import org.infinispan.commons.util.ByRef;
|
import org.infinispan.commons.util.ByRef;
|
||||||
|
import org.infinispan.commons.util.concurrent.CompletionStages;
|
||||||
import org.infinispan.context.Flag;
|
import org.infinispan.context.Flag;
|
||||||
import org.infinispan.factories.ComponentRegistry;
|
import org.infinispan.factories.ComponentRegistry;
|
||||||
import org.infinispan.persistence.manager.PersistenceManager;
|
import org.infinispan.persistence.manager.PersistenceManager;
|
||||||
|
@ -32,8 +51,8 @@ import org.keycloak.common.Profile;
|
||||||
import org.keycloak.common.Profile.Feature;
|
import org.keycloak.common.Profile.Feature;
|
||||||
import org.keycloak.common.util.Retry;
|
import org.keycloak.common.util.Retry;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
|
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||||
import org.keycloak.connections.infinispan.InfinispanUtil;
|
import org.keycloak.connections.infinispan.InfinispanUtil;
|
||||||
import org.keycloak.migration.ModelVersion;
|
|
||||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
@ -67,7 +86,7 @@ import org.keycloak.models.sessions.infinispan.events.RemoveUserSessionsEvent;
|
||||||
import org.keycloak.models.sessions.infinispan.events.SessionEventsSenderTransaction;
|
import org.keycloak.models.sessions.infinispan.events.SessionEventsSenderTransaction;
|
||||||
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheInvoker;
|
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheInvoker;
|
||||||
import org.keycloak.models.sessions.infinispan.stream.Mappers;
|
import org.keycloak.models.sessions.infinispan.stream.Mappers;
|
||||||
import org.keycloak.models.sessions.infinispan.stream.SessionPredicate;
|
import org.keycloak.models.sessions.infinispan.stream.SessionWrapperPredicate;
|
||||||
import org.keycloak.models.sessions.infinispan.stream.UserSessionPredicate;
|
import org.keycloak.models.sessions.infinispan.stream.UserSessionPredicate;
|
||||||
import org.keycloak.models.sessions.infinispan.util.FuturesHelper;
|
import org.keycloak.models.sessions.infinispan.util.FuturesHelper;
|
||||||
import org.keycloak.models.sessions.infinispan.util.InfinispanKeyGenerator;
|
import org.keycloak.models.sessions.infinispan.util.InfinispanKeyGenerator;
|
||||||
|
@ -75,24 +94,6 @@ import org.keycloak.models.sessions.infinispan.util.SessionTimeouts;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
import org.keycloak.models.utils.UserModelDelegate;
|
import org.keycloak.models.utils.UserModelDelegate;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static org.keycloak.models.Constants.SESSION_NOTE_LIGHTWEIGHT_USER;
|
import static org.keycloak.models.Constants.SESSION_NOTE_LIGHTWEIGHT_USER;
|
||||||
import static org.keycloak.utils.StreamsUtil.paginatedStream;
|
import static org.keycloak.utils.StreamsUtil.paginatedStream;
|
||||||
|
|
||||||
|
@ -559,7 +560,7 @@ public class PersistentUserSessionProvider implements UserSessionProvider, Sessi
|
||||||
sessions
|
sessions
|
||||||
.entrySet()
|
.entrySet()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(SessionPredicate.create(realmId))
|
.filter(SessionWrapperPredicate.create(realmId))
|
||||||
.map(Mappers.userSessionEntity())
|
.map(Mappers.userSessionEntity())
|
||||||
.forEach((Consumer<UserSessionEntity>) userSessionEntity -> {
|
.forEach((Consumer<UserSessionEntity>) userSessionEntity -> {
|
||||||
userSessionsSize.incrementAndGet();
|
userSessionsSize.incrementAndGet();
|
||||||
|
@ -586,7 +587,7 @@ public class PersistentUserSessionProvider implements UserSessionProvider, Sessi
|
||||||
sessions
|
sessions
|
||||||
.entrySet()
|
.entrySet()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(SessionPredicate.create(realmId))
|
.filter(UserSessionPredicate.create(realmId))
|
||||||
.map(Mappers.userSessionEntity())
|
.map(Mappers.userSessionEntity())
|
||||||
.forEach((Consumer<UserSessionEntity>) userSessionEntity -> {
|
.forEach((Consumer<UserSessionEntity>) userSessionEntity -> {
|
||||||
userSessionsSize.incrementAndGet();
|
userSessionsSize.incrementAndGet();
|
||||||
|
@ -1013,8 +1014,11 @@ public class PersistentUserSessionProvider implements UserSessionProvider, Sessi
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void migrate(String modelVersion) {
|
public void migrate(String modelVersion) {
|
||||||
if (new ModelVersion(modelVersion).equals(new ModelVersion("25.0.0"))) {
|
// Changed encoding from JBoss Marshalling to ProtoStream.
|
||||||
migrateNonPersistentSessionsToPersistentSessions();
|
// Unable to read the cached data.
|
||||||
|
if ("26.0.0".equals(modelVersion)) {
|
||||||
|
log.debug("Clear caches to migrate to Infinispan Protostream");
|
||||||
|
CompletionStages.join(session.getProvider(InfinispanConnectionProvider.class).migrateToProtostream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,9 @@ import java.util.function.BiFunction;
|
||||||
|
|
||||||
import org.infinispan.commons.marshall.AdvancedExternalizer;
|
import org.infinispan.commons.marshall.AdvancedExternalizer;
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import org.infinispan.commons.marshall.MarshallUtil;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import org.keycloak.marshalling.Marshalling;
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
|
import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
|
||||||
|
|
||||||
|
@ -19,13 +22,13 @@ import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
|
||||||
* @param <K> The Infinispan key type.
|
* @param <K> The Infinispan key type.
|
||||||
* @param <T> The Infinispan value type (Keycloak entity)
|
* @param <T> The Infinispan value type (Keycloak entity)
|
||||||
*/
|
*/
|
||||||
|
@ProtoTypeId(Marshalling.REPLACE_FUNCTION)
|
||||||
public class ReplaceFunction<K, T extends SessionEntity> implements BiFunction<K, SessionEntityWrapper<T>, SessionEntityWrapper<T>> {
|
public class ReplaceFunction<K, T extends SessionEntity> implements BiFunction<K, SessionEntityWrapper<T>, SessionEntityWrapper<T>> {
|
||||||
|
|
||||||
@SuppressWarnings({"removal", "rawtypes"})
|
|
||||||
public static final AdvancedExternalizer<ReplaceFunction> INSTANCE = new Externalizer();
|
|
||||||
private final UUID expectedVersion;
|
private final UUID expectedVersion;
|
||||||
private final SessionEntityWrapper<T> newValue;
|
private final SessionEntityWrapper<T> newValue;
|
||||||
|
|
||||||
|
@ProtoFactory
|
||||||
public ReplaceFunction(UUID expectedVersion, SessionEntityWrapper<T> newValue) {
|
public ReplaceFunction(UUID expectedVersion, SessionEntityWrapper<T> newValue) {
|
||||||
this.expectedVersion = Objects.requireNonNull(expectedVersion);
|
this.expectedVersion = Objects.requireNonNull(expectedVersion);
|
||||||
this.newValue = Objects.requireNonNull(newValue);
|
this.newValue = Objects.requireNonNull(newValue);
|
||||||
|
@ -37,37 +40,13 @@ public class ReplaceFunction<K, T extends SessionEntity> implements BiFunction<K
|
||||||
return expectedVersion.equals(currentValue.getVersion()) ? newValue : currentValue;
|
return expectedVersion.equals(currentValue.getVersion()) ? newValue : currentValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"removal", "rawtypes"})
|
@ProtoField(1)
|
||||||
private static class Externalizer implements AdvancedExternalizer<ReplaceFunction> {
|
UUID getExpectedVersion() {
|
||||||
|
return expectedVersion;
|
||||||
private static final SessionEntityWrapper.ExternalizerImpl EXTERNALIZER = new SessionEntityWrapper.ExternalizerImpl();
|
|
||||||
private static final byte VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Class<? extends ReplaceFunction>> getTypeClasses() {
|
|
||||||
return Set.of(ReplaceFunction.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@ProtoField(2)
|
||||||
public Integer getId() {
|
SessionEntityWrapper<T> getNewValue() {
|
||||||
return Marshalling.REPLACE_FUNCTION_ID;
|
return newValue;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, ReplaceFunction object) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
MarshallUtil.marshallUUID(object.expectedVersion, output, false);
|
|
||||||
EXTERNALIZER.writeObject(output, object.newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReplaceFunction<?,?> readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
var version = input.readByte();
|
|
||||||
if (version != VERSION_1) {
|
|
||||||
throw new IOException("Invalid version: " + version);
|
|
||||||
}
|
|
||||||
//noinspection unchecked
|
|
||||||
return new ReplaceFunction<Object, SessionEntity>(MarshallUtil.unmarshallUUID(input, false), EXTERNALIZER.readObject(input));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,32 +17,27 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.changes;
|
package org.keycloak.models.sessions.infinispan.changes;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.infinispan.protostream.WrappedMessage;
|
||||||
import java.io.ObjectInput;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import java.io.ObjectOutput;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
import org.keycloak.models.sessions.infinispan.entities.AuthenticatedClientSessionEntity;
|
||||||
|
import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
import org.keycloak.models.ClientModel;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.models.sessions.infinispan.entities.AuthenticatedClientSessionEntity;
|
|
||||||
import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(SessionEntityWrapper.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.SESSION_ENTITY_WRAPPER)
|
||||||
public class SessionEntityWrapper<S extends SessionEntity> {
|
public class SessionEntityWrapper<S extends SessionEntity> {
|
||||||
|
|
||||||
private static final Logger log = Logger.getLogger(SessionEntityWrapper.class);
|
|
||||||
|
|
||||||
private final UUID version;
|
private final UUID version;
|
||||||
private final S entity;
|
private final S entity;
|
||||||
private final Map<String, String> localMetadata;
|
private final Map<String, String> localMetadata;
|
||||||
|
@ -87,6 +82,7 @@ public class SessionEntityWrapper<S extends SessionEntity> {
|
||||||
return this.version == null;
|
return this.version == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(1)
|
||||||
public UUID getVersion() {
|
public UUID getVersion() {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
@ -95,6 +91,26 @@ public class SessionEntityWrapper<S extends SessionEntity> {
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
|
WrappedMessage getEntityPS() {
|
||||||
|
return new WrappedMessage(getEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 3, mapImplementation = ConcurrentHashMap.class)
|
||||||
|
public Map<String, String> getLocalMetadata() {
|
||||||
|
return localMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtoFactory
|
||||||
|
static <T extends SessionEntity> SessionEntityWrapper<T> create(UUID version, WrappedMessage entityPS, Map<String, String> localMetadata) {
|
||||||
|
assert entityPS != null;
|
||||||
|
T entity = (T) entityPS.getValue();
|
||||||
|
if (version == null) {
|
||||||
|
return new SessionEntityWrapper<>(entity);
|
||||||
|
}
|
||||||
|
return new SessionEntityWrapper<>(version, localMetadata, entity);
|
||||||
|
}
|
||||||
|
|
||||||
public ClientModel getClientIfNeeded(RealmModel realm) {
|
public ClientModel getClientIfNeeded(RealmModel realm) {
|
||||||
if (entity instanceof AuthenticatedClientSessionEntity) {
|
if (entity instanceof AuthenticatedClientSessionEntity) {
|
||||||
String clientId = ((AuthenticatedClientSessionEntity) entity).getClientId();
|
String clientId = ((AuthenticatedClientSessionEntity) entity).getClientId();
|
||||||
|
@ -124,24 +140,19 @@ public class SessionEntityWrapper<S extends SessionEntity> {
|
||||||
localMetadata.put(key, String.valueOf(value));
|
localMetadata.put(key, String.valueOf(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getLocalMetadata() {
|
|
||||||
return localMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) {
|
||||||
if (!(o instanceof SessionEntityWrapper)) return false;
|
return true;
|
||||||
|
}
|
||||||
SessionEntityWrapper that = (SessionEntityWrapper) o;
|
if (!(o instanceof SessionEntityWrapper)) {
|
||||||
|
|
||||||
if (!Objects.equals(version, that.version)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Objects.equals(entity, that.entity);
|
SessionEntityWrapper<?> that = (SessionEntityWrapper<?>) o;
|
||||||
}
|
|
||||||
|
|
||||||
|
return Objects.equals(version, that.version) && Objects.equals(entity, that.entity);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
|
@ -154,53 +165,4 @@ public class SessionEntityWrapper<S extends SessionEntity> {
|
||||||
return "SessionEntityWrapper{" + "version=" + version + ", entity=" + entity + ", localMetadata=" + localMetadata + '}';
|
return "SessionEntityWrapper{" + "version=" + version + ", entity=" + entity + ", localMetadata=" + localMetadata + '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<SessionEntityWrapper> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, SessionEntityWrapper obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
final boolean forTransport = obj.isForTransport();
|
|
||||||
output.writeBoolean(forTransport);
|
|
||||||
|
|
||||||
if (! forTransport) {
|
|
||||||
output.writeLong(obj.getVersion().getMostSignificantBits());
|
|
||||||
output.writeLong(obj.getVersion().getLeastSignificantBits());
|
|
||||||
MarshallUtil.marshallMap(obj.localMetadata, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
output.writeObject(obj.entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SessionEntityWrapper readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
byte version = input.readByte();
|
|
||||||
|
|
||||||
if (version != VERSION_1) {
|
|
||||||
throw new IOException("Invalid version: " + version);
|
|
||||||
}
|
|
||||||
final boolean forTransport = input.readBoolean();
|
|
||||||
|
|
||||||
if (forTransport) {
|
|
||||||
final SessionEntity entity = (SessionEntity) input.readObject();
|
|
||||||
final SessionEntityWrapper res = new SessionEntityWrapper(entity);
|
|
||||||
if (log.isTraceEnabled()) {
|
|
||||||
log.tracef("Loaded entity from remote store: %s, version=%s, metadata=%s", entity, res.version, res.localMetadata);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
} else {
|
|
||||||
UUID sessionVersion = new UUID(input.readLong(), input.readLong());
|
|
||||||
HashMap<String, String> map = MarshallUtil.<String, String, HashMap<String, String>>unmarshallMap(input, HashMap::new);
|
|
||||||
final SessionEntity entity = (SessionEntity) input.readObject();
|
|
||||||
if (log.isTraceEnabled()) {
|
|
||||||
log.tracef("Found entity locally: entity=%s, version=%s, metadata=%s", entity, sessionVersion, map);
|
|
||||||
}
|
|
||||||
return new SessionEntityWrapper(sessionVersion, map, entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,8 +66,8 @@ public class CrossDCLastSessionRefreshListener implements ClusterListener {
|
||||||
|
|
||||||
lastSessionRefreshes.entrySet().stream().forEach((entry) -> {
|
lastSessionRefreshes.entrySet().stream().forEach((entry) -> {
|
||||||
String sessionId = entry.getKey();
|
String sessionId = entry.getKey();
|
||||||
String realmId = entry.getValue().getRealmId();
|
String realmId = entry.getValue().realmId();
|
||||||
int lastSessionRefresh = entry.getValue().getLastSessionRefresh();
|
int lastSessionRefresh = entry.getValue().lastSessionRefresh();
|
||||||
|
|
||||||
// All nodes will receive the message. So ensure that each node updates just lastSessionRefreshes owned by him.
|
// All nodes will receive the message. So ensure that each node updates just lastSessionRefreshes owned by him.
|
||||||
if (shouldUpdateLocalCache(sessionId)) {
|
if (shouldUpdateLocalCache(sessionId)) {
|
||||||
|
|
|
@ -17,30 +17,29 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.changes.sessions;
|
package org.keycloak.models.sessions.infinispan.changes.sessions;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import java.io.ObjectInput;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
import java.io.ObjectOutput;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.keycloak.cluster.ClusterEvent;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
import org.keycloak.cluster.ClusterEvent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(LastSessionRefreshEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.LAST_SESSION_REFRESH_EVENT)
|
||||||
public class LastSessionRefreshEvent implements ClusterEvent {
|
public class LastSessionRefreshEvent implements ClusterEvent {
|
||||||
|
|
||||||
private final Map<String, SessionData> lastSessionRefreshes;
|
private final Map<String, SessionData> lastSessionRefreshes;
|
||||||
|
|
||||||
|
@ProtoFactory
|
||||||
public LastSessionRefreshEvent(Map<String, SessionData> lastSessionRefreshes) {
|
public LastSessionRefreshEvent(Map<String, SessionData> lastSessionRefreshes) {
|
||||||
this.lastSessionRefreshes = lastSessionRefreshes;
|
this.lastSessionRefreshes = lastSessionRefreshes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 1, mapImplementation = HashMap.class)
|
||||||
public Map<String, SessionData> getLastSessionRefreshes() {
|
public Map<String, SessionData> getLastSessionRefreshes() {
|
||||||
return lastSessionRefreshes;
|
return lastSessionRefreshes;
|
||||||
}
|
}
|
||||||
|
@ -55,29 +54,4 @@ public class LastSessionRefreshEvent implements ClusterEvent {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<LastSessionRefreshEvent> {
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, LastSessionRefreshEvent obj) throws IOException {
|
|
||||||
MarshallUtil.marshallMap(obj.lastSessionRefreshes, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LastSessionRefreshEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
Map<String, SessionData> map = MarshallUtil.unmarshallMap(input, new MarshallUtil.MapBuilder<String, SessionData, Map<String, SessionData>>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, SessionData> build(int size) {
|
|
||||||
return new HashMap<>(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
LastSessionRefreshEvent event = new LastSessionRefreshEvent(map);
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class PersisterLastSessionRefreshStore extends AbstractLastSessionRefresh
|
||||||
protected void sendMessage(KeycloakSession kcSession, Map<String, SessionData> refreshesToSend) {
|
protected void sendMessage(KeycloakSession kcSession, Map<String, SessionData> refreshesToSend) {
|
||||||
Map<String, Set<String>> sessionIdsByRealm =
|
Map<String, Set<String>> sessionIdsByRealm =
|
||||||
refreshesToSend.entrySet().stream().collect(
|
refreshesToSend.entrySet().stream().collect(
|
||||||
Collectors.groupingBy(entry -> entry.getValue().getRealmId(),
|
Collectors.groupingBy(entry -> entry.getValue().realmId(),
|
||||||
Collectors.mapping(Map.Entry::getKey, Collectors.toSet())));
|
Collectors.mapping(Map.Entry::getKey, Collectors.toSet())));
|
||||||
|
|
||||||
// Update DB with a bit lower value than current time to ensure 'revokeRefreshToken' will work correctly taking server
|
// Update DB with a bit lower value than current time to ensure 'revokeRefreshToken' will work correctly taking server
|
||||||
|
|
|
@ -17,59 +17,17 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.changes.sessions;
|
package org.keycloak.models.sessions.infinispan.changes.sessions;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.infinispan.protostream.annotations.Proto;
|
||||||
import java.io.ObjectInput;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import java.io.ObjectOutput;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.KeycloakMarshallUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(SessionData.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.SESSION_DATA)
|
||||||
public class SessionData {
|
@Proto
|
||||||
|
public record SessionData(String realmId, int lastSessionRefresh) {
|
||||||
|
|
||||||
private final String realmId;
|
|
||||||
private final int lastSessionRefresh;
|
|
||||||
|
|
||||||
public SessionData(String realmId, int lastSessionRefresh) {
|
|
||||||
this.realmId = realmId;
|
|
||||||
this.lastSessionRefresh = lastSessionRefresh;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRealmId() {
|
|
||||||
return realmId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLastSessionRefresh() {
|
|
||||||
return lastSessionRefresh;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("realmId: %s, lastSessionRefresh: %d", realmId, lastSessionRefresh);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<SessionData> {
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, SessionData obj) throws IOException {
|
|
||||||
MarshallUtil.marshallString(obj.realmId, output);
|
|
||||||
KeycloakMarshallUtil.marshall(obj.lastSessionRefresh, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SessionData readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
String realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
int lastSessionRefresh = KeycloakMarshallUtil.unmarshallInteger(input);
|
|
||||||
|
|
||||||
return new SessionData(realmId, lastSessionRefresh);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,26 +17,24 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.entities;
|
package org.keycloak.models.sessions.infinispan.entities;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import java.io.ObjectInput;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
import java.io.ObjectOutput;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
||||||
import org.keycloak.models.sessions.infinispan.util.KeycloakMarshallUtil;
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(AuthenticatedClientSessionEntity.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.AUTHENTICATED_CLIENT_SESSION_ENTITY)
|
||||||
public class AuthenticatedClientSessionEntity extends SessionEntity {
|
public class AuthenticatedClientSessionEntity extends SessionEntity {
|
||||||
|
|
||||||
public static final Logger logger = Logger.getLogger(AuthenticatedClientSessionEntity.class);
|
public static final Logger logger = Logger.getLogger(AuthenticatedClientSessionEntity.class);
|
||||||
|
@ -60,6 +58,7 @@ public class AuthenticatedClientSessionEntity extends SessionEntity {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
public String getAuthMethod() {
|
public String getAuthMethod() {
|
||||||
return authMethod;
|
return authMethod;
|
||||||
}
|
}
|
||||||
|
@ -68,6 +67,7 @@ public class AuthenticatedClientSessionEntity extends SessionEntity {
|
||||||
this.authMethod = authMethod;
|
this.authMethod = authMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(3)
|
||||||
public String getRedirectUri() {
|
public String getRedirectUri() {
|
||||||
return redirectUri;
|
return redirectUri;
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ public class AuthenticatedClientSessionEntity extends SessionEntity {
|
||||||
this.redirectUri = redirectUri;
|
this.redirectUri = redirectUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(4)
|
||||||
public int getTimestamp() {
|
public int getTimestamp() {
|
||||||
return timestamp;
|
return timestamp;
|
||||||
}
|
}
|
||||||
|
@ -106,6 +107,7 @@ public class AuthenticatedClientSessionEntity extends SessionEntity {
|
||||||
getNotes().put(CLIENT_ID_NOTE, clientId);
|
getNotes().put(CLIENT_ID_NOTE, clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 5)
|
||||||
public String getAction() {
|
public String getAction() {
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
@ -114,6 +116,7 @@ public class AuthenticatedClientSessionEntity extends SessionEntity {
|
||||||
this.action = action;
|
this.action = action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 6, mapImplementation = ConcurrentHashMap.class)
|
||||||
public Map<String, String> getNotes() {
|
public Map<String, String> getNotes() {
|
||||||
return notes;
|
return notes;
|
||||||
}
|
}
|
||||||
|
@ -122,6 +125,7 @@ public class AuthenticatedClientSessionEntity extends SessionEntity {
|
||||||
this.notes = notes;
|
this.notes = notes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(7)
|
||||||
public UUID getId() {
|
public UUID getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -133,15 +137,27 @@ public class AuthenticatedClientSessionEntity extends SessionEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) {
|
||||||
if (!(o instanceof AuthenticatedClientSessionEntity)) return false;
|
|
||||||
|
|
||||||
AuthenticatedClientSessionEntity that = (AuthenticatedClientSessionEntity) o;
|
|
||||||
|
|
||||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (!(o instanceof AuthenticatedClientSessionEntity that)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Objects.equals(id, that.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// factory method required because of final fields
|
||||||
|
@ProtoFactory
|
||||||
|
AuthenticatedClientSessionEntity(String realmId, String authMethod, String redirectUri, int timestamp, String action, Map<String, String> notes, UUID id) {
|
||||||
|
super(realmId);
|
||||||
|
this.authMethod = authMethod;
|
||||||
|
this.redirectUri = redirectUri;
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.action = action;
|
||||||
|
this.notes = notes;
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
|
@ -180,42 +196,4 @@ public class AuthenticatedClientSessionEntity extends SessionEntity {
|
||||||
public void setUserSessionId(String userSessionId) {
|
public void setUserSessionId(String userSessionId) {
|
||||||
this.userSessionId = userSessionId;
|
this.userSessionId = userSessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<AuthenticatedClientSessionEntity> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, AuthenticatedClientSessionEntity session) throws IOException {
|
|
||||||
MarshallUtil.marshallUUID(session.id, output, false);
|
|
||||||
MarshallUtil.marshallString(session.getRealmId(), output);
|
|
||||||
MarshallUtil.marshallString(session.getAuthMethod(), output);
|
|
||||||
MarshallUtil.marshallString(session.getRedirectUri(), output);
|
|
||||||
KeycloakMarshallUtil.marshall(session.getTimestamp(), output);
|
|
||||||
MarshallUtil.marshallString(session.getAction(), output);
|
|
||||||
|
|
||||||
Map<String, String> notes = session.getNotes();
|
|
||||||
KeycloakMarshallUtil.writeMap(notes, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthenticatedClientSessionEntity readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
AuthenticatedClientSessionEntity sessionEntity = new AuthenticatedClientSessionEntity(MarshallUtil.unmarshallUUID(input, false));
|
|
||||||
|
|
||||||
sessionEntity.setRealmId(MarshallUtil.unmarshallString(input));
|
|
||||||
|
|
||||||
sessionEntity.setAuthMethod(MarshallUtil.unmarshallString(input));
|
|
||||||
sessionEntity.setRedirectUri(MarshallUtil.unmarshallString(input));
|
|
||||||
sessionEntity.setTimestamp(KeycloakMarshallUtil.unmarshallInteger(input));
|
|
||||||
sessionEntity.setAction(MarshallUtil.unmarshallString(input));
|
|
||||||
|
|
||||||
Map<String, String> notes = KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT,
|
|
||||||
new KeycloakMarshallUtil.ConcurrentHashMapBuilder<>());
|
|
||||||
sessionEntity.setNotes(notes);
|
|
||||||
|
|
||||||
return sessionEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,34 +16,35 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.sessions.infinispan.entities;
|
package org.keycloak.models.sessions.infinispan.entities;
|
||||||
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.KeycloakMarshallUtil;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import java.io.IOException;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
import java.io.ObjectInput;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import java.io.ObjectOutput;
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author hmlnarik
|
* @author hmlnarik
|
||||||
*/
|
*/
|
||||||
@SerializeWith(AuthenticatedClientSessionStore.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.AUTHENTICATED_CLIENT_SESSION_STORE)
|
||||||
public class AuthenticatedClientSessionStore {
|
public class AuthenticatedClientSessionStore {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps client UUID to client session ID.
|
* Maps client UUID to client session ID.
|
||||||
*/
|
*/
|
||||||
private final ConcurrentHashMap<String, UUID> authenticatedClientSessionIds;
|
private final ConcurrentMap<String, UUID> authenticatedClientSessionIds;
|
||||||
|
|
||||||
public AuthenticatedClientSessionStore() {
|
public AuthenticatedClientSessionStore() {
|
||||||
authenticatedClientSessionIds = new ConcurrentHashMap<>();
|
authenticatedClientSessionIds = new ConcurrentHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private AuthenticatedClientSessionStore(ConcurrentHashMap<String, UUID> authenticatedClientSessionIds) {
|
@ProtoFactory
|
||||||
|
AuthenticatedClientSessionStore(ConcurrentMap<String, UUID> authenticatedClientSessionIds) {
|
||||||
this.authenticatedClientSessionIds = authenticatedClientSessionIds;
|
this.authenticatedClientSessionIds = authenticatedClientSessionIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,37 +80,14 @@ public class AuthenticatedClientSessionStore {
|
||||||
return authenticatedClientSessionIds.size();
|
return authenticatedClientSessionIds.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 1, mapImplementation = ConcurrentHashMap.class)
|
||||||
|
ConcurrentMap<String, UUID> getAuthenticatedClientSessionIds() {
|
||||||
|
return authenticatedClientSessionIds;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.authenticatedClientSessionIds.toString();
|
return this.authenticatedClientSessionIds.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<AuthenticatedClientSessionStore> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, AuthenticatedClientSessionStore obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
KeycloakMarshallUtil.writeMap(obj.authenticatedClientSessionIds, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.UUID_EXT, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthenticatedClientSessionStore readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthenticatedClientSessionStore readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
AuthenticatedClientSessionStore res = new AuthenticatedClientSessionStore(
|
|
||||||
KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.UUID_EXT, ConcurrentHashMap::new)
|
|
||||||
);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,17 +17,12 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.entities;
|
package org.keycloak.models.sessions.infinispan.entities;
|
||||||
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.keycloak.models.sessions.infinispan.util.KeycloakMarshallUtil;
|
|
||||||
import org.keycloak.sessions.AuthenticationSessionModel;
|
import org.keycloak.sessions.AuthenticationSessionModel;
|
||||||
import org.keycloak.sessions.CommonClientSessionModel.ExecutionStatus;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.util.HashSet;
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
@ -35,8 +30,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(AuthenticationSessionEntity.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.AUTHENTICATION_SESSION_ENTITY)
|
||||||
public class AuthenticationSessionEntity implements Serializable {
|
public class AuthenticationSessionEntity {
|
||||||
|
|
||||||
private String clientUUID;
|
private String clientUUID;
|
||||||
|
|
||||||
|
@ -93,6 +88,7 @@ public class AuthenticationSessionEntity implements Serializable {
|
||||||
this.userSessionNotes = userSessionNotes;
|
this.userSessionNotes = userSessionNotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(1)
|
||||||
public String getClientUUID() {
|
public String getClientUUID() {
|
||||||
return clientUUID;
|
return clientUUID;
|
||||||
}
|
}
|
||||||
|
@ -101,6 +97,7 @@ public class AuthenticationSessionEntity implements Serializable {
|
||||||
this.clientUUID = clientUUID;
|
this.clientUUID = clientUUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
public String getAuthUserId() {
|
public String getAuthUserId() {
|
||||||
return authUserId;
|
return authUserId;
|
||||||
}
|
}
|
||||||
|
@ -109,6 +106,7 @@ public class AuthenticationSessionEntity implements Serializable {
|
||||||
this.authUserId = authUserId;
|
this.authUserId = authUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(3)
|
||||||
public int getTimestamp() {
|
public int getTimestamp() {
|
||||||
return timestamp;
|
return timestamp;
|
||||||
}
|
}
|
||||||
|
@ -117,6 +115,7 @@ public class AuthenticationSessionEntity implements Serializable {
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(4)
|
||||||
public String getRedirectUri() {
|
public String getRedirectUri() {
|
||||||
return redirectUri;
|
return redirectUri;
|
||||||
}
|
}
|
||||||
|
@ -125,6 +124,7 @@ public class AuthenticationSessionEntity implements Serializable {
|
||||||
this.redirectUri = redirectUri;
|
this.redirectUri = redirectUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(5)
|
||||||
public String getAction() {
|
public String getAction() {
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
@ -133,6 +133,7 @@ public class AuthenticationSessionEntity implements Serializable {
|
||||||
this.action = action;
|
this.action = action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 6, collectionImplementation = HashSet.class)
|
||||||
public Set<String> getClientScopes() {
|
public Set<String> getClientScopes() {
|
||||||
return clientScopes;
|
return clientScopes;
|
||||||
}
|
}
|
||||||
|
@ -141,6 +142,7 @@ public class AuthenticationSessionEntity implements Serializable {
|
||||||
this.clientScopes = clientScopes;
|
this.clientScopes = clientScopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 7, mapImplementation = ConcurrentHashMap.class)
|
||||||
public Map<String, AuthenticationSessionModel.ExecutionStatus> getExecutionStatus() {
|
public Map<String, AuthenticationSessionModel.ExecutionStatus> getExecutionStatus() {
|
||||||
return executionStatus;
|
return executionStatus;
|
||||||
}
|
}
|
||||||
|
@ -149,6 +151,7 @@ public class AuthenticationSessionEntity implements Serializable {
|
||||||
this.executionStatus = executionStatus;
|
this.executionStatus = executionStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(8)
|
||||||
public String getProtocol() {
|
public String getProtocol() {
|
||||||
return protocol;
|
return protocol;
|
||||||
}
|
}
|
||||||
|
@ -157,6 +160,7 @@ public class AuthenticationSessionEntity implements Serializable {
|
||||||
this.protocol = protocol;
|
this.protocol = protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 9, mapImplementation = ConcurrentHashMap.class)
|
||||||
public Map<String, String> getClientNotes() {
|
public Map<String, String> getClientNotes() {
|
||||||
return clientNotes;
|
return clientNotes;
|
||||||
}
|
}
|
||||||
|
@ -165,6 +169,7 @@ public class AuthenticationSessionEntity implements Serializable {
|
||||||
this.clientNotes = clientNotes;
|
this.clientNotes = clientNotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 10, collectionImplementation = HashSet.class)
|
||||||
public Set<String> getRequiredActions() {
|
public Set<String> getRequiredActions() {
|
||||||
return requiredActions;
|
return requiredActions;
|
||||||
}
|
}
|
||||||
|
@ -173,6 +178,7 @@ public class AuthenticationSessionEntity implements Serializable {
|
||||||
this.requiredActions = requiredActions;
|
this.requiredActions = requiredActions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 11, mapImplementation = ConcurrentHashMap.class)
|
||||||
public Map<String, String> getUserSessionNotes() {
|
public Map<String, String> getUserSessionNotes() {
|
||||||
return userSessionNotes;
|
return userSessionNotes;
|
||||||
}
|
}
|
||||||
|
@ -181,6 +187,7 @@ public class AuthenticationSessionEntity implements Serializable {
|
||||||
this.userSessionNotes = userSessionNotes;
|
this.userSessionNotes = userSessionNotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 12, mapImplementation = ConcurrentHashMap.class)
|
||||||
public Map<String, String> getAuthNotes() {
|
public Map<String, String> getAuthNotes() {
|
||||||
return authNotes;
|
return authNotes;
|
||||||
}
|
}
|
||||||
|
@ -188,109 +195,4 @@ public class AuthenticationSessionEntity implements Serializable {
|
||||||
public void setAuthNotes(Map<String, String> authNotes) {
|
public void setAuthNotes(Map<String, String> authNotes) {
|
||||||
this.authNotes = authNotes;
|
this.authNotes = authNotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<AuthenticationSessionEntity> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
private static final int VERSION_2 = 2;
|
|
||||||
|
|
||||||
public static final ExternalizerImpl INSTANCE = new ExternalizerImpl();
|
|
||||||
|
|
||||||
private static AuthenticationSessionModel.ExecutionStatus fromOrdinal(int ordinal) {
|
|
||||||
ExecutionStatus[] values = AuthenticationSessionModel.ExecutionStatus.values();
|
|
||||||
return (ordinal < 0 || ordinal >= values.length)
|
|
||||||
? null
|
|
||||||
: values[ordinal];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Externalizer<AuthenticationSessionModel.ExecutionStatus> EXECUTION_STATUS_EXT = new Externalizer<AuthenticationSessionModel.ExecutionStatus>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, AuthenticationSessionModel.ExecutionStatus e) throws IOException {
|
|
||||||
MarshallUtil.marshallEnum(e, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthenticationSessionModel.ExecutionStatus readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
return MarshallUtil.unmarshallEnum(input, ExternalizerImpl::fromOrdinal);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, AuthenticationSessionEntity value) throws IOException {
|
|
||||||
output.writeByte(VERSION_2);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(value.clientUUID, output);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(value.authUserId, output);
|
|
||||||
|
|
||||||
output.writeInt(value.timestamp);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(value.redirectUri, output);
|
|
||||||
MarshallUtil.marshallString(value.action, output);
|
|
||||||
KeycloakMarshallUtil.writeCollection(value.clientScopes, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
|
|
||||||
KeycloakMarshallUtil.writeMap(value.executionStatus, KeycloakMarshallUtil.STRING_EXT, EXECUTION_STATUS_EXT, output);
|
|
||||||
MarshallUtil.marshallString(value.protocol, output);
|
|
||||||
|
|
||||||
KeycloakMarshallUtil.writeMap(value.clientNotes, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
KeycloakMarshallUtil.writeMap(value.authNotes, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
KeycloakMarshallUtil.writeCollection(value.requiredActions, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
KeycloakMarshallUtil.writeMap(value.userSessionNotes, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthenticationSessionEntity readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
case VERSION_2:
|
|
||||||
return readObjectVersion2(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthenticationSessionEntity readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
return new AuthenticationSessionEntity(
|
|
||||||
MarshallUtil.unmarshallString(input), // clientUUID
|
|
||||||
|
|
||||||
MarshallUtil.unmarshallString(input), // authUserId
|
|
||||||
|
|
||||||
MarshallUtil.unmarshallString(input), // redirectUri
|
|
||||||
MarshallUtil.unmarshallString(input), // action
|
|
||||||
KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, ConcurrentHashMap::newKeySet), // clientScopes
|
|
||||||
|
|
||||||
KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, EXECUTION_STATUS_EXT, size -> new ConcurrentHashMap<>(size)), // executionStatus
|
|
||||||
MarshallUtil.unmarshallString(input), // protocol
|
|
||||||
|
|
||||||
KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, size -> new ConcurrentHashMap<>(size)), // clientNotes
|
|
||||||
KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, size -> new ConcurrentHashMap<>(size)), // authNotes
|
|
||||||
KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, ConcurrentHashMap::newKeySet), // requiredActions
|
|
||||||
KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, size -> new ConcurrentHashMap<>(size)) // userSessionNotes
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthenticationSessionEntity readObjectVersion2(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
return new AuthenticationSessionEntity(
|
|
||||||
MarshallUtil.unmarshallString(input), // clientUUID
|
|
||||||
|
|
||||||
MarshallUtil.unmarshallString(input), // authUserId
|
|
||||||
|
|
||||||
input.readInt(), // timestamp
|
|
||||||
|
|
||||||
MarshallUtil.unmarshallString(input), // redirectUri
|
|
||||||
MarshallUtil.unmarshallString(input), // action
|
|
||||||
KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, ConcurrentHashMap::newKeySet), // clientScopes
|
|
||||||
|
|
||||||
KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, EXECUTION_STATUS_EXT, size -> new ConcurrentHashMap<>(size)), // executionStatus
|
|
||||||
MarshallUtil.unmarshallString(input), // protocol
|
|
||||||
|
|
||||||
KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, size -> new ConcurrentHashMap<>(size)), // clientNotes
|
|
||||||
KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, size -> new ConcurrentHashMap<>(size)), // authNotes
|
|
||||||
KeycloakMarshallUtil.readCollection(input, KeycloakMarshallUtil.STRING_EXT, ConcurrentHashMap::newKeySet), // requiredActions
|
|
||||||
KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, size -> new ConcurrentHashMap<>(size)) // userSessionNotes
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,17 +17,16 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.entities;
|
package org.keycloak.models.sessions.infinispan.entities;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
import java.io.ObjectInput;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import java.io.ObjectOutput;
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import java.util.Objects;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(LoginFailureEntity.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.LOGIN_FAILURE_ENTITY)
|
||||||
public class LoginFailureEntity extends SessionEntity {
|
public class LoginFailureEntity extends SessionEntity {
|
||||||
|
|
||||||
private String userId;
|
private String userId;
|
||||||
|
@ -51,6 +50,7 @@ public class LoginFailureEntity extends SessionEntity {
|
||||||
this.lastIPFailure = lastIPFailure;
|
this.lastIPFailure = lastIPFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
public String getUserId() {
|
public String getUserId() {
|
||||||
return userId;
|
return userId;
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@ public class LoginFailureEntity extends SessionEntity {
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(3)
|
||||||
public int getFailedLoginNotBefore() {
|
public int getFailedLoginNotBefore() {
|
||||||
return failedLoginNotBefore;
|
return failedLoginNotBefore;
|
||||||
}
|
}
|
||||||
|
@ -69,6 +70,7 @@ public class LoginFailureEntity extends SessionEntity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(4)
|
||||||
public int getNumFailures() {
|
public int getNumFailures() {
|
||||||
return numFailures;
|
return numFailures;
|
||||||
}
|
}
|
||||||
|
@ -77,6 +79,7 @@ public class LoginFailureEntity extends SessionEntity {
|
||||||
this.numFailures = numFailures;
|
this.numFailures = numFailures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(5)
|
||||||
public int getNumTemporaryLockouts() {
|
public int getNumTemporaryLockouts() {
|
||||||
return numTemporaryLockouts;
|
return numTemporaryLockouts;
|
||||||
}
|
}
|
||||||
|
@ -85,6 +88,7 @@ public class LoginFailureEntity extends SessionEntity {
|
||||||
this.numTemporaryLockouts = numTemporaryLockouts;
|
this.numTemporaryLockouts = numTemporaryLockouts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(6)
|
||||||
public long getLastFailure() {
|
public long getLastFailure() {
|
||||||
return lastFailure;
|
return lastFailure;
|
||||||
}
|
}
|
||||||
|
@ -95,6 +99,7 @@ public class LoginFailureEntity extends SessionEntity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(7)
|
||||||
public String getLastIPFailure() {
|
public String getLastIPFailure() {
|
||||||
return lastIPFailure;
|
return lastIPFailure;
|
||||||
}
|
}
|
||||||
|
@ -113,17 +118,18 @@ public class LoginFailureEntity extends SessionEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) {
|
||||||
if (!(o instanceof LoginFailureEntity)) return false;
|
|
||||||
|
|
||||||
LoginFailureEntity that = (LoginFailureEntity) o;
|
|
||||||
|
|
||||||
if (userId != null ? !userId.equals(that.userId) : that.userId != null) return false;
|
|
||||||
if (getRealmId() != null ? !getRealmId().equals(that.getRealmId()) : that.getRealmId() != null) return false;
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (!(o instanceof LoginFailureEntity that)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Objects.equals(userId, that.userId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return getRealmId() != null ? getRealmId().equals(that.getRealmId()) : that.getRealmId() == null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
|
@ -137,43 +143,4 @@ public class LoginFailureEntity extends SessionEntity {
|
||||||
return String.format("LoginFailureEntity [ userId=%s, realm=%s, numFailures=%d ]", userId, getRealmId(), numFailures);
|
return String.format("LoginFailureEntity [ userId=%s, realm=%s, numFailures=%d ]", userId, getRealmId(), numFailures);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<LoginFailureEntity> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, LoginFailureEntity value) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(value.getRealmId(), output);
|
|
||||||
MarshallUtil.marshallString(value.userId, output);
|
|
||||||
output.writeInt(value.failedLoginNotBefore);
|
|
||||||
output.writeInt(value.numFailures);
|
|
||||||
output.writeInt(value.numTemporaryLockouts);
|
|
||||||
output.writeLong(value.lastFailure);
|
|
||||||
MarshallUtil.marshallString(value.lastIPFailure, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LoginFailureEntity readObject(ObjectInput input) throws IOException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LoginFailureEntity readObjectVersion1(ObjectInput input) throws IOException {
|
|
||||||
return new LoginFailureEntity(
|
|
||||||
MarshallUtil.unmarshallString(input),
|
|
||||||
MarshallUtil.unmarshallString(input),
|
|
||||||
input.readInt(),
|
|
||||||
input.readInt(),
|
|
||||||
input.readInt(),
|
|
||||||
input.readLong(),
|
|
||||||
MarshallUtil.unmarshallString(input)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,77 +17,14 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.entities;
|
package org.keycloak.models.sessions.infinispan.entities;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.infinispan.protostream.annotations.Proto;
|
||||||
import java.io.ObjectInput;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import java.io.ObjectOutput;
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(LoginFailureKey.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.LOGIN_FAILURE_KEY)
|
||||||
public class LoginFailureKey {
|
@Proto
|
||||||
|
public record LoginFailureKey(String realmId, String userId) {
|
||||||
private final String realmId;
|
|
||||||
private final String userId;
|
|
||||||
|
|
||||||
public LoginFailureKey(String realmId, String userId) {
|
|
||||||
this.realmId = realmId;
|
|
||||||
this.userId = userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
|
|
||||||
LoginFailureKey key = (LoginFailureKey) o;
|
|
||||||
|
|
||||||
if (realmId != null ? !realmId.equals(key.realmId) : key.realmId != null) return false;
|
|
||||||
if (userId != null ? !userId.equals(key.userId) : key.userId != null) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = realmId != null ? realmId.hashCode() : 0;
|
|
||||||
result = 31 * result + (userId != null ? userId.hashCode() : 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("LoginFailureKey [ realmId=%s. userId=%s ]", realmId, userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<LoginFailureKey> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, LoginFailureKey value) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(value.realmId, output);
|
|
||||||
MarshallUtil.marshallString(value.userId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LoginFailureKey readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LoginFailureKey readObjectVersion1(ObjectInput input) throws IOException {
|
|
||||||
return new LoginFailureKey(MarshallUtil.unmarshallString(input), MarshallUtil.unmarshallString(input));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,20 +17,19 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.entities;
|
package org.keycloak.models.sessions.infinispan.entities;
|
||||||
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.KeycloakMarshallUtil;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import java.io.IOException;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
import java.io.ObjectInput;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import java.io.ObjectOutput;
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(RootAuthenticationSessionEntity.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.ROOT_AUTHENTICATION_SESSION_ENTITY)
|
||||||
public class RootAuthenticationSessionEntity extends SessionEntity {
|
public class RootAuthenticationSessionEntity extends SessionEntity {
|
||||||
|
|
||||||
private final String id;
|
private final String id;
|
||||||
|
@ -48,10 +47,17 @@ public class RootAuthenticationSessionEntity extends SessionEntity {
|
||||||
this.authenticationSessions = authenticationSessions;
|
this.authenticationSessions = authenticationSessions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoFactory
|
||||||
|
static RootAuthenticationSessionEntity protoFactory(String realmId, String id, int timestamp, Map<String, AuthenticationSessionEntity> authenticationSessions) {
|
||||||
|
return new RootAuthenticationSessionEntity(realmId, id, timestamp, authenticationSessions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(3)
|
||||||
public int getTimestamp() {
|
public int getTimestamp() {
|
||||||
return timestamp;
|
return timestamp;
|
||||||
}
|
}
|
||||||
|
@ -60,6 +66,7 @@ public class RootAuthenticationSessionEntity extends SessionEntity {
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 4, mapImplementation = ConcurrentHashMap.class)
|
||||||
public Map<String, AuthenticationSessionEntity> getAuthenticationSessions() {
|
public Map<String, AuthenticationSessionEntity> getAuthenticationSessions() {
|
||||||
return authenticationSessions;
|
return authenticationSessions;
|
||||||
}
|
}
|
||||||
|
@ -70,15 +77,13 @@ public class RootAuthenticationSessionEntity extends SessionEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) {
|
||||||
if (!(o instanceof RootAuthenticationSessionEntity)) return false;
|
|
||||||
|
|
||||||
RootAuthenticationSessionEntity that = (RootAuthenticationSessionEntity) o;
|
|
||||||
|
|
||||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return o instanceof RootAuthenticationSessionEntity that &&
|
||||||
|
Objects.equals(id, that.id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
|
@ -90,41 +95,4 @@ public class RootAuthenticationSessionEntity extends SessionEntity {
|
||||||
return String.format("RootAuthenticationSessionEntity [ id=%s, realm=%s ]", getId(), getRealmId());
|
return String.format("RootAuthenticationSessionEntity [ id=%s, realm=%s ]", getId(), getRealmId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<RootAuthenticationSessionEntity> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, RootAuthenticationSessionEntity value) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(value.getRealmId(), output);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(value.id, output);
|
|
||||||
output.writeInt(value.timestamp);
|
|
||||||
|
|
||||||
KeycloakMarshallUtil.writeMap(value.authenticationSessions, KeycloakMarshallUtil.STRING_EXT, AuthenticationSessionEntity.ExternalizerImpl.INSTANCE, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RootAuthenticationSessionEntity readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RootAuthenticationSessionEntity readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
return new RootAuthenticationSessionEntity(
|
|
||||||
MarshallUtil.unmarshallString(input), // realmId
|
|
||||||
|
|
||||||
MarshallUtil.unmarshallString(input), // id
|
|
||||||
input.readInt(), // timestamp
|
|
||||||
|
|
||||||
KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, AuthenticationSessionEntity.ExternalizerImpl.INSTANCE, size -> new ConcurrentHashMap<>(size)) // authenticationSessions
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.entities;
|
package org.keycloak.models.sessions.infinispan.entities;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
|
||||||
import org.keycloak.common.Profile;
|
import org.keycloak.common.Profile;
|
||||||
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
||||||
|
|
||||||
|
@ -30,7 +29,7 @@ import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
public abstract class SessionEntity implements Serializable {
|
public abstract class SessionEntity {
|
||||||
|
|
||||||
private String realmId;
|
private String realmId;
|
||||||
private boolean isOffline;
|
private boolean isOffline;
|
||||||
|
@ -39,6 +38,7 @@ public abstract class SessionEntity implements Serializable {
|
||||||
* Returns realmId ID.
|
* Returns realmId ID.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@ProtoField(1)
|
||||||
public String getRealmId() {
|
public String getRealmId() {
|
||||||
return realmId;
|
return realmId;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ public abstract class SessionEntity implements Serializable {
|
||||||
} else {
|
} else {
|
||||||
return new SessionEntityWrapper<>(localEntityWrapper.getLocalMetadata(), this);
|
return new SessionEntityWrapper<>(localEntityWrapper.getLocalMetadata(), this);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract boolean equals(Object obj);
|
public abstract boolean equals(Object obj);
|
||||||
|
|
|
@ -16,28 +16,40 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.sessions.infinispan.entities;
|
package org.keycloak.models.sessions.infinispan.entities;
|
||||||
|
|
||||||
import org.keycloak.models.SingleUseObjectValueModel;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import java.io.*;
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
import java.util.*;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
import org.keycloak.models.SingleUseObjectValueModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author hmlnarik
|
* @author hmlnarik
|
||||||
*/
|
*/
|
||||||
@SerializeWith(SingleUseObjectValueEntity.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.SINGLE_USE_OBJECT_VALUE_ENTITY)
|
||||||
public class SingleUseObjectValueEntity implements SingleUseObjectValueModel {
|
public class SingleUseObjectValueEntity implements SingleUseObjectValueModel {
|
||||||
|
|
||||||
private final Map<String, String> notes;
|
private final Map<String, String> notes;
|
||||||
|
|
||||||
|
@ProtoFactory
|
||||||
public SingleUseObjectValueEntity(Map<String, String> notes) {
|
public SingleUseObjectValueEntity(Map<String, String> notes) {
|
||||||
this.notes = notes == null ? Collections.EMPTY_MAP : new HashMap<>(notes);
|
if (notes == null || notes.isEmpty()) {
|
||||||
|
this.notes = Map.of();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var copy = new HashMap<>(notes);
|
||||||
|
// protostream does not support null values for primitive types as string
|
||||||
|
copy.values().removeIf(Objects::isNull);
|
||||||
|
this.notes = Map.copyOf(copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 1, mapImplementation = HashMap.class)
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> getNotes() {
|
public Map<String, String> getNotes() {
|
||||||
return Collections.unmodifiableMap(notes);
|
return notes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,32 +62,4 @@ public class SingleUseObjectValueEntity implements SingleUseObjectValueModel {
|
||||||
return String.format("SingleUseObjectValueEntity [ notes=%s ]", notes.toString());
|
return String.format("SingleUseObjectValueEntity [ notes=%s ]", notes.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<SingleUseObjectValueEntity> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, SingleUseObjectValueEntity t) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
output.writeBoolean(t.notes.isEmpty());
|
|
||||||
if (! t.notes.isEmpty()) {
|
|
||||||
output.writeObject(t.notes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SingleUseObjectValueEntity readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
byte version = input.readByte();
|
|
||||||
|
|
||||||
if (version != VERSION_1) {
|
|
||||||
throw new IOException("Invalid version: " + version);
|
|
||||||
}
|
|
||||||
boolean notesEmpty = input.readBoolean();
|
|
||||||
|
|
||||||
Map<String, String> notes = notesEmpty ? Collections.EMPTY_MAP : (Map<String, String>) input.readObject();
|
|
||||||
|
|
||||||
return new SingleUseObjectValueEntity(notes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,29 +17,23 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.entities;
|
package org.keycloak.models.sessions.infinispan.entities;
|
||||||
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.models.UserSessionModel;
|
|
||||||
import org.keycloak.models.UserSessionModel.State;
|
|
||||||
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
|
||||||
import org.keycloak.models.sessions.infinispan.util.KeycloakMarshallUtil;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.util.EnumMap;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Objects;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.infinispan.protostream.annotations.ProtoFactory;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.marshalling.Marshalling;
|
||||||
|
import org.keycloak.models.UserSessionModel;
|
||||||
|
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(UserSessionEntity.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.USER_SESSION_ENTITY)
|
||||||
public class UserSessionEntity extends SessionEntity {
|
public class UserSessionEntity extends SessionEntity {
|
||||||
|
|
||||||
public static final Logger logger = Logger.getLogger(UserSessionEntity.class);
|
public static final Logger logger = Logger.getLogger(UserSessionEntity.class);
|
||||||
|
@ -72,6 +66,26 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoFactory
|
||||||
|
static UserSessionEntity protoFactory(String realmId, String id, String user, String loginUsername, String ipAddress, String authMethod, boolean rememberMe, int started, int lastSessionRefresh, Map<String, String> notes, AuthenticatedClientSessionStore authenticatedClientSessions, UserSessionModel.State state, String brokerSessionId, String brokerUserId) {
|
||||||
|
var entity = new UserSessionEntity(id);
|
||||||
|
entity.setRealmId(realmId);
|
||||||
|
entity.setUser(user);
|
||||||
|
entity.setLoginUsername(loginUsername);
|
||||||
|
entity.setIpAddress(ipAddress);
|
||||||
|
entity.setAuthMethod(authMethod);
|
||||||
|
entity.setRememberMe(rememberMe);
|
||||||
|
entity.setStarted(started);
|
||||||
|
entity.setLastSessionRefresh(lastSessionRefresh);
|
||||||
|
entity.setBrokerSessionId(brokerSessionId);
|
||||||
|
entity.setBrokerUserId(brokerUserId);
|
||||||
|
entity.setState(state);
|
||||||
|
entity.setNotes(notes);
|
||||||
|
entity.setAuthenticatedClientSessions(authenticatedClientSessions);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -80,6 +94,7 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
|
|
||||||
private AuthenticatedClientSessionStore authenticatedClientSessions = new AuthenticatedClientSessionStore();
|
private AuthenticatedClientSessionStore authenticatedClientSessions = new AuthenticatedClientSessionStore();
|
||||||
|
|
||||||
|
@ProtoField(3)
|
||||||
public String getUser() {
|
public String getUser() {
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
@ -88,6 +103,7 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(4)
|
||||||
public String getLoginUsername() {
|
public String getLoginUsername() {
|
||||||
return loginUsername;
|
return loginUsername;
|
||||||
}
|
}
|
||||||
|
@ -96,6 +112,7 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
this.loginUsername = loginUsername;
|
this.loginUsername = loginUsername;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(5)
|
||||||
public String getIpAddress() {
|
public String getIpAddress() {
|
||||||
return ipAddress;
|
return ipAddress;
|
||||||
}
|
}
|
||||||
|
@ -104,6 +121,7 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
this.ipAddress = ipAddress;
|
this.ipAddress = ipAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(6)
|
||||||
public String getAuthMethod() {
|
public String getAuthMethod() {
|
||||||
return authMethod;
|
return authMethod;
|
||||||
}
|
}
|
||||||
|
@ -112,6 +130,7 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
this.authMethod = authMethod;
|
this.authMethod = authMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(7)
|
||||||
public boolean isRememberMe() {
|
public boolean isRememberMe() {
|
||||||
return rememberMe;
|
return rememberMe;
|
||||||
}
|
}
|
||||||
|
@ -120,6 +139,7 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
this.rememberMe = rememberMe;
|
this.rememberMe = rememberMe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(8)
|
||||||
public int getStarted() {
|
public int getStarted() {
|
||||||
return started;
|
return started;
|
||||||
}
|
}
|
||||||
|
@ -128,6 +148,7 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
this.started = started;
|
this.started = started;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(9)
|
||||||
public int getLastSessionRefresh() {
|
public int getLastSessionRefresh() {
|
||||||
return lastSessionRefresh;
|
return lastSessionRefresh;
|
||||||
}
|
}
|
||||||
|
@ -136,6 +157,7 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
this.lastSessionRefresh = lastSessionRefresh;
|
this.lastSessionRefresh = lastSessionRefresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 10, mapImplementation = ConcurrentHashMap.class)
|
||||||
public Map<String, String> getNotes() {
|
public Map<String, String> getNotes() {
|
||||||
return notes;
|
return notes;
|
||||||
}
|
}
|
||||||
|
@ -144,6 +166,7 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
this.notes = notes;
|
this.notes = notes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(11)
|
||||||
public AuthenticatedClientSessionStore getAuthenticatedClientSessions() {
|
public AuthenticatedClientSessionStore getAuthenticatedClientSessions() {
|
||||||
return authenticatedClientSessions;
|
return authenticatedClientSessions;
|
||||||
}
|
}
|
||||||
|
@ -152,6 +175,7 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
this.authenticatedClientSessions = authenticatedClientSessions;
|
this.authenticatedClientSessions = authenticatedClientSessions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(value = 12)
|
||||||
public UserSessionModel.State getState() {
|
public UserSessionModel.State getState() {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -160,6 +184,7 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(13)
|
||||||
public String getBrokerSessionId() {
|
public String getBrokerSessionId() {
|
||||||
return brokerSessionId;
|
return brokerSessionId;
|
||||||
}
|
}
|
||||||
|
@ -168,6 +193,7 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
this.brokerSessionId = brokerSessionId;
|
this.brokerSessionId = brokerSessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProtoField(14)
|
||||||
public String getBrokerUserId() {
|
public String getBrokerUserId() {
|
||||||
return brokerUserId;
|
return brokerUserId;
|
||||||
}
|
}
|
||||||
|
@ -178,15 +204,13 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) {
|
||||||
if (!(o instanceof UserSessionEntity)) return false;
|
|
||||||
|
|
||||||
UserSessionEntity that = (UserSessionEntity) o;
|
|
||||||
|
|
||||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return o instanceof UserSessionEntity that &&
|
||||||
|
Objects.equals(id, that.id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
|
@ -224,88 +248,4 @@ public class UserSessionEntity extends SessionEntity {
|
||||||
return entityWrapper;
|
return entityWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<UserSessionEntity> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
private static final EnumMap<UserSessionModel.State, Integer> STATE_TO_ID = new EnumMap<>(UserSessionModel.State.class);
|
|
||||||
private static final Map<Integer, UserSessionModel.State> ID_TO_STATE = new HashMap<>();
|
|
||||||
static {
|
|
||||||
STATE_TO_ID.put(State.LOGGED_IN, 1);
|
|
||||||
STATE_TO_ID.put(State.LOGGED_OUT, 2);
|
|
||||||
STATE_TO_ID.put(State.LOGGING_OUT, 3);
|
|
||||||
|
|
||||||
for (Entry<State, Integer> entry : STATE_TO_ID.entrySet()) {
|
|
||||||
ID_TO_STATE.put(entry.getValue(), entry.getKey());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, UserSessionEntity session) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(session.getAuthMethod(), output);
|
|
||||||
MarshallUtil.marshallString(session.getBrokerSessionId(), output);
|
|
||||||
MarshallUtil.marshallString(session.getBrokerUserId(), output);
|
|
||||||
MarshallUtil.marshallString(session.getId(), output);
|
|
||||||
MarshallUtil.marshallString(session.getIpAddress(), output);
|
|
||||||
MarshallUtil.marshallString(session.getLoginUsername(), output);
|
|
||||||
MarshallUtil.marshallString(session.getRealmId(), output);
|
|
||||||
MarshallUtil.marshallString(session.getUser(), output);
|
|
||||||
|
|
||||||
KeycloakMarshallUtil.marshall(session.getLastSessionRefresh(), output);
|
|
||||||
KeycloakMarshallUtil.marshall(session.getStarted(), output);
|
|
||||||
output.writeBoolean(session.isRememberMe());
|
|
||||||
|
|
||||||
int state = session.getState() == null ? 0 : STATE_TO_ID.get(session.getState());
|
|
||||||
output.writeInt(state);
|
|
||||||
|
|
||||||
Map<String, String> notes = session.getNotes();
|
|
||||||
KeycloakMarshallUtil.writeMap(notes, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, output);
|
|
||||||
|
|
||||||
output.writeObject(session.getAuthenticatedClientSessions());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserSessionEntity readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserSessionEntity readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
String authMethod = MarshallUtil.unmarshallString(input);
|
|
||||||
String brokerSessionId = MarshallUtil.unmarshallString(input);
|
|
||||||
String brokerUserId = MarshallUtil.unmarshallString(input);
|
|
||||||
UserSessionEntity sessionEntity = new UserSessionEntity(MarshallUtil.unmarshallString(input));
|
|
||||||
sessionEntity.setAuthMethod(authMethod);
|
|
||||||
sessionEntity.setBrokerSessionId(brokerSessionId);
|
|
||||||
sessionEntity.setBrokerUserId(brokerUserId);
|
|
||||||
sessionEntity.setIpAddress(MarshallUtil.unmarshallString(input));
|
|
||||||
sessionEntity.setLoginUsername(MarshallUtil.unmarshallString(input));
|
|
||||||
sessionEntity.setRealmId(MarshallUtil.unmarshallString(input));
|
|
||||||
sessionEntity.setUser(MarshallUtil.unmarshallString(input));
|
|
||||||
|
|
||||||
sessionEntity.setLastSessionRefresh(KeycloakMarshallUtil.unmarshallInteger(input));
|
|
||||||
sessionEntity.setStarted(KeycloakMarshallUtil.unmarshallInteger(input));
|
|
||||||
sessionEntity.setRememberMe(input.readBoolean());
|
|
||||||
|
|
||||||
sessionEntity.setState(ID_TO_STATE.get(input.readInt()));
|
|
||||||
|
|
||||||
Map<String, String> notes = KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT,
|
|
||||||
new KeycloakMarshallUtil.ConcurrentHashMapBuilder<>());
|
|
||||||
sessionEntity.setNotes(notes);
|
|
||||||
|
|
||||||
AuthenticatedClientSessionStore authSessions = (AuthenticatedClientSessionStore) input.readObject();
|
|
||||||
sessionEntity.setAuthenticatedClientSessions(authSessions);
|
|
||||||
|
|
||||||
return sessionEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,45 +17,13 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.events;
|
package org.keycloak.models.sessions.infinispan.events;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import java.io.ObjectInput;
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(RealmRemovedSessionEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.REALM_REMOVED_SESSION_EVENT)
|
||||||
public class RealmRemovedSessionEvent extends SessionClusterEvent {
|
public class RealmRemovedSessionEvent extends SessionClusterEvent {
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<RealmRemovedSessionEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, RealmRemovedSessionEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
obj.marshallTo(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RealmRemovedSessionEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RealmRemovedSessionEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
RealmRemovedSessionEvent res = new RealmRemovedSessionEvent();
|
|
||||||
res.unmarshallFrom(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,45 +17,13 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.events;
|
package org.keycloak.models.sessions.infinispan.events;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import java.io.ObjectInput;
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(RemoveAllUserLoginFailuresEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.REMOVE_ALL_USER_LOGIN_FAILURES_EVENT)
|
||||||
public class RemoveAllUserLoginFailuresEvent extends SessionClusterEvent {
|
public class RemoveAllUserLoginFailuresEvent extends SessionClusterEvent {
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<RemoveAllUserLoginFailuresEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, RemoveAllUserLoginFailuresEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
obj.marshallTo(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RemoveAllUserLoginFailuresEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RemoveAllUserLoginFailuresEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
RemoveAllUserLoginFailuresEvent res = new RemoveAllUserLoginFailuresEvent();
|
|
||||||
res.unmarshallFrom(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,45 +17,13 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.events;
|
package org.keycloak.models.sessions.infinispan.events;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.infinispan.protostream.annotations.ProtoTypeId;
|
||||||
import java.io.ObjectInput;
|
import org.keycloak.marshalling.Marshalling;
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import org.infinispan.commons.marshall.Externalizer;
|
|
||||||
import org.infinispan.commons.marshall.SerializeWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@SerializeWith(RemoveUserSessionsEvent.ExternalizerImpl.class)
|
@ProtoTypeId(Marshalling.REMOVE_ALL_USER_SESSIONS_EVENT)
|
||||||
public class RemoveUserSessionsEvent extends SessionClusterEvent {
|
public class RemoveUserSessionsEvent extends SessionClusterEvent {
|
||||||
|
|
||||||
public static class ExternalizerImpl implements Externalizer<RemoveUserSessionsEvent> {
|
|
||||||
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeObject(ObjectOutput output, RemoveUserSessionsEvent obj) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
obj.marshallTo(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RemoveUserSessionsEvent readObject(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
return readObjectVersion1(input);
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RemoveUserSessionsEvent readObjectVersion1(ObjectInput input) throws IOException, ClassNotFoundException {
|
|
||||||
RemoveUserSessionsEvent res = new RemoveUserSessionsEvent();
|
|
||||||
res.unmarshallFrom(input);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,13 @@
|
||||||
|
|
||||||
package org.keycloak.models.sessions.infinispan.events;
|
package org.keycloak.models.sessions.infinispan.events;
|
||||||
|
|
||||||
import org.keycloak.cluster.ClusterEvent;
|
|
||||||
import org.keycloak.connections.infinispan.TopologyInfo;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.connections.infinispan.InfinispanUtil;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInput;
|
|
||||||
import java.io.ObjectOutput;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.infinispan.commons.marshall.MarshallUtil;
|
import org.infinispan.protostream.annotations.ProtoField;
|
||||||
|
import org.keycloak.cluster.ClusterEvent;
|
||||||
|
import org.keycloak.connections.infinispan.InfinispanUtil;
|
||||||
|
import org.keycloak.connections.infinispan.TopologyInfo;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
@ -42,7 +39,7 @@ public abstract class SessionClusterEvent implements ClusterEvent {
|
||||||
|
|
||||||
public static <T extends SessionClusterEvent> T createEvent(Class<T> eventClass, String eventKey, KeycloakSession session, String realmId, boolean resendingEvent) {
|
public static <T extends SessionClusterEvent> T createEvent(Class<T> eventClass, String eventKey, KeycloakSession session, String realmId, boolean resendingEvent) {
|
||||||
try {
|
try {
|
||||||
T event = eventClass.newInstance();
|
T event = eventClass.getDeclaredConstructor().newInstance();
|
||||||
event.setData(session, eventKey, realmId, resendingEvent);
|
event.setData(session, eventKey, realmId, resendingEvent);
|
||||||
return event;
|
return event;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -61,26 +58,51 @@ public abstract class SessionClusterEvent implements ClusterEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ProtoField(1)
|
||||||
public String getRealmId() {
|
public String getRealmId() {
|
||||||
return realmId;
|
return realmId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setRealmId(String realmId) {
|
||||||
|
this.realmId = realmId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtoField(2)
|
||||||
public String getEventKey() {
|
public String getEventKey() {
|
||||||
return eventKey;
|
return eventKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setEventKey(String eventKey) {
|
||||||
|
this.eventKey = eventKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtoField(3)
|
||||||
public boolean isResendingEvent() {
|
public boolean isResendingEvent() {
|
||||||
return resendingEvent;
|
return resendingEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setResendingEvent(boolean resendingEvent) {
|
||||||
|
this.resendingEvent = resendingEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtoField(4)
|
||||||
public String getSiteId() {
|
public String getSiteId() {
|
||||||
return siteId;
|
return siteId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setSiteId(String siteId) {
|
||||||
|
this.siteId = siteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtoField(5)
|
||||||
public String getNodeId() {
|
public String getNodeId() {
|
||||||
return nodeId;
|
return nodeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setNodeId(String nodeId) {
|
||||||
|
this.nodeId = nodeId;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
@ -99,40 +121,4 @@ public abstract class SessionClusterEvent implements ClusterEvent {
|
||||||
String simpleClassName = getClass().getSimpleName();
|
String simpleClassName = getClass().getSimpleName();
|
||||||
return String.format("%s [ realmId=%s ]", simpleClassName, realmId);
|
return String.format("%s [ realmId=%s ]", simpleClassName, realmId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Infinispan marshalling support for child classes
|
|
||||||
private static final int VERSION_1 = 1;
|
|
||||||
|
|
||||||
protected void marshallTo(ObjectOutput output) throws IOException {
|
|
||||||
output.writeByte(VERSION_1);
|
|
||||||
|
|
||||||
MarshallUtil.marshallString(realmId, output);
|
|
||||||
MarshallUtil.marshallString(eventKey, output);
|
|
||||||
output.writeBoolean(resendingEvent);
|
|
||||||
MarshallUtil.marshallString(siteId, output);
|
|
||||||
MarshallUtil.marshallString(nodeId, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the properties of this object from the input stream.
|
|
||||||
* @param input
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
protected void unmarshallFrom(ObjectInput input) throws IOException {
|
|
||||||
switch (input.readByte()) {
|
|
||||||
case VERSION_1:
|
|
||||||
unmarshallFromVersion1(input);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IOException("Unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void unmarshallFromVersion1(ObjectInput input) throws IOException {
|
|
||||||
this.realmId = MarshallUtil.unmarshallString(input);
|
|
||||||
this.eventKey = MarshallUtil.unmarshallString(input);
|
|
||||||
this.resendingEvent = input.readBoolean();
|
|
||||||
this.siteId = MarshallUtil.unmarshallString(input);
|
|
||||||
this.nodeId = MarshallUtil.unmarshallString(input);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,6 @@ import org.infinispan.lifecycle.ComponentStatus;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
@ -35,11 +33,11 @@ public abstract class BaseCacheInitializer extends CacheInitializer {
|
||||||
private static final Logger log = Logger.getLogger(BaseCacheInitializer.class);
|
private static final Logger log = Logger.getLogger(BaseCacheInitializer.class);
|
||||||
|
|
||||||
protected final KeycloakSessionFactory sessionFactory;
|
protected final KeycloakSessionFactory sessionFactory;
|
||||||
protected final Cache<String, Serializable> workCache;
|
protected final Cache<String, InitializerState> workCache;
|
||||||
protected final SessionLoader<SessionLoader.LoaderContext, SessionLoader.WorkerContext, SessionLoader.WorkerResult> sessionLoader;
|
protected final SessionLoader<SessionLoader.LoaderContext, SessionLoader.WorkerContext, SessionLoader.WorkerResult> sessionLoader;
|
||||||
protected final String stateKey;
|
protected final String stateKey;
|
||||||
|
|
||||||
public BaseCacheInitializer(KeycloakSessionFactory sessionFactory, Cache<String, Serializable> workCache, SessionLoader<SessionLoader.LoaderContext, SessionLoader.WorkerContext, SessionLoader.WorkerResult> sessionLoader, String stateKeySuffix) {
|
public BaseCacheInitializer(KeycloakSessionFactory sessionFactory, Cache<String, InitializerState> workCache, SessionLoader<SessionLoader.LoaderContext, SessionLoader.WorkerContext, SessionLoader.WorkerResult> sessionLoader, String stateKeySuffix) {
|
||||||
this.sessionFactory = sessionFactory;
|
this.sessionFactory = sessionFactory;
|
||||||
this.workCache = workCache;
|
this.workCache = workCache;
|
||||||
this.sessionLoader = sessionLoader;
|
this.sessionLoader = sessionLoader;
|
||||||
|
@ -67,7 +65,7 @@ public abstract class BaseCacheInitializer extends CacheInitializer {
|
||||||
|
|
||||||
protected InitializerState getStateFromCache() {
|
protected InitializerState getStateFromCache() {
|
||||||
// We ignore cacheStore for now, so that in Cross-DC scenario (with RemoteStore enabled) is the remoteStore ignored.
|
// We ignore cacheStore for now, so that in Cross-DC scenario (with RemoteStore enabled) is the remoteStore ignored.
|
||||||
return (InitializerState) workCache.getAdvancedCache()
|
return workCache.getAdvancedCache()
|
||||||
.withFlags(Flag.SKIP_CACHE_STORE, Flag.SKIP_CACHE_LOAD)
|
.withFlags(Flag.SKIP_CACHE_STORE, Flag.SKIP_CACHE_LOAD)
|
||||||
.get(stateKey);
|
.get(stateKey);
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue