KEYCLOAK-18845 Remove key type in map storage (simplify generics)
This commit is contained in:
parent
07402d9aac
commit
8889122dc1
45 changed files with 155 additions and 157 deletions
|
@ -8,7 +8,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-model-map</artifactId>
|
||||
<name>Keycloak Model Naive Map</name>
|
||||
<name>Keycloak Model Map</name>
|
||||
<description/>
|
||||
|
||||
<dependencies>
|
||||
|
|
|
@ -44,16 +44,16 @@ import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
|||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public class MapRootAuthenticationSessionProvider<K> implements AuthenticationSessionProvider {
|
||||
public class MapRootAuthenticationSessionProvider implements AuthenticationSessionProvider {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapRootAuthenticationSessionProvider.class);
|
||||
private final KeycloakSession session;
|
||||
protected final MapKeycloakTransaction<K, MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel> tx;
|
||||
private final MapStorage<K, MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel> sessionStore;
|
||||
protected final MapKeycloakTransaction<MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel> tx;
|
||||
private final MapStorage<MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel> sessionStore;
|
||||
|
||||
private static final String AUTHENTICATION_SESSION_EVENTS = "AUTHENTICATION_SESSION_EVENTS";
|
||||
|
||||
public MapRootAuthenticationSessionProvider(KeycloakSession session, MapStorage<K, MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel> sessionStore) {
|
||||
public MapRootAuthenticationSessionProvider(KeycloakSession session, MapStorage<MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel> sessionStore) {
|
||||
this.session = session;
|
||||
this.sessionStore = sessionStore;
|
||||
this.tx = sessionStore.createTransaction(session);
|
||||
|
@ -87,7 +87,7 @@ public class MapRootAuthenticationSessionProvider<K> implements AuthenticationSe
|
|||
LOG.tracef("createRootAuthenticationSession(%s)%s", realm.getName(), getShortStackTrace());
|
||||
|
||||
// create map authentication session entity
|
||||
MapRootAuthenticationSessionEntity entity = new MapRootAuthenticationSessionEntity(null, realm.getId());
|
||||
MapRootAuthenticationSessionEntity entity = new MapRootAuthenticationSessionEntity(id, realm.getId());
|
||||
entity.setTimestamp(Time.currentTime());
|
||||
|
||||
if (id != null && tx.read(id) != null) {
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.keycloak.sessions.RootAuthenticationSessionModel;
|
|||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public class MapRootAuthenticationSessionProviderFactory<K> extends AbstractMapProviderFactory<AuthenticationSessionProvider, K, MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel>
|
||||
public class MapRootAuthenticationSessionProviderFactory extends AbstractMapProviderFactory<AuthenticationSessionProvider, MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel>
|
||||
implements AuthenticationSessionProviderFactory {
|
||||
|
||||
public MapRootAuthenticationSessionProviderFactory() {
|
||||
|
@ -35,7 +35,7 @@ public class MapRootAuthenticationSessionProviderFactory<K> extends AbstractMapP
|
|||
|
||||
@Override
|
||||
public AuthenticationSessionProvider create(KeycloakSession session) {
|
||||
return new MapRootAuthenticationSessionProvider<>(session, getStorage(session));
|
||||
return new MapRootAuthenticationSessionProvider(session, getStorage(session));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -45,7 +45,7 @@ import static org.keycloak.models.utils.KeycloakModelUtils.getComponentFactory;
|
|||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class MapAuthorizationStoreFactory<K> implements AmphibianProviderFactory<StoreFactory>, AuthorizationStoreFactory, EnvironmentDependentProviderFactory {
|
||||
public class MapAuthorizationStoreFactory implements AmphibianProviderFactory<StoreFactory>, AuthorizationStoreFactory, EnvironmentDependentProviderFactory {
|
||||
|
||||
public static final String PROVIDER_ID = AbstractMapProviderFactory.PROVIDER_ID;
|
||||
|
||||
|
|
|
@ -48,14 +48,14 @@ import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
|||
import static org.keycloak.utils.StreamsUtil.distinctByKey;
|
||||
import static org.keycloak.utils.StreamsUtil.paginatedStream;
|
||||
|
||||
public class MapPermissionTicketStore<K extends Comparable<K>> implements PermissionTicketStore {
|
||||
public class MapPermissionTicketStore implements PermissionTicketStore {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapPermissionTicketStore.class);
|
||||
private final AuthorizationProvider authorizationProvider;
|
||||
final MapKeycloakTransaction<K, MapPermissionTicketEntity, PermissionTicket> tx;
|
||||
private final MapStorage<K, MapPermissionTicketEntity, PermissionTicket> permissionTicketStore;
|
||||
final MapKeycloakTransaction<MapPermissionTicketEntity, PermissionTicket> tx;
|
||||
private final MapStorage<MapPermissionTicketEntity, PermissionTicket> permissionTicketStore;
|
||||
|
||||
public MapPermissionTicketStore(KeycloakSession session, MapStorage<K, MapPermissionTicketEntity, PermissionTicket> permissionTicketStore, AuthorizationProvider provider) {
|
||||
public MapPermissionTicketStore(KeycloakSession session, MapStorage<MapPermissionTicketEntity, PermissionTicket> permissionTicketStore, AuthorizationProvider provider) {
|
||||
this.authorizationProvider = provider;
|
||||
this.permissionTicketStore = permissionTicketStore;
|
||||
this.tx = permissionTicketStore.createTransaction(session);
|
||||
|
|
|
@ -43,14 +43,14 @@ import java.util.stream.Collectors;
|
|||
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
||||
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
||||
|
||||
public class MapPolicyStore<K> implements PolicyStore {
|
||||
public class MapPolicyStore implements PolicyStore {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapPolicyStore.class);
|
||||
private final AuthorizationProvider authorizationProvider;
|
||||
final MapKeycloakTransaction<K, MapPolicyEntity, Policy> tx;
|
||||
private final MapStorage<K, MapPolicyEntity, Policy> policyStore;
|
||||
final MapKeycloakTransaction<MapPolicyEntity, Policy> tx;
|
||||
private final MapStorage<MapPolicyEntity, Policy> policyStore;
|
||||
|
||||
public MapPolicyStore(KeycloakSession session, MapStorage<K, MapPolicyEntity, Policy> policyStore, AuthorizationProvider provider) {
|
||||
public MapPolicyStore(KeycloakSession session, MapStorage<MapPolicyEntity, Policy> policyStore, AuthorizationProvider provider) {
|
||||
this.authorizationProvider = provider;
|
||||
this.policyStore = policyStore;
|
||||
this.tx = policyStore.createTransaction(session);
|
||||
|
@ -134,7 +134,7 @@ public class MapPolicyStore<K> implements PolicyStore {
|
|||
|
||||
@Override
|
||||
public List<Policy> findByResourceServer(Map<Policy.FilterOption, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
||||
LOG.tracef("findByResource(%s, %s, %d, %d)%s", attributes, resourceServerId, firstResult, maxResult, getShortStackTrace());
|
||||
LOG.tracef("findByResourceServer(%s, %s, %d, %d)%s", attributes, resourceServerId, firstResult, maxResult, getShortStackTrace());
|
||||
|
||||
ModelCriteriaBuilder<Policy> mcb = forResourceServer(resourceServerId).and(
|
||||
attributes.entrySet().stream()
|
||||
|
|
|
@ -40,14 +40,14 @@ import org.keycloak.storage.StorageId;
|
|||
|
||||
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
||||
|
||||
public class MapResourceServerStore<K> implements ResourceServerStore {
|
||||
public class MapResourceServerStore implements ResourceServerStore {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapResourceServerStore.class);
|
||||
private final AuthorizationProvider authorizationProvider;
|
||||
final MapKeycloakTransaction<K, MapResourceServerEntity, ResourceServer> tx;
|
||||
private final MapStorage<K, MapResourceServerEntity, ResourceServer> resourceServerStore;
|
||||
final MapKeycloakTransaction<MapResourceServerEntity, ResourceServer> tx;
|
||||
private final MapStorage<MapResourceServerEntity, ResourceServer> resourceServerStore;
|
||||
|
||||
public MapResourceServerStore(KeycloakSession session, MapStorage<K, MapResourceServerEntity, ResourceServer> resourceServerStore, AuthorizationProvider provider) {
|
||||
public MapResourceServerStore(KeycloakSession session, MapStorage<MapResourceServerEntity, ResourceServer> resourceServerStore, AuthorizationProvider provider) {
|
||||
this.resourceServerStore = resourceServerStore;
|
||||
this.tx = resourceServerStore.createTransaction(session);
|
||||
this.authorizationProvider = provider;
|
||||
|
|
|
@ -42,14 +42,14 @@ import java.util.stream.Collectors;
|
|||
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
||||
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
||||
|
||||
public class MapResourceStore<K extends Comparable<K>> implements ResourceStore {
|
||||
public class MapResourceStore implements ResourceStore {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapResourceStore.class);
|
||||
private final AuthorizationProvider authorizationProvider;
|
||||
final MapKeycloakTransaction<K, MapResourceEntity, Resource> tx;
|
||||
private final MapStorage<K, MapResourceEntity, Resource> resourceStore;
|
||||
final MapKeycloakTransaction<MapResourceEntity, Resource> tx;
|
||||
private final MapStorage<MapResourceEntity, Resource> resourceStore;
|
||||
|
||||
public MapResourceStore(KeycloakSession session, MapStorage<K, MapResourceEntity, Resource> resourceStore, AuthorizationProvider provider) {
|
||||
public MapResourceStore(KeycloakSession session, MapStorage<MapResourceEntity, Resource> resourceStore, AuthorizationProvider provider) {
|
||||
this.resourceStore = resourceStore;
|
||||
this.tx = resourceStore.createTransaction(session);
|
||||
session.getTransactionManager().enlist(tx);
|
||||
|
|
|
@ -40,14 +40,14 @@ import java.util.stream.Collectors;
|
|||
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
||||
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
||||
|
||||
public class MapScopeStore<K> implements ScopeStore {
|
||||
public class MapScopeStore implements ScopeStore {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapScopeStore.class);
|
||||
private final AuthorizationProvider authorizationProvider;
|
||||
final MapKeycloakTransaction<K, MapScopeEntity, Scope> tx;
|
||||
private final MapStorage<K, MapScopeEntity, Scope> scopeStore;
|
||||
final MapKeycloakTransaction<MapScopeEntity, Scope> tx;
|
||||
private final MapStorage<MapScopeEntity, Scope> scopeStore;
|
||||
|
||||
public MapScopeStore(KeycloakSession session, MapStorage<K, MapScopeEntity, Scope> scopeStore, AuthorizationProvider provider) {
|
||||
public MapScopeStore(KeycloakSession session, MapStorage<MapScopeEntity, Scope> scopeStore, AuthorizationProvider provider) {
|
||||
this.authorizationProvider = provider;
|
||||
this.scopeStore = scopeStore;
|
||||
this.tx = scopeStore.createTransaction(session);
|
||||
|
|
|
@ -30,7 +30,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MapPolicyAdapter<K> extends AbstractPolicyModel<MapPolicyEntity> {
|
||||
public class MapPolicyAdapter extends AbstractPolicyModel<MapPolicyEntity> {
|
||||
|
||||
public MapPolicyAdapter(MapPolicyEntity entity, StoreFactory storeFactory) {
|
||||
super(entity, storeFactory);
|
||||
|
|
|
@ -20,7 +20,7 @@ package org.keycloak.models.map.client;
|
|||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class MapClientEntityDelegate<K> extends MapClientEntityLazyDelegate<K> {
|
||||
public class MapClientEntityDelegate extends MapClientEntityLazyDelegate {
|
||||
|
||||
private final MapClientEntity delegate;
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package org.keycloak.models.map.client;
|
||||
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.map.common.AbstractEntity;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -36,7 +35,7 @@ import java.util.stream.Stream;
|
|||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class MapClientEntityImpl<K> implements MapClientEntity {
|
||||
public class MapClientEntityImpl implements MapClientEntity {
|
||||
|
||||
private String id;
|
||||
private String realmId;
|
||||
|
|
|
@ -29,7 +29,7 @@ import java.util.stream.Stream;
|
|||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class MapClientEntityLazyDelegate<K> implements MapClientEntity {
|
||||
public class MapClientEntityLazyDelegate implements MapClientEntity {
|
||||
|
||||
private final Supplier<MapClientEntity> delegateSupplier;
|
||||
|
||||
|
|
|
@ -50,15 +50,15 @@ import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
|||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class MapClientProvider<K> implements ClientProvider {
|
||||
public class MapClientProvider implements ClientProvider {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapClientProvider.class);
|
||||
private final KeycloakSession session;
|
||||
final MapKeycloakTransaction<K, MapClientEntity, ClientModel> tx;
|
||||
private final MapStorage<K, MapClientEntity, ClientModel> clientStore;
|
||||
final MapKeycloakTransaction<MapClientEntity, ClientModel> tx;
|
||||
private final MapStorage<MapClientEntity, ClientModel> clientStore;
|
||||
private final ConcurrentMap<String, ConcurrentMap<String, Integer>> clientRegisteredNodesStore;
|
||||
|
||||
public MapClientProvider(KeycloakSession session, MapStorage<K, MapClientEntity, ClientModel> clientStore, ConcurrentMap<String, ConcurrentMap<String, Integer>> clientRegisteredNodesStore) {
|
||||
public MapClientProvider(KeycloakSession session, MapStorage<MapClientEntity, ClientModel> clientStore, ConcurrentMap<String, ConcurrentMap<String, Integer>> clientRegisteredNodesStore) {
|
||||
this.session = session;
|
||||
this.clientStore = clientStore;
|
||||
this.clientRegisteredNodesStore = clientRegisteredNodesStore;
|
||||
|
@ -140,10 +140,8 @@ public class MapClientProvider<K> implements ClientProvider {
|
|||
public ClientModel addClient(RealmModel realm, String id, String clientId) {
|
||||
LOG.tracef("addClient(%s, %s, %s)%s", realm, id, clientId, getShortStackTrace());
|
||||
|
||||
MapClientEntity entity = new MapClientEntityImpl<>(null, realm.getId());
|
||||
if (clientId != null) {
|
||||
entity.setClientId(clientId);
|
||||
}
|
||||
MapClientEntity entity = new MapClientEntityImpl(id, realm.getId());
|
||||
entity.setClientId(clientId);
|
||||
entity.setEnabled(true);
|
||||
entity.setStandardFlowEnabled(true);
|
||||
if (id != null && tx.read(id) != null) {
|
||||
|
@ -352,7 +350,7 @@ public class MapClientProvider<K> implements ClientProvider {
|
|||
.compare(SearchableFields.SCOPE_MAPPING_ROLE, Operator.EQ, role.getId());
|
||||
try (Stream<MapClientEntity> toRemove = tx.read(withCriteria(mcb))) {
|
||||
toRemove
|
||||
.map(clientEntity -> session.clients().getClientById(realm, clientEntity.getId().toString()))
|
||||
.map(clientEntity -> session.clients().getClientById(realm, clientEntity.getId()))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(clientModel -> clientModel.deleteScopeMapping(role));
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ import java.util.concurrent.ConcurrentMap;
|
|||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class MapClientProviderFactory<K> extends AbstractMapProviderFactory<ClientProvider, K, MapClientEntity, ClientModel> implements ClientProviderFactory, ProviderEventListener {
|
||||
public class MapClientProviderFactory extends AbstractMapProviderFactory<ClientProvider, MapClientEntity, ClientModel> implements ClientProviderFactory, ProviderEventListener {
|
||||
|
||||
private final ConcurrentHashMap<String, ConcurrentMap<String, Integer>> REGISTERED_NODES_STORE = new ConcurrentHashMap<>();
|
||||
|
||||
|
@ -53,7 +53,7 @@ public class MapClientProviderFactory<K> extends AbstractMapProviderFactory<Clie
|
|||
|
||||
@Override
|
||||
public MapClientProvider create(KeycloakSession session) {
|
||||
return new MapClientProvider<>(session, getStorage(session), REGISTERED_NODES_STORE);
|
||||
return new MapClientProvider(session, getStorage(session), REGISTERED_NODES_STORE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -39,14 +39,14 @@ import org.keycloak.models.utils.KeycloakModelUtils;
|
|||
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
||||
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
||||
|
||||
public class MapClientScopeProvider<K> implements ClientScopeProvider {
|
||||
public class MapClientScopeProvider implements ClientScopeProvider {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapClientScopeProvider.class);
|
||||
private final KeycloakSession session;
|
||||
private final MapKeycloakTransaction<K, MapClientScopeEntity, ClientScopeModel> tx;
|
||||
private final MapStorage<K, MapClientScopeEntity, ClientScopeModel> clientScopeStore;
|
||||
private final MapKeycloakTransaction<MapClientScopeEntity, ClientScopeModel> tx;
|
||||
private final MapStorage<MapClientScopeEntity, ClientScopeModel> clientScopeStore;
|
||||
|
||||
public MapClientScopeProvider(KeycloakSession session, MapStorage<K, MapClientScopeEntity, ClientScopeModel> clientScopeStore) {
|
||||
public MapClientScopeProvider(KeycloakSession session, MapStorage<MapClientScopeEntity, ClientScopeModel> clientScopeStore) {
|
||||
this.session = session;
|
||||
this.clientScopeStore = clientScopeStore;
|
||||
this.tx = clientScopeStore.createTransaction(session);
|
||||
|
@ -91,7 +91,7 @@ public class MapClientScopeProvider<K> implements ClientScopeProvider {
|
|||
|
||||
MapClientScopeEntity entity = new MapClientScopeEntity(id, realm.getId());
|
||||
entity.setName(KeycloakModelUtils.convertClientScopeName(name));
|
||||
if (tx.read(id) != null) {
|
||||
if (id != null && tx.read(id) != null) {
|
||||
throw new ModelDuplicateException("Client scope exists: " + id);
|
||||
}
|
||||
entity = tx.create(entity);
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.keycloak.models.ClientScopeProviderFactory;
|
|||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
||||
|
||||
public class MapClientScopeProviderFactory<K> extends AbstractMapProviderFactory<ClientScopeProvider, K, MapClientScopeEntity, ClientScopeModel> implements ClientScopeProviderFactory {
|
||||
public class MapClientScopeProviderFactory extends AbstractMapProviderFactory<ClientScopeProvider, MapClientScopeEntity, ClientScopeModel> implements ClientScopeProviderFactory {
|
||||
|
||||
public MapClientScopeProviderFactory() {
|
||||
super(ClientScopeModel.class);
|
||||
|
@ -30,7 +30,7 @@ public class MapClientScopeProviderFactory<K> extends AbstractMapProviderFactory
|
|||
|
||||
@Override
|
||||
public ClientScopeProvider create(KeycloakSession session) {
|
||||
return new MapClientScopeProvider<>(session, getStorage(session));
|
||||
return new MapClientScopeProvider(session, getStorage(session));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -34,7 +34,7 @@ import static org.keycloak.models.utils.KeycloakModelUtils.getComponentFactory;
|
|||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public abstract class AbstractMapProviderFactory<T extends Provider, K, V extends AbstractEntity, M> implements AmphibianProviderFactory<T>, EnvironmentDependentProviderFactory {
|
||||
public abstract class AbstractMapProviderFactory<T extends Provider, V extends AbstractEntity, M> implements AmphibianProviderFactory<T>, EnvironmentDependentProviderFactory {
|
||||
|
||||
public static final String PROVIDER_ID = "map";
|
||||
|
||||
|
@ -56,7 +56,7 @@ public abstract class AbstractMapProviderFactory<T extends Provider, K, V extend
|
|||
return PROVIDER_ID;
|
||||
}
|
||||
|
||||
protected MapStorage<K, V, M> getStorage(KeycloakSession session) {
|
||||
protected MapStorage<V, M> getStorage(KeycloakSession session) {
|
||||
ProviderFactory<MapStorageProvider> storageProviderFactory = getComponentFactory(session.getKeycloakSessionFactory(),
|
||||
MapStorageProvider.class, storageConfigScope, MapStorageSpi.NAME);
|
||||
final MapStorageProvider factory = storageProviderFactory.create(session);
|
||||
|
|
|
@ -112,6 +112,11 @@ public interface StringKeyConvertor<K> {
|
|||
static final SecureRandom numberGenerator = new SecureRandom();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String keyToString(Long key) {
|
||||
return Long.toUnsignedString(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long fromString(String key) {
|
||||
return key == null ? null : Long.parseUnsignedLong(key);
|
||||
|
|
|
@ -33,7 +33,7 @@ import java.util.Set;
|
|||
*/
|
||||
public class MapGroupEntity implements AbstractEntity, UpdatableEntity {
|
||||
|
||||
private final String id;
|
||||
private String id;
|
||||
private final String realmId;
|
||||
|
||||
private String name;
|
||||
|
|
|
@ -42,14 +42,14 @@ import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
|||
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
||||
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
||||
|
||||
public class MapGroupProvider<K> implements GroupProvider {
|
||||
public class MapGroupProvider implements GroupProvider {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapGroupProvider.class);
|
||||
private final KeycloakSession session;
|
||||
final MapKeycloakTransaction<K, MapGroupEntity, GroupModel> tx;
|
||||
private final MapStorage<K, MapGroupEntity, GroupModel> groupStore;
|
||||
final MapKeycloakTransaction<MapGroupEntity, GroupModel> tx;
|
||||
private final MapStorage<MapGroupEntity, GroupModel> groupStore;
|
||||
|
||||
public MapGroupProvider(KeycloakSession session, MapStorage<K, MapGroupEntity, GroupModel> groupStore) {
|
||||
public MapGroupProvider(KeycloakSession session, MapStorage<MapGroupEntity, GroupModel> groupStore) {
|
||||
this.session = session;
|
||||
this.groupStore = groupStore;
|
||||
this.tx = groupStore.createTransaction(session);
|
||||
|
|
|
@ -35,7 +35,7 @@ import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
|||
*
|
||||
* @author mhajas
|
||||
*/
|
||||
public class MapGroupProviderFactory<K> extends AbstractMapProviderFactory<GroupProvider, K, MapGroupEntity, GroupModel> implements GroupProviderFactory, ProviderEventListener {
|
||||
public class MapGroupProviderFactory extends AbstractMapProviderFactory<GroupProvider, MapGroupEntity, GroupModel> implements GroupProviderFactory, ProviderEventListener {
|
||||
|
||||
private Runnable onClose;
|
||||
|
||||
|
@ -51,7 +51,7 @@ public class MapGroupProviderFactory<K> extends AbstractMapProviderFactory<Group
|
|||
|
||||
@Override
|
||||
public MapGroupProvider create(KeycloakSession session) {
|
||||
return new MapGroupProvider<>(session, getStorage(session));
|
||||
return new MapGroupProvider(session, getStorage(session));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -33,14 +33,14 @@ import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
|||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public class MapUserLoginFailureProvider<K> implements UserLoginFailureProvider {
|
||||
public class MapUserLoginFailureProvider implements UserLoginFailureProvider {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapUserLoginFailureProvider.class);
|
||||
private final KeycloakSession session;
|
||||
protected final MapKeycloakTransaction<K, MapUserLoginFailureEntity, UserLoginFailureModel> userLoginFailureTx;
|
||||
private final MapStorage<K, MapUserLoginFailureEntity, UserLoginFailureModel> userLoginFailureStore;
|
||||
protected final MapKeycloakTransaction<MapUserLoginFailureEntity, UserLoginFailureModel> userLoginFailureTx;
|
||||
private final MapStorage<MapUserLoginFailureEntity, UserLoginFailureModel> userLoginFailureStore;
|
||||
|
||||
public MapUserLoginFailureProvider(KeycloakSession session, MapStorage<K, MapUserLoginFailureEntity, UserLoginFailureModel> userLoginFailureStore) {
|
||||
public MapUserLoginFailureProvider(KeycloakSession session, MapStorage<MapUserLoginFailureEntity, UserLoginFailureModel> userLoginFailureStore) {
|
||||
this.session = session;
|
||||
this.userLoginFailureStore = userLoginFailureStore;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ import org.keycloak.provider.ProviderEventListener;
|
|||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public class MapUserLoginFailureProviderFactory<K> extends AbstractMapProviderFactory<UserLoginFailureProvider, K, MapUserLoginFailureEntity, UserLoginFailureModel>
|
||||
public class MapUserLoginFailureProviderFactory extends AbstractMapProviderFactory<UserLoginFailureProvider, MapUserLoginFailureEntity, UserLoginFailureModel>
|
||||
implements UserLoginFailureProviderFactory, ProviderEventListener {
|
||||
|
||||
private Runnable onClose;
|
||||
|
@ -53,8 +53,8 @@ public class MapUserLoginFailureProviderFactory<K> extends AbstractMapProviderFa
|
|||
}
|
||||
|
||||
@Override
|
||||
public MapUserLoginFailureProvider<K> create(KeycloakSession session) {
|
||||
return new MapUserLoginFailureProvider<>(session, getStorage(session));
|
||||
public MapUserLoginFailureProvider create(KeycloakSession session) {
|
||||
return new MapUserLoginFailureProvider(session, getStorage(session));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -45,7 +45,7 @@ import org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntity;
|
|||
|
||||
public class MapRealmEntity implements AbstractEntity, UpdatableEntity {
|
||||
|
||||
private final String id;
|
||||
private String id;
|
||||
private String name;
|
||||
|
||||
private Boolean enabled = false;
|
||||
|
|
|
@ -40,14 +40,14 @@ import org.keycloak.models.utils.KeycloakModelUtils;
|
|||
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
||||
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
||||
|
||||
public class MapRealmProvider<K> implements RealmProvider {
|
||||
public class MapRealmProvider implements RealmProvider {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapRealmProvider.class);
|
||||
private final KeycloakSession session;
|
||||
final MapKeycloakTransaction<K, MapRealmEntity, RealmModel> tx;
|
||||
private final MapStorage<K, MapRealmEntity, RealmModel> realmStore;
|
||||
final MapKeycloakTransaction<MapRealmEntity, RealmModel> tx;
|
||||
private final MapStorage<MapRealmEntity, RealmModel> realmStore;
|
||||
|
||||
public MapRealmProvider(KeycloakSession session, MapStorage<K, MapRealmEntity, RealmModel> realmStore) {
|
||||
public MapRealmProvider(KeycloakSession session, MapStorage<MapRealmEntity, RealmModel> realmStore) {
|
||||
this.session = session;
|
||||
this.realmStore = realmStore;
|
||||
this.tx = realmStore.createTransaction(session);
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.models.RealmProvider;
|
||||
import org.keycloak.models.RealmProviderFactory;
|
||||
|
||||
public class MapRealmProviderFactory<K> extends AbstractMapProviderFactory<RealmProvider, K, MapRealmEntity, RealmModel> implements RealmProviderFactory {
|
||||
public class MapRealmProviderFactory extends AbstractMapProviderFactory<RealmProvider, MapRealmEntity, RealmModel> implements RealmProviderFactory {
|
||||
|
||||
public MapRealmProviderFactory() {
|
||||
super(RealmModel.class);
|
||||
|
@ -30,7 +30,7 @@ public class MapRealmProviderFactory<K> extends AbstractMapProviderFactory<Realm
|
|||
|
||||
@Override
|
||||
public RealmProvider create(KeycloakSession session) {
|
||||
return new MapRealmProvider<>(session, getStorage(session));
|
||||
return new MapRealmProvider(session, getStorage(session));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -70,7 +70,7 @@ public class MapRoleAdapter extends AbstractRoleModel<MapRoleEntity> implements
|
|||
|
||||
@Override
|
||||
public Stream<RoleModel> getCompositesStream() {
|
||||
LOG.tracef("%% %s(%s).getCompositesStream():%d - %s", entity.getName(), entity.getId().toString(), entity.getCompositeRoles().size(), getShortStackTrace());
|
||||
LOG.tracef("%% %s(%s).getCompositesStream():%d - %s", entity.getName(), entity.getId(), entity.getCompositeRoles().size(), getShortStackTrace());
|
||||
return entity.getCompositeRoles().stream()
|
||||
.map(uuid -> session.roles().getRoleById(realm, uuid))
|
||||
.filter(Objects::nonNull);
|
||||
|
@ -78,13 +78,13 @@ public class MapRoleAdapter extends AbstractRoleModel<MapRoleEntity> implements
|
|||
|
||||
@Override
|
||||
public void addCompositeRole(RoleModel role) {
|
||||
LOG.tracef("%s(%s).addCompositeRole(%s(%s))%s", entity.getName(), entity.getId().toString(), role.getName(), role.getId(), getShortStackTrace());
|
||||
LOG.tracef("%s(%s).addCompositeRole(%s(%s))%s", entity.getName(), entity.getId(), role.getName(), role.getId(), getShortStackTrace());
|
||||
entity.addCompositeRole(role.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCompositeRole(RoleModel role) {
|
||||
LOG.tracef("%s(%s).removeCompositeRole(%s(%s))%s", entity.getName(), entity.getId().toString(), role.getName(), role.getId(), getShortStackTrace());
|
||||
LOG.tracef("%s(%s).removeCompositeRole(%s(%s))%s", entity.getName(), entity.getId(), role.getName(), role.getId(), getShortStackTrace());
|
||||
entity.removeCompositeRole(role.getId());
|
||||
}
|
||||
|
||||
|
|
|
@ -40,14 +40,14 @@ import org.keycloak.models.RoleProvider;
|
|||
import org.keycloak.models.map.storage.ModelCriteriaBuilder;
|
||||
import org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator;
|
||||
|
||||
public class MapRoleProvider<K> implements RoleProvider {
|
||||
public class MapRoleProvider implements RoleProvider {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapRoleProvider.class);
|
||||
private final KeycloakSession session;
|
||||
final MapKeycloakTransaction<K, MapRoleEntity, RoleModel> tx;
|
||||
private final MapStorage<K, MapRoleEntity, RoleModel> roleStore;
|
||||
final MapKeycloakTransaction<MapRoleEntity, RoleModel> tx;
|
||||
private final MapStorage<MapRoleEntity, RoleModel> roleStore;
|
||||
|
||||
public MapRoleProvider(KeycloakSession session, MapStorage<K, MapRoleEntity, RoleModel> roleStore) {
|
||||
public MapRoleProvider(KeycloakSession session, MapStorage<MapRoleEntity, RoleModel> roleStore) {
|
||||
this.session = session;
|
||||
this.roleStore = roleStore;
|
||||
this.tx = roleStore.createTransaction(session);
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.keycloak.models.RoleModel;
|
|||
import org.keycloak.models.RoleProvider;
|
||||
import org.keycloak.models.RoleProviderFactory;
|
||||
|
||||
public class MapRoleProviderFactory<K> extends AbstractMapProviderFactory<RoleProvider, K, MapRoleEntity, RoleModel> implements RoleProviderFactory {
|
||||
public class MapRoleProviderFactory extends AbstractMapProviderFactory<RoleProvider, MapRoleEntity, RoleModel> implements RoleProviderFactory {
|
||||
|
||||
public MapRoleProviderFactory() {
|
||||
super(RoleModel.class);
|
||||
|
@ -30,7 +30,7 @@ public class MapRoleProviderFactory<K> extends AbstractMapProviderFactory<RolePr
|
|||
|
||||
@Override
|
||||
public RoleProvider create(KeycloakSession session) {
|
||||
return new MapRoleProvider<>(session, getStorage(session));
|
||||
return new MapRoleProvider(session, getStorage(session));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,11 +19,9 @@ package org.keycloak.models.map.storage;
|
|||
import org.keycloak.models.KeycloakTransaction;
|
||||
import org.keycloak.models.map.common.AbstractEntity;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface MapKeycloakTransaction<K, V extends AbstractEntity, M> extends KeycloakTransaction {
|
||||
public interface MapKeycloakTransaction<V extends AbstractEntity, M> extends KeycloakTransaction {
|
||||
|
||||
/**
|
||||
* Instructs this transaction to add a new value into the underlying store on commit.
|
||||
|
|
|
@ -28,7 +28,6 @@ import java.util.stream.Stream;
|
|||
* ({@link #getCount(org.keycloak.models.map.storage.QueryParameters)}).
|
||||
*
|
||||
* @author hmlnarik
|
||||
* @param <K> Type of the primary key. Various storages can
|
||||
* @param <V> Type of the stored values that contains all the data stripped of session state. In other words, in the entities
|
||||
* there are only IDs and mostly primitive types / {@code String}, never references to {@code *Model} instances.
|
||||
* See the {@code Abstract*Entity} classes in this module.
|
||||
|
@ -36,11 +35,12 @@ import java.util.stream.Stream;
|
|||
* filtering via model fields in {@link ModelCriteriaBuilder} which is necessary to abstract from physical
|
||||
* layout and thus to support no-downtime upgrade.
|
||||
*/
|
||||
public interface MapStorage<K, V extends AbstractEntity, M> {
|
||||
public interface MapStorage<V extends AbstractEntity, M> {
|
||||
|
||||
/**
|
||||
* Creates an object in the store. ID of the {@code value} may be prescribed in id of the {@code value}.
|
||||
* If the id is {@code null}, then the {@code value}'s ID will be generated and returned in the id of the return value.
|
||||
* If the id is {@code null} or its format is not matching the store internal format for ID, then
|
||||
* the {@code value}'s ID will be generated and returned in the id of the return value.
|
||||
* @param value Entity to create in the store
|
||||
* @throws NullPointerException if {@code value} is {@code null}
|
||||
* @see AbstractEntity#getId()
|
||||
|
@ -129,6 +129,6 @@ public interface MapStorage<K, V extends AbstractEntity, M> {
|
|||
*
|
||||
* @return See description. Never returns {@code null}
|
||||
*/
|
||||
MapKeycloakTransaction<K, V, M> createTransaction(KeycloakSession session);
|
||||
MapKeycloakTransaction<V, M> createTransaction(KeycloakSession session);
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ public interface MapStorageProvider extends Provider {
|
|||
|
||||
/**
|
||||
* Returns a key-value storage implementation for the given types.
|
||||
* @param <K> type of the primary key
|
||||
* @param <V> type of the value
|
||||
* @param <M> type of the corresponding model (e.g. {@code UserModel})
|
||||
* @param modelType Model type
|
||||
|
@ -36,5 +35,5 @@ public interface MapStorageProvider extends Provider {
|
|||
* @return
|
||||
* @throws IllegalArgumentException If some of the types is not supported by the underlying implementation.
|
||||
*/
|
||||
<K, V extends AbstractEntity, M> MapStorage<K, V, M> getStorage(Class<M> modelType, Flag... flags);
|
||||
<V extends AbstractEntity, M> MapStorage<V, M> getStorage(Class<M> modelType, Flag... flags);
|
||||
}
|
||||
|
|
|
@ -36,21 +36,21 @@ import org.keycloak.models.map.storage.ModelCriteriaBuilder;
|
|||
import org.keycloak.models.map.storage.QueryParameters;
|
||||
import org.keycloak.utils.StreamsUtil;
|
||||
|
||||
public class ConcurrentHashMapKeycloakTransaction<K, V extends AbstractEntity & UpdatableEntity, M> implements MapKeycloakTransaction<K, V, M> {
|
||||
public class ConcurrentHashMapKeycloakTransaction<K, V extends AbstractEntity & UpdatableEntity, M> implements MapKeycloakTransaction<V, M> {
|
||||
|
||||
private final static Logger log = Logger.getLogger(ConcurrentHashMapKeycloakTransaction.class);
|
||||
|
||||
private boolean active;
|
||||
private boolean rollback;
|
||||
private final Map<String, MapTaskWithValue> tasks = new LinkedHashMap<>();
|
||||
private final MapStorage<K, V, M> map;
|
||||
private final MapStorage<V, M> map;
|
||||
private final StringKeyConvertor<K> keyConvertor;
|
||||
|
||||
enum MapOperation {
|
||||
CREATE, UPDATE, DELETE,
|
||||
}
|
||||
|
||||
public ConcurrentHashMapKeycloakTransaction(MapStorage<K, V, M> map, StringKeyConvertor<K> keyConvertor) {
|
||||
public ConcurrentHashMapKeycloakTransaction(MapStorage<V, M> map, StringKeyConvertor<K> keyConvertor) {
|
||||
this.map = map;
|
||||
this.keyConvertor = keyConvertor;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ import static org.keycloak.utils.StreamsUtil.paginatedStream;
|
|||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class ConcurrentHashMapStorage<K, V extends AbstractEntity & UpdatableEntity, M> implements MapStorage<K, V, M> {
|
||||
public class ConcurrentHashMapStorage<K, V extends AbstractEntity & UpdatableEntity, M> implements MapStorage<V, M> {
|
||||
|
||||
private final ConcurrentMap<K, V> store = new ConcurrentHashMap<>();
|
||||
|
||||
|
@ -71,7 +71,8 @@ public class ConcurrentHashMapStorage<K, V extends AbstractEntity & UpdatableEnt
|
|||
@Override
|
||||
public V read(String key) {
|
||||
Objects.requireNonNull(key, "Key must be non-null");
|
||||
return store.get(keyConvertor.fromString(key));
|
||||
K k = keyConvertor.fromStringSafe(key);
|
||||
return store.get(k);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -126,8 +127,8 @@ public class ConcurrentHashMapStorage<K, V extends AbstractEntity & UpdatableEnt
|
|||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public MapKeycloakTransaction<K, V, M> createTransaction(KeycloakSession session) {
|
||||
MapKeycloakTransaction<K, V, M> sessionTransaction = session.getAttribute("map-transaction-" + hashCode(), MapKeycloakTransaction.class);
|
||||
public MapKeycloakTransaction<V, M> createTransaction(KeycloakSession session) {
|
||||
MapKeycloakTransaction<V, M> sessionTransaction = session.getAttribute("map-transaction-" + hashCode(), MapKeycloakTransaction.class);
|
||||
return sessionTransaction == null ? new ConcurrentHashMapKeycloakTransaction<>(this, keyConvertor) : sessionTransaction;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,8 +39,8 @@ public class ConcurrentHashMapStorageProvider implements MapStorageProvider {
|
|||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <K, V extends AbstractEntity, M> MapStorage<K, V, M> getStorage(Class<M> modelType, Flag... flags) {
|
||||
public <V extends AbstractEntity, M> MapStorage<V, M> getStorage(Class<M> modelType, Flag... flags) {
|
||||
ConcurrentHashMapStorage storage = factory.getStorage(modelType, flags);
|
||||
return (MapStorage<K, V, M>) storage;
|
||||
return (MapStorage<V, M>) storage;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,9 +44,9 @@ public class UserSessionConcurrentHashMapStorage<K> extends ConcurrentHashMapSto
|
|||
|
||||
private class Transaction extends ConcurrentHashMapKeycloakTransaction<K, MapUserSessionEntity, UserSessionModel> {
|
||||
|
||||
private final MapKeycloakTransaction<K, MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionTr;
|
||||
private final MapKeycloakTransaction<MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionTr;
|
||||
|
||||
public Transaction(MapKeycloakTransaction<K, MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionTr, StringKeyConvertor<K> keyConvertor) {
|
||||
public Transaction(MapKeycloakTransaction<MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionTr, StringKeyConvertor<K> keyConvertor) {
|
||||
super(UserSessionConcurrentHashMapStorage.this, keyConvertor);
|
||||
this.clientSessionTr = clientSessionTr;
|
||||
}
|
||||
|
@ -77,8 +77,8 @@ public class UserSessionConcurrentHashMapStorage<K> extends ConcurrentHashMapSto
|
|||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public MapKeycloakTransaction<K, MapUserSessionEntity, UserSessionModel> createTransaction(KeycloakSession session) {
|
||||
MapKeycloakTransaction<K, MapUserSessionEntity, UserSessionModel> sessionTransaction = session.getAttribute("map-transaction-" + hashCode(), MapKeycloakTransaction.class);
|
||||
public MapKeycloakTransaction<MapUserSessionEntity, UserSessionModel> createTransaction(KeycloakSession session) {
|
||||
MapKeycloakTransaction<MapUserSessionEntity, UserSessionModel> sessionTransaction = session.getAttribute("map-transaction-" + hashCode(), MapKeycloakTransaction.class);
|
||||
return sessionTransaction == null ? new Transaction(clientSessionStore.createTransaction(session), clientSessionStore.getKeyConvertor()) : sessionTransaction;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,14 +72,14 @@ import static org.keycloak.models.UserModel.USERNAME;
|
|||
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
|
||||
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
||||
|
||||
public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialStore.Streams {
|
||||
public class MapUserProvider implements UserProvider.Streams, UserCredentialStore.Streams {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapUserProvider.class);
|
||||
private final KeycloakSession session;
|
||||
final MapKeycloakTransaction<K, MapUserEntity, UserModel> tx;
|
||||
private final MapStorage<K, MapUserEntity, UserModel> userStore;
|
||||
final MapKeycloakTransaction<MapUserEntity, UserModel> tx;
|
||||
private final MapStorage<MapUserEntity, UserModel> userStore;
|
||||
|
||||
public MapUserProvider(KeycloakSession session, MapStorage<K, MapUserEntity, UserModel> store) {
|
||||
public MapUserProvider(KeycloakSession session, MapStorage<MapUserEntity, UserModel> store) {
|
||||
this.session = session;
|
||||
this.userStore = store;
|
||||
this.tx = userStore.createTransaction(session);
|
||||
|
@ -131,10 +131,6 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
.orElseThrow(this::userDoesntExistException);
|
||||
}
|
||||
|
||||
private Optional<MapUserEntity> getRegisteredEntityById(RealmModel realm, String id) {
|
||||
return getEntityById(realm, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink) {
|
||||
if (user == null || user.getId() == null) {
|
||||
|
@ -314,7 +310,7 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
throw new ModelDuplicateException("User with username '" + username + "' in realm " + realm.getName() + " already exists" );
|
||||
}
|
||||
|
||||
if (tx.read(id) != null) {
|
||||
if (id != null && tx.read(id) != null) {
|
||||
throw new ModelDuplicateException("User exists: " + id);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
|||
*
|
||||
* @author mhajas
|
||||
*/
|
||||
public class MapUserProviderFactory<K> extends AbstractMapProviderFactory<UserProvider, K, MapUserEntity, UserModel> implements UserProviderFactory {
|
||||
public class MapUserProviderFactory extends AbstractMapProviderFactory<UserProvider, MapUserEntity, UserModel> implements UserProviderFactory {
|
||||
|
||||
public MapUserProviderFactory() {
|
||||
super(UserModel.class);
|
||||
|
@ -35,7 +35,7 @@ public class MapUserProviderFactory<K> extends AbstractMapProviderFactory<UserPr
|
|||
|
||||
@Override
|
||||
public UserProvider create(KeycloakSession session) {
|
||||
return new MapUserProvider<>(session, getStorage(session));
|
||||
return new MapUserProvider(session, getStorage(session));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,14 +19,13 @@ package org.keycloak.models.map.userSession;
|
|||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.models.map.common.AbstractEntity;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public abstract class AbstractUserSessionModel<K> implements UserSessionModel {
|
||||
public abstract class AbstractUserSessionModel implements UserSessionModel {
|
||||
protected final KeycloakSession session;
|
||||
protected final RealmModel realm;
|
||||
protected final MapUserSessionEntity entity;
|
||||
|
|
|
@ -37,6 +37,7 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
@ -53,22 +54,22 @@ import static org.keycloak.models.map.userSession.SessionExpiration.setUserSessi
|
|||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
||||
public class MapUserSessionProvider implements UserSessionProvider {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapUserSessionProvider.class);
|
||||
private final KeycloakSession session;
|
||||
protected final MapKeycloakTransaction<UK, MapUserSessionEntity, UserSessionModel> userSessionTx;
|
||||
protected final MapKeycloakTransaction<CK, MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionTx;
|
||||
private final MapStorage<UK, MapUserSessionEntity, UserSessionModel> userSessionStore;
|
||||
private final MapStorage<CK, MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionStore;
|
||||
protected final MapKeycloakTransaction<MapUserSessionEntity, UserSessionModel> userSessionTx;
|
||||
protected final MapKeycloakTransaction<MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionTx;
|
||||
private final MapStorage<MapUserSessionEntity, UserSessionModel> userSessionStore;
|
||||
private final MapStorage<MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionStore;
|
||||
|
||||
/**
|
||||
* Storage for transient user sessions which lifespan is limited to one request.
|
||||
*/
|
||||
private final Map<String, MapUserSessionEntity> transientUserSessions = new HashMap<>();
|
||||
|
||||
public MapUserSessionProvider(KeycloakSession session, MapStorage<UK, MapUserSessionEntity, UserSessionModel> userSessionStore,
|
||||
MapStorage<CK, MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionStore) {
|
||||
public MapUserSessionProvider(KeycloakSession session, MapStorage<MapUserSessionEntity, UserSessionModel> userSessionStore,
|
||||
MapStorage<MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionStore) {
|
||||
this.session = session;
|
||||
this.userSessionStore = userSessionStore;
|
||||
this.clientSessionStore = clientSessionStore;
|
||||
|
@ -200,20 +201,23 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
String brokerUserId, UserSessionModel.SessionPersistenceState persistenceState) {
|
||||
LOG.tracef("createUserSession(%s, %s, %s, %s)%s", id, realm, loginUsername, persistenceState, getShortStackTrace());
|
||||
|
||||
MapUserSessionEntity entity = new MapUserSessionEntity(id, realm, user, loginUsername, ipAddress, authMethod, rememberMe, brokerSessionId, brokerUserId, false);
|
||||
entity.setPersistenceState(persistenceState);
|
||||
setUserSessionExpiration(entity, realm);
|
||||
|
||||
MapUserSessionEntity entity;
|
||||
if (Objects.equals(persistenceState, TRANSIENT)) {
|
||||
if (id == null) {
|
||||
id = UUID.randomUUID().toString();
|
||||
}
|
||||
entity = new MapUserSessionEntity(id, realm, user, loginUsername, ipAddress, authMethod, rememberMe, brokerSessionId, brokerUserId, false);
|
||||
transientUserSessions.put(entity.getId(), entity);
|
||||
} else {
|
||||
if (userSessionTx.read(entity.getId()) != null) {
|
||||
throw new ModelDuplicateException("User session exists: " + entity.getId());
|
||||
if (id != null && userSessionTx.read(id) != null) {
|
||||
throw new ModelDuplicateException("User session exists: " + id);
|
||||
}
|
||||
|
||||
entity = new MapUserSessionEntity(id, realm, user, loginUsername, ipAddress, authMethod, rememberMe, brokerSessionId, brokerUserId, false);
|
||||
entity = userSessionTx.create(entity);
|
||||
}
|
||||
|
||||
entity.setPersistenceState(persistenceState);
|
||||
setUserSessionExpiration(entity, realm);
|
||||
UserSessionModel userSession = userEntityToAdapterFunc(realm).apply(entity);
|
||||
|
||||
if (userSession != null) {
|
||||
|
@ -411,17 +415,16 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
LOG.tracef("createOfflineUserSession(%s)%s", userSession, getShortStackTrace());
|
||||
|
||||
MapUserSessionEntity offlineUserSession = createUserSessionEntityInstance(userSession, true);
|
||||
offlineUserSession = userSessionTx.create(offlineUserSession);
|
||||
|
||||
// set a reference for the offline user session to the original online user session
|
||||
userSession.setNote(CORRESPONDING_SESSION_ID, offlineUserSession.getId().toString());
|
||||
userSession.setNote(CORRESPONDING_SESSION_ID, offlineUserSession.getId());
|
||||
|
||||
int currentTime = Time.currentTime();
|
||||
offlineUserSession.setStarted(currentTime);
|
||||
offlineUserSession.setLastSessionRefresh(currentTime);
|
||||
setUserSessionExpiration(offlineUserSession, userSession.getRealm());
|
||||
|
||||
offlineUserSession = userSessionTx.create(offlineUserSession);
|
||||
|
||||
return userEntityToAdapterFunc(userSession.getRealm()).apply(offlineUserSession);
|
||||
}
|
||||
|
||||
|
@ -463,14 +466,13 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
clientSessionEntity.getNotes().put(AuthenticatedClientSessionModel.STARTED_AT_NOTE, String.valueOf(currentTime));
|
||||
clientSessionEntity.setTimestamp(currentTime);
|
||||
setClientSessionExpiration(clientSessionEntity, clientSession.getRealm(), clientSession.getClient());
|
||||
clientSessionEntity = clientSessionTx.create(clientSessionEntity);
|
||||
|
||||
Optional<MapUserSessionEntity> userSessionEntity = getOfflineUserSessionEntityStream(clientSession.getRealm(), offlineUserSession.getId()).findFirst();
|
||||
if (userSessionEntity.isPresent()) {
|
||||
userSessionEntity.get().addAuthenticatedClientSession(clientSession.getClient().getId(), clientSessionEntity.getId());
|
||||
}
|
||||
|
||||
clientSessionEntity = clientSessionTx.create(clientSessionEntity);
|
||||
|
||||
return clientEntityToAdapterFunc(clientSession.getRealm(),
|
||||
clientSession.getClient(), offlineUserSession).apply(clientSessionEntity);
|
||||
}
|
||||
|
@ -554,9 +556,8 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
// Update timestamp to same value as userSession. LastSessionRefresh of userSession from DB will have correct value
|
||||
clientSession.setTimestamp(userSessionEntity.getLastSessionRefresh());
|
||||
|
||||
userSessionEntity.addAuthenticatedClientSession(entry.getKey(), clientSession.getId());
|
||||
|
||||
clientSession = clientSessionTx.create(clientSession);
|
||||
userSessionEntity.addAuthenticatedClientSession(entry.getKey(), clientSession.getId());
|
||||
}
|
||||
|
||||
return userSessionEntity;
|
||||
|
|
|
@ -79,7 +79,7 @@ public class MapUserSessionProviderFactory<UK, CK> implements AmphibianProviderF
|
|||
}
|
||||
|
||||
@Override
|
||||
public MapUserSessionProvider<UK, CK> create(KeycloakSession session) {
|
||||
public MapUserSessionProvider create(KeycloakSession session) {
|
||||
MapStorageProviderFactory storageProviderFactoryUs = (MapStorageProviderFactory) getComponentFactory(session.getKeycloakSessionFactory(),
|
||||
MapStorageProvider.class, storageConfigScopeUserSessions, MapStorageSpi.NAME);
|
||||
final MapStorageProvider factoryUs = storageProviderFactoryUs.create(session);
|
||||
|
@ -90,7 +90,7 @@ public class MapUserSessionProviderFactory<UK, CK> implements AmphibianProviderF
|
|||
final MapStorageProvider factoryCs = storageProviderFactoryCs.create(session);
|
||||
MapStorage clientSessionStore = factoryCs.getStorage(AuthenticatedClientSessionModel.class);
|
||||
|
||||
return new MapUserSessionProvider<>(session, userSessionStore, clientSessionStore);
|
||||
return new MapUserSessionProvider(session, userSessionStore, clientSessionStore);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.keycloak.protocol.oidc.OIDCConfigAttributes;
|
|||
*/
|
||||
public class SessionExpiration {
|
||||
|
||||
public static <K> void setClientSessionExpiration(MapAuthenticatedClientSessionEntity entity, RealmModel realm, ClientModel client) {
|
||||
public static void setClientSessionExpiration(MapAuthenticatedClientSessionEntity entity, RealmModel realm, ClientModel client) {
|
||||
if (entity.isOffline()) {
|
||||
long sessionExpires = entity.getTimestamp() + realm.getOfflineSessionIdleTimeout();
|
||||
if (realm.isOfflineSessionMaxLifespanEnabled()) {
|
||||
|
@ -99,7 +99,7 @@ public class SessionExpiration {
|
|||
}
|
||||
}
|
||||
|
||||
public static <K> void setUserSessionExpiration(MapUserSessionEntity entity, RealmModel realm) {
|
||||
public static void setUserSessionExpiration(MapUserSessionEntity entity, RealmModel realm) {
|
||||
if (entity.isOffline()) {
|
||||
long sessionExpires = entity.getLastSessionRefresh() + realm.getOfflineSessionIdleTimeout();
|
||||
if (realm.isOfflineSessionMaxLifespanEnabled()) {
|
||||
|
|
|
@ -142,7 +142,7 @@ public class LogoutEndpoint {
|
|||
|
||||
if (redirect != null) {
|
||||
String validatedUri;
|
||||
ClientModel client = (idToken == null || idToken.getIssuedFor() == null) ? null : realm.getClientById(idToken.getIssuedFor());
|
||||
ClientModel client = (idToken == null || idToken.getIssuedFor() == null) ? null : realm.getClientByClientId(idToken.getIssuedFor());
|
||||
if (client != null) {
|
||||
validatedUri = RedirectUtils.verifyRedirectUri(session, redirect, client);
|
||||
} else {
|
||||
|
|
|
@ -30,6 +30,8 @@ import org.keycloak.models.map.storage.MapStorage;
|
|||
import org.keycloak.models.map.storage.MapStorageProvider;
|
||||
import org.keycloak.models.map.storage.MapStorageProviderFactory;
|
||||
import org.keycloak.models.map.common.StringKeyConvertor;
|
||||
import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorage;
|
||||
import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorageProviderFactory;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.provider.InvalidationHandler.ObjectType;
|
||||
import org.hamcrest.Matchers;
|
||||
|
@ -47,7 +49,7 @@ import static org.hamcrest.Matchers.nullValue;
|
|||
*/
|
||||
@RequireProvider(value = ClientProvider.class, only = {MapClientProviderFactory.PROVIDER_ID})
|
||||
@RequireProvider(RealmProvider.class)
|
||||
@RequireProvider(MapStorageProvider.class)
|
||||
@RequireProvider(value = MapStorageProvider.class, only = {ConcurrentHashMapStorageProviderFactory.PROVIDER_ID})
|
||||
public class MapStorageTest extends KeycloakModelTest {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapStorageTest.class.getName());
|
||||
|
@ -82,9 +84,9 @@ public class MapStorageTest extends KeycloakModelTest {
|
|||
String component2Id = createMapStorageComponent("component2", "keyType", "string");
|
||||
|
||||
String[] ids = withRealm(realmId, (session, realm) -> {
|
||||
MapStorage<K, MapClientEntity, ClientModel> storageMain = (MapStorage) session.getProvider(MapStorageProvider.class).getStorage(ClientModel.class);
|
||||
MapStorage<K1, MapClientEntity, ClientModel> storage1 = (MapStorage) session.getComponentProvider(MapStorageProvider.class, component1Id).getStorage(ClientModel.class);
|
||||
MapStorage<K2, MapClientEntity, ClientModel> storage2 = (MapStorage) session.getComponentProvider(MapStorageProvider.class, component2Id).getStorage(ClientModel.class);
|
||||
ConcurrentHashMapStorage<K, MapClientEntity, ClientModel> storageMain = (ConcurrentHashMapStorage<K, MapClientEntity, ClientModel>) (MapStorage) session.getProvider(MapStorageProvider.class).getStorage(ClientModel.class);
|
||||
ConcurrentHashMapStorage<K1, MapClientEntity, ClientModel> storage1 = (ConcurrentHashMapStorage<K1, MapClientEntity, ClientModel>) (MapStorage) session.getComponentProvider(MapStorageProvider.class, component1Id).getStorage(ClientModel.class);
|
||||
ConcurrentHashMapStorage<K2, MapClientEntity, ClientModel> storage2 = (ConcurrentHashMapStorage<K2, MapClientEntity, ClientModel>) (MapStorage) session.getComponentProvider(MapStorageProvider.class, component2Id).getStorage(ClientModel.class);
|
||||
|
||||
// Assert that the map storage can be used both as a standalone store and a component
|
||||
assertThat(storageMain, notNullValue());
|
||||
|
@ -115,9 +117,9 @@ public class MapStorageTest extends KeycloakModelTest {
|
|||
assertClientDoesNotExist(storage2, idMain, kcMain, kc2);
|
||||
assertClientDoesNotExist(storage2, id1, kc1, kc2);
|
||||
|
||||
MapClientEntity clientMain = new MapClientEntityImpl<>(idMain, realmId);
|
||||
MapClientEntity client1 = new MapClientEntityImpl<>(id1, realmId);
|
||||
MapClientEntity client2 = new MapClientEntityImpl<>(id2, realmId);
|
||||
MapClientEntity clientMain = new MapClientEntityImpl(idMain, realmId);
|
||||
MapClientEntity client1 = new MapClientEntityImpl(id1, realmId);
|
||||
MapClientEntity client2 = new MapClientEntityImpl(id2, realmId);
|
||||
|
||||
clientMain = storageMain.create(clientMain);
|
||||
client1 = storage1.create(client1);
|
||||
|
@ -147,7 +149,7 @@ public class MapStorageTest extends KeycloakModelTest {
|
|||
assertClientsPersisted(component1Id, component2Id, idMain, id1, id2);
|
||||
}
|
||||
|
||||
private <K,K1> void assertClientDoesNotExist(MapStorage<K, MapClientEntity, ClientModel> storage, String id, final StringKeyConvertor<K1> kc, final StringKeyConvertor<K> kcStorage) {
|
||||
private <K,K1> void assertClientDoesNotExist(MapStorage<MapClientEntity, ClientModel> storage, String id, final StringKeyConvertor<K1> kc, final StringKeyConvertor<K> kcStorage) {
|
||||
// Assert that the other stores do not contain the to-be-created clients (if they use compatible key format)
|
||||
try {
|
||||
assertThat(storage.read(id), nullValue());
|
||||
|
@ -160,11 +162,11 @@ public class MapStorageTest extends KeycloakModelTest {
|
|||
// Check that in the next transaction, the objects are still there
|
||||
withRealm(realmId, (session, realm) -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
MapStorage<K, MapClientEntity, ClientModel> storageMain = (MapStorage) session.getProvider(MapStorageProvider.class).getStorage(ClientModel.class);
|
||||
ConcurrentHashMapStorage<K, MapClientEntity, ClientModel> storageMain = (ConcurrentHashMapStorage<K, MapClientEntity, ClientModel>) (MapStorage) session.getProvider(MapStorageProvider.class).getStorage(ClientModel.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
MapStorage<K1, MapClientEntity, ClientModel> storage1 = (MapStorage) session.getComponentProvider(MapStorageProvider.class, component1Id).getStorage(ClientModel.class);
|
||||
ConcurrentHashMapStorage<K1, MapClientEntity, ClientModel> storage1 = (ConcurrentHashMapStorage<K1, MapClientEntity, ClientModel>) (MapStorage) session.getComponentProvider(MapStorageProvider.class, component1Id).getStorage(ClientModel.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
MapStorage<K2, MapClientEntity, ClientModel> storage2 = (MapStorage) session.getComponentProvider(MapStorageProvider.class, component2Id).getStorage(ClientModel.class);
|
||||
ConcurrentHashMapStorage<K2, MapClientEntity, ClientModel> storage2 = (ConcurrentHashMapStorage<K2, MapClientEntity, ClientModel>) (MapStorage) session.getComponentProvider(MapStorageProvider.class, component2Id).getStorage(ClientModel.class);
|
||||
|
||||
final StringKeyConvertor<K> kcMain = storageMain.getKeyConvertor();
|
||||
final StringKeyConvertor<K1> kc1 = storage1.getKeyConvertor();
|
||||
|
|
Loading…
Reference in a new issue