KEYCLOAK-18845 Remove key type in map storage (simplify generics)

This commit is contained in:
Hynek Mlnarik 2021-07-19 18:19:14 +02:00 committed by Hynek Mlnařík
parent 07402d9aac
commit 8889122dc1
45 changed files with 155 additions and 157 deletions

View file

@ -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>

View file

@ -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) {

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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()

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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));
}

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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());
}

View file

@ -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);

View file

@ -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

View file

@ -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.

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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()) {

View file

@ -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 {

View file

@ -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();