KEYCLOAK-18845 Remove key type in map storage (move StringKeyConvertor to CHM)
This commit is contained in:
parent
9018fe9fad
commit
07402d9aac
76 changed files with 636 additions and 635 deletions
|
@ -31,12 +31,17 @@ import java.util.stream.Collectors;
|
|||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public abstract class MapRootAuthenticationSessionAdapter<K> extends AbstractRootAuthenticationSessionModel<MapRootAuthenticationSessionEntity<K>> {
|
||||
public class MapRootAuthenticationSessionAdapter extends AbstractRootAuthenticationSessionModel<MapRootAuthenticationSessionEntity> {
|
||||
|
||||
public MapRootAuthenticationSessionAdapter(KeycloakSession session, RealmModel realm, MapRootAuthenticationSessionEntity<K> entity) {
|
||||
public MapRootAuthenticationSessionAdapter(KeycloakSession session, RealmModel realm, MapRootAuthenticationSessionEntity entity) {
|
||||
super(session, realm, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel getRealm() {
|
||||
return session.realms().getRealm(entity.getRealmId());
|
||||
|
|
|
@ -26,9 +26,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public class MapRootAuthenticationSessionEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
||||
public class MapRootAuthenticationSessionEntity implements AbstractEntity, UpdatableEntity {
|
||||
|
||||
private K id;
|
||||
private String id;
|
||||
private String realmId;
|
||||
|
||||
/**
|
||||
|
@ -43,8 +43,7 @@ public class MapRootAuthenticationSessionEntity<K> implements AbstractEntity<K>,
|
|||
this.realmId = null;
|
||||
}
|
||||
|
||||
public MapRootAuthenticationSessionEntity(K id, String realmId) {
|
||||
Objects.requireNonNull(id, "id");
|
||||
public MapRootAuthenticationSessionEntity(String id, String realmId) {
|
||||
Objects.requireNonNull(realmId, "realmId");
|
||||
|
||||
this.id = id;
|
||||
|
@ -52,7 +51,7 @@ public class MapRootAuthenticationSessionEntity<K> implements AbstractEntity<K>,
|
|||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,12 +48,12 @@ public class MapRootAuthenticationSessionProvider<K> implements AuthenticationSe
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(MapRootAuthenticationSessionProvider.class);
|
||||
private final KeycloakSession session;
|
||||
protected final MapKeycloakTransaction<K, MapRootAuthenticationSessionEntity<K>, RootAuthenticationSessionModel> tx;
|
||||
private final MapStorage<K, MapRootAuthenticationSessionEntity<K>, RootAuthenticationSessionModel> sessionStore;
|
||||
protected final MapKeycloakTransaction<K, MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel> tx;
|
||||
private final MapStorage<K, MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel> sessionStore;
|
||||
|
||||
private static final String AUTHENTICATION_SESSION_EVENTS = "AUTHENTICATION_SESSION_EVENTS";
|
||||
|
||||
public MapRootAuthenticationSessionProvider(KeycloakSession session, MapStorage<K, MapRootAuthenticationSessionEntity<K>, RootAuthenticationSessionModel> sessionStore) {
|
||||
public MapRootAuthenticationSessionProvider(KeycloakSession session, MapStorage<K, MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel> sessionStore) {
|
||||
this.session = session;
|
||||
this.sessionStore = sessionStore;
|
||||
this.tx = sessionStore.createTransaction(session);
|
||||
|
@ -61,18 +61,13 @@ public class MapRootAuthenticationSessionProvider<K> implements AuthenticationSe
|
|||
session.getTransactionManager().enlistAfterCompletion(tx);
|
||||
}
|
||||
|
||||
private Function<MapRootAuthenticationSessionEntity<K>, RootAuthenticationSessionModel> entityToAdapterFunc(RealmModel realm) {
|
||||
private Function<MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel> entityToAdapterFunc(RealmModel realm) {
|
||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||
|
||||
return origEntity -> new MapRootAuthenticationSessionAdapter<K>(session, realm, origEntity) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return sessionStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
};
|
||||
return origEntity -> new MapRootAuthenticationSessionAdapter(session, realm, origEntity);
|
||||
}
|
||||
|
||||
private Predicate<MapRootAuthenticationSessionEntity<K>> entityRealmFilter(String realmId) {
|
||||
private Predicate<MapRootAuthenticationSessionEntity> entityRealmFilter(String realmId) {
|
||||
if (realmId == null) {
|
||||
return c -> false;
|
||||
}
|
||||
|
@ -89,16 +84,13 @@ public class MapRootAuthenticationSessionProvider<K> implements AuthenticationSe
|
|||
public RootAuthenticationSessionModel createRootAuthenticationSession(RealmModel realm, String id) {
|
||||
Objects.requireNonNull(realm, "The provided realm can't be null!");
|
||||
|
||||
final K entityId = id == null ? sessionStore.getKeyConvertor().yieldNewUniqueKey() : sessionStore.getKeyConvertor().fromString(id);
|
||||
|
||||
LOG.tracef("createRootAuthenticationSession(%s)%s", realm.getName(), getShortStackTrace());
|
||||
|
||||
// create map authentication session entity
|
||||
MapRootAuthenticationSessionEntity<K> entity = new MapRootAuthenticationSessionEntity<>(entityId, realm.getId());
|
||||
entity.setRealmId(realm.getId());
|
||||
MapRootAuthenticationSessionEntity entity = new MapRootAuthenticationSessionEntity(null, realm.getId());
|
||||
entity.setTimestamp(Time.currentTime());
|
||||
|
||||
if (tx.read(entity.getId()) != null) {
|
||||
if (id != null && tx.read(id) != null) {
|
||||
throw new ModelDuplicateException("Root authentication session exists: " + entity.getId());
|
||||
}
|
||||
|
||||
|
@ -116,7 +108,7 @@ public class MapRootAuthenticationSessionProvider<K> implements AuthenticationSe
|
|||
|
||||
LOG.tracef("getRootAuthenticationSession(%s, %s)%s", realm.getName(), authenticationSessionId, getShortStackTrace());
|
||||
|
||||
MapRootAuthenticationSessionEntity<K> entity = tx.read(sessionStore.getKeyConvertor().fromStringSafe(authenticationSessionId));
|
||||
MapRootAuthenticationSessionEntity entity = tx.read(authenticationSessionId);
|
||||
return (entity == null || !entityRealmFilter(realm.getId()).test(entity))
|
||||
? null
|
||||
: entityToAdapterFunc(realm).apply(entity);
|
||||
|
@ -125,7 +117,7 @@ public class MapRootAuthenticationSessionProvider<K> implements AuthenticationSe
|
|||
@Override
|
||||
public void removeRootAuthenticationSession(RealmModel realm, RootAuthenticationSessionModel authenticationSession) {
|
||||
Objects.requireNonNull(authenticationSession, "The provided root authentication session can't be null!");
|
||||
tx.delete(sessionStore.getKeyConvertor().fromString(authenticationSession.getId()));
|
||||
tx.delete(authenticationSession.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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<K>, RootAuthenticationSessionModel>
|
||||
public class MapRootAuthenticationSessionProviderFactory<K> extends AbstractMapProviderFactory<AuthenticationSessionProvider, K, MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel>
|
||||
implements AuthenticationSessionProviderFactory {
|
||||
|
||||
public MapRootAuthenticationSessionProviderFactory() {
|
||||
|
|
|
@ -52,25 +52,20 @@ public class MapPermissionTicketStore<K extends Comparable<K>> implements Permis
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(MapPermissionTicketStore.class);
|
||||
private final AuthorizationProvider authorizationProvider;
|
||||
final MapKeycloakTransaction<K, MapPermissionTicketEntity<K>, PermissionTicket> tx;
|
||||
private final MapStorage<K, MapPermissionTicketEntity<K>, PermissionTicket> permissionTicketStore;
|
||||
final MapKeycloakTransaction<K, MapPermissionTicketEntity, PermissionTicket> tx;
|
||||
private final MapStorage<K, MapPermissionTicketEntity, PermissionTicket> permissionTicketStore;
|
||||
|
||||
public MapPermissionTicketStore(KeycloakSession session, MapStorage<K, MapPermissionTicketEntity<K>, PermissionTicket> permissionTicketStore, AuthorizationProvider provider) {
|
||||
public MapPermissionTicketStore(KeycloakSession session, MapStorage<K, MapPermissionTicketEntity, PermissionTicket> permissionTicketStore, AuthorizationProvider provider) {
|
||||
this.authorizationProvider = provider;
|
||||
this.permissionTicketStore = permissionTicketStore;
|
||||
this.tx = permissionTicketStore.createTransaction(session);
|
||||
session.getTransactionManager().enlist(tx);
|
||||
}
|
||||
|
||||
private PermissionTicket entityToAdapter(MapPermissionTicketEntity<K> origEntity) {
|
||||
private PermissionTicket entityToAdapter(MapPermissionTicketEntity origEntity) {
|
||||
if (origEntity == null) return null;
|
||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||
return new MapPermissionTicketAdapter<K>(origEntity, authorizationProvider.getStoreFactory()) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return permissionTicketStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
};
|
||||
return new MapPermissionTicketAdapter(origEntity, authorizationProvider.getStoreFactory());
|
||||
}
|
||||
|
||||
private ModelCriteriaBuilder<PermissionTicket> forResourceServer(String resourceServerId) {
|
||||
|
@ -114,8 +109,7 @@ public class MapPermissionTicketStore<K extends Comparable<K>> implements Permis
|
|||
+ ", Resource: " + resourceId + ", owner: " + owner + ", scopeId: " + scopeId + " already exists.");
|
||||
}
|
||||
|
||||
final K newId = permissionTicketStore.getKeyConvertor().yieldNewUniqueKey();
|
||||
MapPermissionTicketEntity<K> entity = new MapPermissionTicketEntity<>(newId);
|
||||
MapPermissionTicketEntity entity = new MapPermissionTicketEntity(null);
|
||||
entity.setResourceId(resourceId);
|
||||
entity.setRequester(requester);
|
||||
entity.setCreatedTimestamp(System.currentTimeMillis());
|
||||
|
@ -135,7 +129,7 @@ public class MapPermissionTicketStore<K extends Comparable<K>> implements Permis
|
|||
@Override
|
||||
public void delete(String id) {
|
||||
LOG.tracef("delete(%s)%s", id, getShortStackTrace());
|
||||
tx.delete(permissionTicketStore.getKeyConvertor().fromString(id));
|
||||
tx.delete(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -276,7 +270,7 @@ public class MapPermissionTicketStore<K extends Comparable<K>> implements Permis
|
|||
.compare(SearchableFields.REQUESTER, Operator.EQ, requester)
|
||||
.compare(SearchableFields.GRANTED_TIMESTAMP, Operator.EXISTS);
|
||||
|
||||
Function<MapPermissionTicketEntity<K>, Resource> ticketResourceMapper;
|
||||
Function<MapPermissionTicketEntity, Resource> ticketResourceMapper;
|
||||
|
||||
ResourceStore resourceStore = authorizationProvider.getStoreFactory().getResourceStore();
|
||||
if (name != null) {
|
||||
|
|
|
@ -47,25 +47,20 @@ public class MapPolicyStore<K> implements PolicyStore {
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(MapPolicyStore.class);
|
||||
private final AuthorizationProvider authorizationProvider;
|
||||
final MapKeycloakTransaction<K, MapPolicyEntity<K>, Policy> tx;
|
||||
private final MapStorage<K, MapPolicyEntity<K>, Policy> policyStore;
|
||||
final MapKeycloakTransaction<K, MapPolicyEntity, Policy> tx;
|
||||
private final MapStorage<K, MapPolicyEntity, Policy> policyStore;
|
||||
|
||||
public MapPolicyStore(KeycloakSession session, MapStorage<K, MapPolicyEntity<K>, Policy> policyStore, AuthorizationProvider provider) {
|
||||
public MapPolicyStore(KeycloakSession session, MapStorage<K, MapPolicyEntity, Policy> policyStore, AuthorizationProvider provider) {
|
||||
this.authorizationProvider = provider;
|
||||
this.policyStore = policyStore;
|
||||
this.tx = policyStore.createTransaction(session);
|
||||
session.getTransactionManager().enlist(tx);
|
||||
}
|
||||
|
||||
private Policy entityToAdapter(MapPolicyEntity<K> origEntity) {
|
||||
private Policy entityToAdapter(MapPolicyEntity origEntity) {
|
||||
if (origEntity == null) return null;
|
||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||
return new MapPolicyAdapter<K>(origEntity, authorizationProvider.getStoreFactory()) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return policyStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
};
|
||||
return new MapPolicyAdapter(origEntity, authorizationProvider.getStoreFactory());
|
||||
}
|
||||
|
||||
private ModelCriteriaBuilder<Policy> forResourceServer(String resourceServerId) {
|
||||
|
@ -89,8 +84,8 @@ public class MapPolicyStore<K> implements PolicyStore {
|
|||
throw new ModelDuplicateException("Policy with name '" + representation.getName() + "' for " + resourceServer.getId() + " already exists");
|
||||
}
|
||||
|
||||
K uid = representation.getId() == null ? policyStore.getKeyConvertor().yieldNewUniqueKey() : policyStore.getKeyConvertor().fromString(representation.getId());
|
||||
MapPolicyEntity<K> entity = new MapPolicyEntity<>(uid);
|
||||
String uid = representation.getId();
|
||||
MapPolicyEntity entity = new MapPolicyEntity(uid);
|
||||
entity.setType(representation.getType());
|
||||
entity.setName(representation.getName());
|
||||
entity.setResourceServerId(resourceServer.getId());
|
||||
|
@ -103,7 +98,7 @@ public class MapPolicyStore<K> implements PolicyStore {
|
|||
@Override
|
||||
public void delete(String id) {
|
||||
LOG.tracef("delete(%s)%s", id, getShortStackTrace());
|
||||
tx.delete(policyStore.getKeyConvertor().fromString(id));
|
||||
tx.delete(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -153,8 +148,7 @@ public class MapPolicyStore<K> implements PolicyStore {
|
|||
}
|
||||
|
||||
return tx.read(withCriteria(mcb).pagination(firstResult, maxResult, SearchableFields.NAME))
|
||||
.map(MapPolicyEntity<K>::getId)
|
||||
.map(policyStore.getKeyConvertor()::keyToString)
|
||||
.map(MapPolicyEntity::getId)
|
||||
// We need to go through cache
|
||||
.map(id -> authorizationProvider.getStoreFactory().getPolicyStore().findById(id, resourceServerId))
|
||||
.collect(Collectors.toList());
|
||||
|
|
|
@ -44,25 +44,20 @@ public class MapResourceServerStore<K> implements ResourceServerStore {
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(MapResourceServerStore.class);
|
||||
private final AuthorizationProvider authorizationProvider;
|
||||
final MapKeycloakTransaction<K, MapResourceServerEntity<K>, ResourceServer> tx;
|
||||
private final MapStorage<K, MapResourceServerEntity<K>, ResourceServer> resourceServerStore;
|
||||
final MapKeycloakTransaction<K, MapResourceServerEntity, ResourceServer> tx;
|
||||
private final MapStorage<K, MapResourceServerEntity, ResourceServer> resourceServerStore;
|
||||
|
||||
public MapResourceServerStore(KeycloakSession session, MapStorage<K, MapResourceServerEntity<K>, ResourceServer> resourceServerStore, AuthorizationProvider provider) {
|
||||
public MapResourceServerStore(KeycloakSession session, MapStorage<K, MapResourceServerEntity, ResourceServer> resourceServerStore, AuthorizationProvider provider) {
|
||||
this.resourceServerStore = resourceServerStore;
|
||||
this.tx = resourceServerStore.createTransaction(session);
|
||||
this.authorizationProvider = provider;
|
||||
session.getTransactionManager().enlist(tx);
|
||||
}
|
||||
|
||||
private ResourceServer entityToAdapter(MapResourceServerEntity<K> origEntity) {
|
||||
private ResourceServer entityToAdapter(MapResourceServerEntity origEntity) {
|
||||
if (origEntity == null) return null;
|
||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||
return new MapResourceServerAdapter<K>(origEntity, authorizationProvider.getStoreFactory()) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return resourceServerStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
};
|
||||
return new MapResourceServerAdapter(origEntity, authorizationProvider.getStoreFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -75,15 +70,13 @@ public class MapResourceServerStore<K> implements ResourceServerStore {
|
|||
throw new ModelException("Creating resource server from federated ClientModel not supported");
|
||||
}
|
||||
|
||||
if (tx.read(resourceServerStore.getKeyConvertor().fromString(clientId)) != null) {
|
||||
if (tx.read(clientId) != null) {
|
||||
throw new ModelDuplicateException("Resource server already exists: " + clientId);
|
||||
}
|
||||
|
||||
MapResourceServerEntity<K> entity = new MapResourceServerEntity<>(resourceServerStore.getKeyConvertor().fromString(clientId));
|
||||
MapResourceServerEntity entity = new MapResourceServerEntity(clientId);
|
||||
|
||||
entity = tx.create(entity);
|
||||
|
||||
return entityToAdapter(entity);
|
||||
return entityToAdapter(tx.create(entity));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,6 +84,7 @@ public class MapResourceServerStore<K> implements ResourceServerStore {
|
|||
LOG.tracef("delete(%s, %s)%s", id, getShortStackTrace());
|
||||
if (id == null) return;
|
||||
|
||||
// TODO: Simplify the following, ideally by leveraging triggers, stored procedures or ref integrity
|
||||
PolicyStore policyStore = authorizationProvider.getStoreFactory().getPolicyStore();
|
||||
policyStore.findByResourceServer(id).stream()
|
||||
.map(Policy::getId)
|
||||
|
@ -111,7 +105,7 @@ public class MapResourceServerStore<K> implements ResourceServerStore {
|
|||
.map(Scope::getId)
|
||||
.forEach(scopeStore::delete);
|
||||
|
||||
tx.delete(resourceServerStore.getKeyConvertor().fromString(id));
|
||||
tx.delete(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -122,8 +116,7 @@ public class MapResourceServerStore<K> implements ResourceServerStore {
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
MapResourceServerEntity<K> entity = tx.read(resourceServerStore.getKeyConvertor().fromStringSafe(id));
|
||||
MapResourceServerEntity entity = tx.read(id);
|
||||
return entityToAdapter(entity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,25 +46,20 @@ public class MapResourceStore<K extends Comparable<K>> implements ResourceStore
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(MapResourceStore.class);
|
||||
private final AuthorizationProvider authorizationProvider;
|
||||
final MapKeycloakTransaction<K, MapResourceEntity<K>, Resource> tx;
|
||||
private final MapStorage<K, MapResourceEntity<K>, Resource> resourceStore;
|
||||
final MapKeycloakTransaction<K, MapResourceEntity, Resource> tx;
|
||||
private final MapStorage<K, MapResourceEntity, Resource> resourceStore;
|
||||
|
||||
public MapResourceStore(KeycloakSession session, MapStorage<K, MapResourceEntity<K>, Resource> resourceStore, AuthorizationProvider provider) {
|
||||
public MapResourceStore(KeycloakSession session, MapStorage<K, MapResourceEntity, Resource> resourceStore, AuthorizationProvider provider) {
|
||||
this.resourceStore = resourceStore;
|
||||
this.tx = resourceStore.createTransaction(session);
|
||||
session.getTransactionManager().enlist(tx);
|
||||
authorizationProvider = provider;
|
||||
}
|
||||
|
||||
private Resource entityToAdapter(MapResourceEntity<K> origEntity) {
|
||||
private Resource entityToAdapter(MapResourceEntity origEntity) {
|
||||
if (origEntity == null) return null;
|
||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||
return new MapResourceAdapter<K>(origEntity, authorizationProvider.getStoreFactory()) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return resourceStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
};
|
||||
return new MapResourceAdapter(origEntity, authorizationProvider.getStoreFactory());
|
||||
}
|
||||
|
||||
private ModelCriteriaBuilder<Resource> forResourceServer(String resourceServerId) {
|
||||
|
@ -88,8 +83,7 @@ public class MapResourceStore<K extends Comparable<K>> implements ResourceStore
|
|||
throw new ModelDuplicateException("Resource with name '" + name + "' for " + resourceServer.getId() + " already exists for request owner " + owner);
|
||||
}
|
||||
|
||||
K uid = id == null ? resourceStore.getKeyConvertor().yieldNewUniqueKey(): resourceStore.getKeyConvertor().fromString(id);
|
||||
MapResourceEntity<K> entity = new MapResourceEntity<>(uid);
|
||||
MapResourceEntity entity = new MapResourceEntity(id);
|
||||
|
||||
entity.setName(name);
|
||||
entity.setResourceServerId(resourceServer.getId());
|
||||
|
@ -104,7 +98,7 @@ public class MapResourceStore<K extends Comparable<K>> implements ResourceStore
|
|||
public void delete(String id) {
|
||||
LOG.tracef("delete(%s)%s", id, getShortStackTrace());
|
||||
|
||||
tx.delete(resourceStore.getKeyConvertor().fromString(id));
|
||||
tx.delete(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -44,25 +44,20 @@ public class MapScopeStore<K> implements ScopeStore {
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(MapScopeStore.class);
|
||||
private final AuthorizationProvider authorizationProvider;
|
||||
final MapKeycloakTransaction<K, MapScopeEntity<K>, Scope> tx;
|
||||
private final MapStorage<K, MapScopeEntity<K>, Scope> scopeStore;
|
||||
final MapKeycloakTransaction<K, MapScopeEntity, Scope> tx;
|
||||
private final MapStorage<K, MapScopeEntity, Scope> scopeStore;
|
||||
|
||||
public MapScopeStore(KeycloakSession session, MapStorage<K, MapScopeEntity<K>, Scope> scopeStore, AuthorizationProvider provider) {
|
||||
public MapScopeStore(KeycloakSession session, MapStorage<K, MapScopeEntity, Scope> scopeStore, AuthorizationProvider provider) {
|
||||
this.authorizationProvider = provider;
|
||||
this.scopeStore = scopeStore;
|
||||
this.tx = scopeStore.createTransaction(session);
|
||||
session.getTransactionManager().enlist(tx);
|
||||
}
|
||||
|
||||
private Scope entityToAdapter(MapScopeEntity<K> origEntity) {
|
||||
private Scope entityToAdapter(MapScopeEntity origEntity) {
|
||||
if (origEntity == null) return null;
|
||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||
return new MapScopeAdapter<K>(origEntity, authorizationProvider.getStoreFactory()) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return scopeStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
};
|
||||
return new MapScopeAdapter(origEntity, authorizationProvider.getStoreFactory());
|
||||
}
|
||||
|
||||
private ModelCriteriaBuilder<Scope> forResourceServer(String resourceServerId) {
|
||||
|
@ -87,8 +82,7 @@ public class MapScopeStore<K> implements ScopeStore {
|
|||
throw new ModelDuplicateException("Scope with name '" + name + "' for " + resourceServer.getId() + " already exists");
|
||||
}
|
||||
|
||||
K uid = id == null ? scopeStore.getKeyConvertor().yieldNewUniqueKey(): scopeStore.getKeyConvertor().fromString(id);
|
||||
MapScopeEntity<K> entity = new MapScopeEntity<>(uid);
|
||||
MapScopeEntity entity = new MapScopeEntity(id);
|
||||
|
||||
entity.setName(name);
|
||||
entity.setResourceServerId(resourceServer.getId());
|
||||
|
@ -101,7 +95,7 @@ public class MapScopeStore<K> implements ScopeStore {
|
|||
@Override
|
||||
public void delete(String id) {
|
||||
LOG.tracef("delete(%s)%s", id, getShortStackTrace());
|
||||
tx.delete(scopeStore.getKeyConvertor().fromString(id));
|
||||
tx.delete(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -24,7 +24,7 @@ import org.keycloak.models.map.common.AbstractEntity;
|
|||
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class AbstractPolicyModel<E extends AbstractEntity<?>> extends AbstractAuthorizationModel implements Policy {
|
||||
public abstract class AbstractPolicyModel<E extends AbstractEntity> extends AbstractAuthorizationModel implements Policy {
|
||||
|
||||
protected final E entity;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ import org.keycloak.models.map.common.AbstractEntity;
|
|||
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class AbstractResourceModel<E extends AbstractEntity<?>> extends AbstractAuthorizationModel implements Resource {
|
||||
public abstract class AbstractResourceModel<E extends AbstractEntity> extends AbstractAuthorizationModel implements Resource {
|
||||
|
||||
protected final E entity;
|
||||
|
||||
|
|
|
@ -28,12 +28,17 @@ import org.keycloak.authorization.store.StoreFactory;
|
|||
import org.keycloak.models.map.authorization.entity.MapPermissionTicketEntity;
|
||||
import static org.keycloak.authorization.UserManagedPermissionUtil.updatePolicy;
|
||||
|
||||
public abstract class MapPermissionTicketAdapter<K extends Comparable<K>> extends AbstractPermissionTicketModel<MapPermissionTicketEntity<K>> {
|
||||
public class MapPermissionTicketAdapter extends AbstractPermissionTicketModel<MapPermissionTicketEntity> {
|
||||
|
||||
public MapPermissionTicketAdapter(MapPermissionTicketEntity<K> entity, StoreFactory storeFactory) {
|
||||
public MapPermissionTicketAdapter(MapPermissionTicketEntity entity, StoreFactory storeFactory) {
|
||||
super(entity, storeFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOwner() {
|
||||
return entity.getOwner();
|
||||
|
|
|
@ -30,12 +30,17 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class MapPolicyAdapter<K> extends AbstractPolicyModel<MapPolicyEntity<K>> {
|
||||
public class MapPolicyAdapter<K> extends AbstractPolicyModel<MapPolicyEntity> {
|
||||
|
||||
public MapPolicyAdapter(MapPolicyEntity<K> entity, StoreFactory storeFactory) {
|
||||
public MapPolicyAdapter(MapPolicyEntity entity, StoreFactory storeFactory) {
|
||||
super(entity, storeFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return entity.getType();
|
||||
|
|
|
@ -28,12 +28,17 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class MapResourceAdapter<K> extends AbstractResourceModel<MapResourceEntity<K>> {
|
||||
public class MapResourceAdapter extends AbstractResourceModel<MapResourceEntity> {
|
||||
|
||||
public MapResourceAdapter(MapResourceEntity<K> entity, StoreFactory storeFactory) {
|
||||
public MapResourceAdapter(MapResourceEntity entity, StoreFactory storeFactory) {
|
||||
super(entity, storeFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return entity.getName();
|
||||
|
|
|
@ -23,12 +23,17 @@ import org.keycloak.models.map.authorization.entity.MapResourceServerEntity;
|
|||
import org.keycloak.representations.idm.authorization.DecisionStrategy;
|
||||
import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
|
||||
|
||||
public abstract class MapResourceServerAdapter<K> extends AbstractResourceServerModel<MapResourceServerEntity<K>> {
|
||||
public class MapResourceServerAdapter extends AbstractResourceServerModel<MapResourceServerEntity> {
|
||||
|
||||
public MapResourceServerAdapter(MapResourceServerEntity<K> entity, StoreFactory storeFactory) {
|
||||
public MapResourceServerAdapter(MapResourceServerEntity entity, StoreFactory storeFactory) {
|
||||
super(entity, storeFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowRemoteResourceManagement() {
|
||||
return entity.isAllowRemoteResourceManagement();
|
||||
|
|
|
@ -22,12 +22,17 @@ import org.keycloak.authorization.model.ResourceServer;
|
|||
import org.keycloak.authorization.store.StoreFactory;
|
||||
import org.keycloak.models.map.authorization.entity.MapScopeEntity;
|
||||
|
||||
public abstract class MapScopeAdapter<K> extends AbstractScopeModel<MapScopeEntity<K>> {
|
||||
public class MapScopeAdapter extends AbstractScopeModel<MapScopeEntity> {
|
||||
|
||||
public MapScopeAdapter(MapScopeEntity<K> entity, StoreFactory storeFactory) {
|
||||
public MapScopeAdapter(MapScopeEntity entity, StoreFactory storeFactory) {
|
||||
super(entity, storeFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return entity.getName();
|
||||
|
|
|
@ -22,9 +22,9 @@ import org.keycloak.models.map.common.AbstractEntity;
|
|||
import org.keycloak.models.map.common.UpdatableEntity;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MapPermissionTicketEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
||||
public class MapPermissionTicketEntity implements AbstractEntity, UpdatableEntity {
|
||||
|
||||
private final K id;
|
||||
private final String id;
|
||||
private String owner;
|
||||
private String requester;
|
||||
private Long createdTimestamp;
|
||||
|
@ -35,7 +35,7 @@ public class MapPermissionTicketEntity<K> implements AbstractEntity<K>, Updatabl
|
|||
private String policyId;
|
||||
private boolean updated = false;
|
||||
|
||||
public MapPermissionTicketEntity(K id) {
|
||||
public MapPermissionTicketEntity(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ public class MapPermissionTicketEntity<K> implements AbstractEntity<K>, Updatabl
|
|||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,9 @@ import java.util.Set;
|
|||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MapPolicyEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
||||
public class MapPolicyEntity implements AbstractEntity, UpdatableEntity {
|
||||
|
||||
private final K id;
|
||||
private final String id;
|
||||
private String name;
|
||||
private String description;
|
||||
private String type;
|
||||
|
@ -44,7 +44,7 @@ public class MapPolicyEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
|||
private String owner;
|
||||
private boolean updated = false;
|
||||
|
||||
public MapPolicyEntity(K id) {
|
||||
public MapPolicyEntity(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,7 @@ public class MapPolicyEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@ import java.util.Map;
|
|||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
public class MapResourceEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
||||
public class MapResourceEntity implements AbstractEntity, UpdatableEntity {
|
||||
|
||||
private final K id;
|
||||
private final String id;
|
||||
private String name;
|
||||
private String displayName;
|
||||
private final Set<String> uris = new HashSet<>();
|
||||
|
@ -43,7 +43,7 @@ public class MapResourceEntity<K> implements AbstractEntity<K>, UpdatableEntity
|
|||
private final Map<String, List<String>> attributes = new HashMap<>();
|
||||
private boolean updated = false;
|
||||
|
||||
public MapResourceEntity(K id) {
|
||||
public MapResourceEntity(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ public class MapResourceEntity<K> implements AbstractEntity<K>, UpdatableEntity
|
|||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,16 +24,16 @@ import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
|
|||
|
||||
import java.util.Objects;
|
||||
|
||||
public class MapResourceServerEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
||||
public class MapResourceServerEntity implements AbstractEntity, UpdatableEntity {
|
||||
|
||||
private final K id;
|
||||
private final String id;
|
||||
private boolean updated = false;
|
||||
|
||||
private boolean allowRemoteResourceManagement;
|
||||
private PolicyEnforcementMode policyEnforcementMode = PolicyEnforcementMode.ENFORCING;
|
||||
private DecisionStrategy decisionStrategy = DecisionStrategy.UNANIMOUS;
|
||||
|
||||
public MapResourceServerEntity(K id) {
|
||||
public MapResourceServerEntity(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ public class MapResourceServerEntity<K> implements AbstractEntity<K>, UpdatableE
|
|||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,16 +22,16 @@ import org.keycloak.models.map.common.AbstractEntity;
|
|||
import org.keycloak.models.map.common.UpdatableEntity;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MapScopeEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
||||
public class MapScopeEntity implements AbstractEntity, UpdatableEntity {
|
||||
|
||||
private final K id;
|
||||
private final String id;
|
||||
private String name;
|
||||
private String displayName;
|
||||
private String iconUri;
|
||||
private String resourceServerId;
|
||||
private boolean updated = false;
|
||||
|
||||
public MapScopeEntity(K id) {
|
||||
public MapScopeEntity(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ public class MapScopeEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,12 +36,17 @@ import java.util.stream.Stream;
|
|||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public abstract class MapClientAdapter<K> extends AbstractClientModel<MapClientEntity<K>> implements ClientModel {
|
||||
public abstract class MapClientAdapter extends AbstractClientModel<MapClientEntity> implements ClientModel {
|
||||
|
||||
public MapClientAdapter(KeycloakSession session, RealmModel realm, MapClientEntity<K> entity) {
|
||||
public MapClientAdapter(KeycloakSession session, RealmModel realm, MapClientEntity entity) {
|
||||
super(session, realm, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientId() {
|
||||
return entity.getClientId();
|
||||
|
|
|
@ -29,7 +29,7 @@ import java.util.stream.Stream;
|
|||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public interface MapClientEntity<K> extends AbstractEntity<K>, UpdatableEntity {
|
||||
public interface MapClientEntity extends AbstractEntity, UpdatableEntity {
|
||||
|
||||
void addClientScope(String id, Boolean defaultScope);
|
||||
|
||||
|
|
|
@ -22,15 +22,15 @@ package org.keycloak.models.map.client;
|
|||
*/
|
||||
public class MapClientEntityDelegate<K> extends MapClientEntityLazyDelegate<K> {
|
||||
|
||||
private final MapClientEntity<K> delegate;
|
||||
private final MapClientEntity delegate;
|
||||
|
||||
public MapClientEntityDelegate(MapClientEntity<K> delegate) {
|
||||
public MapClientEntityDelegate(MapClientEntity delegate) {
|
||||
super(null);
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MapClientEntity<K> getDelegate() {
|
||||
protected MapClientEntity getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,9 +36,9 @@ import java.util.stream.Stream;
|
|||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class MapClientEntityImpl<K> implements MapClientEntity<K> {
|
||||
public class MapClientEntityImpl<K> implements MapClientEntity {
|
||||
|
||||
private K id;
|
||||
private String id;
|
||||
private String realmId;
|
||||
|
||||
private String clientId;
|
||||
|
@ -84,8 +84,7 @@ public class MapClientEntityImpl<K> implements MapClientEntity<K> {
|
|||
this.realmId = null;
|
||||
}
|
||||
|
||||
public MapClientEntityImpl(K id, String realmId) {
|
||||
Objects.requireNonNull(id, "id");
|
||||
public MapClientEntityImpl(String id, String realmId) {
|
||||
Objects.requireNonNull(realmId, "realmId");
|
||||
|
||||
this.id = id;
|
||||
|
@ -93,7 +92,7 @@ public class MapClientEntityImpl<K> implements MapClientEntity<K> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,21 +29,21 @@ import java.util.stream.Stream;
|
|||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class MapClientEntityLazyDelegate<K> implements MapClientEntity<K> {
|
||||
public class MapClientEntityLazyDelegate<K> implements MapClientEntity {
|
||||
|
||||
private final Supplier<MapClientEntity<K>> delegateSupplier;
|
||||
private final Supplier<MapClientEntity> delegateSupplier;
|
||||
|
||||
private final AtomicMarkableReference<MapClientEntity<K>> delegate = new AtomicMarkableReference<>(null, false);
|
||||
private final AtomicMarkableReference<MapClientEntity> delegate = new AtomicMarkableReference<>(null, false);
|
||||
|
||||
public MapClientEntityLazyDelegate(Supplier<MapClientEntity<K>> delegateSupplier) {
|
||||
public MapClientEntityLazyDelegate(Supplier<MapClientEntity> delegateSupplier) {
|
||||
this.delegateSupplier = delegateSupplier;
|
||||
}
|
||||
|
||||
protected MapClientEntity<K> getDelegate() {
|
||||
protected MapClientEntity getDelegate() {
|
||||
if (! delegate.isMarked()) {
|
||||
delegate.compareAndSet(null, delegateSupplier == null ? null : delegateSupplier.get(), false, true);
|
||||
}
|
||||
MapClientEntity<K> ref = delegate.getReference();
|
||||
MapClientEntity ref = delegate.getReference();
|
||||
if (ref == null) {
|
||||
throw new IllegalStateException("Invalid delegate obtained");
|
||||
}
|
||||
|
@ -456,7 +456,7 @@ public class MapClientEntityLazyDelegate<K> implements MapClientEntity<K> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return getDelegate().getId();
|
||||
}
|
||||
|
||||
|
|
|
@ -54,11 +54,11 @@ public class MapClientProvider<K> implements ClientProvider {
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(MapClientProvider.class);
|
||||
private final KeycloakSession session;
|
||||
final MapKeycloakTransaction<K, MapClientEntity<K>, ClientModel> tx;
|
||||
private final MapStorage<K, MapClientEntity<K>, ClientModel> clientStore;
|
||||
private final ConcurrentMap<K, ConcurrentMap<String, Integer>> clientRegisteredNodesStore;
|
||||
final MapKeycloakTransaction<K, MapClientEntity, ClientModel> tx;
|
||||
private final MapStorage<K, MapClientEntity, ClientModel> clientStore;
|
||||
private final ConcurrentMap<String, ConcurrentMap<String, Integer>> clientRegisteredNodesStore;
|
||||
|
||||
public MapClientProvider(KeycloakSession session, MapStorage<K, MapClientEntity<K>, ClientModel> clientStore, ConcurrentMap<K, ConcurrentMap<String, Integer>> clientRegisteredNodesStore) {
|
||||
public MapClientProvider(KeycloakSession session, MapStorage<K, MapClientEntity, ClientModel> clientStore, ConcurrentMap<String, ConcurrentMap<String, Integer>> clientRegisteredNodesStore) {
|
||||
this.session = session;
|
||||
this.clientStore = clientStore;
|
||||
this.clientRegisteredNodesStore = clientRegisteredNodesStore;
|
||||
|
@ -80,15 +80,10 @@ public class MapClientProvider<K> implements ClientProvider {
|
|||
};
|
||||
}
|
||||
|
||||
private <T extends MapClientEntity<K>> Function<T, ClientModel> entityToAdapterFunc(RealmModel realm) {
|
||||
private <T extends MapClientEntity> Function<T, ClientModel> entityToAdapterFunc(RealmModel realm) {
|
||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||
|
||||
return origEntity -> new MapClientAdapter<K>(session, realm, origEntity) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return clientStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
|
||||
return origEntity -> new MapClientAdapter(session, realm, origEntity) {
|
||||
@Override
|
||||
public void updateClient() {
|
||||
LOG.tracef("updateClient(%s)%s", realm, origEntity.getId(), getShortStackTrace());
|
||||
|
@ -115,7 +110,7 @@ public class MapClientProvider<K> implements ClientProvider {
|
|||
};
|
||||
}
|
||||
|
||||
private Predicate<MapClientEntity<K>> entityRealmFilter(RealmModel realm) {
|
||||
private Predicate<MapClientEntity> entityRealmFilter(RealmModel realm) {
|
||||
if (realm == null || realm.getId() == null) {
|
||||
return c -> false;
|
||||
}
|
||||
|
@ -143,22 +138,22 @@ public class MapClientProvider<K> implements ClientProvider {
|
|||
|
||||
@Override
|
||||
public ClientModel addClient(RealmModel realm, String id, String clientId) {
|
||||
final K entityId = id == null ? clientStore.getKeyConvertor().yieldNewUniqueKey() : clientStore.getKeyConvertor().fromString(id);
|
||||
|
||||
if (clientId == null) {
|
||||
clientId = entityId.toString();
|
||||
}
|
||||
|
||||
LOG.tracef("addClient(%s, %s, %s)%s", realm, id, clientId, getShortStackTrace());
|
||||
|
||||
MapClientEntity<K> entity = new MapClientEntityImpl<>(entityId, realm.getId());
|
||||
entity.setClientId(clientId);
|
||||
MapClientEntity entity = new MapClientEntityImpl<>(null, realm.getId());
|
||||
if (clientId != null) {
|
||||
entity.setClientId(clientId);
|
||||
}
|
||||
entity.setEnabled(true);
|
||||
entity.setStandardFlowEnabled(true);
|
||||
if (tx.read(entity.getId()) != null) {
|
||||
if (id != null && tx.read(id) != null) {
|
||||
throw new ModelDuplicateException("Client exists: " + id);
|
||||
}
|
||||
entity = tx.create(entity);
|
||||
if (clientId == null) {
|
||||
clientId = entity.getId();
|
||||
entity.setClientId(clientId);
|
||||
}
|
||||
final ClientModel resource = entityToAdapterFunc(realm).apply(entity);
|
||||
|
||||
// TODO: Sending an event should be extracted to store layer
|
||||
|
@ -211,7 +206,7 @@ public class MapClientProvider<K> implements ClientProvider {
|
|||
});
|
||||
// TODO: ^^^^^^^ Up to here
|
||||
|
||||
tx.delete(clientStore.getKeyConvertor().fromString(id));
|
||||
tx.delete(id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -232,7 +227,7 @@ public class MapClientProvider<K> implements ClientProvider {
|
|||
|
||||
LOG.tracef("getClientById(%s, %s)%s", realm, id, getShortStackTrace());
|
||||
|
||||
MapClientEntity<K> entity = tx.read(clientStore.getKeyConvertor().fromStringSafe(id));
|
||||
MapClientEntity entity = tx.read(id);
|
||||
return (entity == null || ! entityRealmFilter(realm).test(entity))
|
||||
? null
|
||||
: entityToAdapterFunc(realm).apply(entity);
|
||||
|
@ -286,7 +281,7 @@ public class MapClientProvider<K> implements ClientProvider {
|
|||
@Override
|
||||
public void addClientScopes(RealmModel realm, ClientModel client, Set<ClientScopeModel> clientScopes, boolean defaultScope) {
|
||||
final String id = client.getId();
|
||||
MapClientEntity<K> entity = tx.read(clientStore.getKeyConvertor().fromString(id));
|
||||
MapClientEntity entity = tx.read(id);
|
||||
|
||||
if (entity == null) return;
|
||||
|
||||
|
@ -307,7 +302,7 @@ public class MapClientProvider<K> implements ClientProvider {
|
|||
@Override
|
||||
public void removeClientScope(RealmModel realm, ClientModel client, ClientScopeModel clientScope) {
|
||||
final String id = client.getId();
|
||||
MapClientEntity<K> entity = tx.read(clientStore.getKeyConvertor().fromString(id));
|
||||
MapClientEntity entity = tx.read(id);
|
||||
|
||||
if (entity == null) return;
|
||||
|
||||
|
@ -319,7 +314,7 @@ public class MapClientProvider<K> implements ClientProvider {
|
|||
@Override
|
||||
public Map<String, ClientScopeModel> getClientScopes(RealmModel realm, ClientModel client, boolean defaultScopes) {
|
||||
final String id = client.getId();
|
||||
MapClientEntity<K> entity = tx.read(clientStore.getKeyConvertor().fromString(id));
|
||||
MapClientEntity entity = tx.read(id);
|
||||
|
||||
if (entity == null) return null;
|
||||
|
||||
|
@ -341,7 +336,7 @@ public class MapClientProvider<K> implements ClientProvider {
|
|||
.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
|
||||
.compare(SearchableFields.ENABLED, Operator.EQ, Boolean.TRUE);
|
||||
|
||||
try (Stream<MapClientEntity<K>> st = tx.read(withCriteria(mcb))) {
|
||||
try (Stream<MapClientEntity> st = tx.read(withCriteria(mcb))) {
|
||||
return st
|
||||
.filter(mce -> mce.getRedirectUris() != null && ! mce.getRedirectUris().isEmpty())
|
||||
.collect(Collectors.toMap(
|
||||
|
@ -355,7 +350,7 @@ public class MapClientProvider<K> implements ClientProvider {
|
|||
ModelCriteriaBuilder<ClientModel> mcb = clientStore.createCriteriaBuilder()
|
||||
.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
|
||||
.compare(SearchableFields.SCOPE_MAPPING_ROLE, Operator.EQ, role.getId());
|
||||
try (Stream<MapClientEntity<K>> toRemove = tx.read(withCriteria(mcb))) {
|
||||
try (Stream<MapClientEntity> toRemove = tx.read(withCriteria(mcb))) {
|
||||
toRemove
|
||||
.map(clientEntity -> session.clients().getClientById(realm, clientEntity.getId().toString()))
|
||||
.filter(Objects::nonNull)
|
||||
|
|
|
@ -35,9 +35,9 @@ import java.util.concurrent.ConcurrentMap;
|
|||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class MapClientProviderFactory<K> extends AbstractMapProviderFactory<ClientProvider, K, MapClientEntity<K>, ClientModel> implements ClientProviderFactory, ProviderEventListener {
|
||||
public class MapClientProviderFactory<K> extends AbstractMapProviderFactory<ClientProvider, K, MapClientEntity, ClientModel> implements ClientProviderFactory, ProviderEventListener {
|
||||
|
||||
private final ConcurrentHashMap<K, ConcurrentMap<String, Integer>> REGISTERED_NODES_STORE = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, ConcurrentMap<String, Integer>> REGISTERED_NODES_STORE = new ConcurrentHashMap<>();
|
||||
|
||||
private Runnable onClose;
|
||||
|
||||
|
|
|
@ -31,12 +31,17 @@ import org.keycloak.models.RoleModel;
|
|||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.models.utils.RoleUtils;
|
||||
|
||||
public abstract class MapClientScopeAdapter<K> extends AbstractClientScopeModel<MapClientScopeEntity<K>> implements ClientScopeModel {
|
||||
public class MapClientScopeAdapter extends AbstractClientScopeModel<MapClientScopeEntity> implements ClientScopeModel {
|
||||
|
||||
public MapClientScopeAdapter(KeycloakSession session, RealmModel realm, MapClientScopeEntity<K> entity) {
|
||||
public MapClientScopeAdapter(KeycloakSession session, RealmModel realm, MapClientScopeEntity entity) {
|
||||
super(session, realm, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return entity.getName();
|
||||
|
|
|
@ -31,9 +31,9 @@ import org.keycloak.models.ProtocolMapperModel;
|
|||
import org.keycloak.models.map.common.AbstractEntity;
|
||||
import org.keycloak.models.map.common.UpdatableEntity;
|
||||
|
||||
public class MapClientScopeEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
||||
public class MapClientScopeEntity implements AbstractEntity, UpdatableEntity {
|
||||
|
||||
private final K id;
|
||||
private final String id;
|
||||
private final String realmId;
|
||||
|
||||
private String name;
|
||||
|
@ -54,8 +54,7 @@ public class MapClientScopeEntity<K> implements AbstractEntity<K>, UpdatableEnti
|
|||
this.realmId = null;
|
||||
}
|
||||
|
||||
public MapClientScopeEntity(K id, String realmId) {
|
||||
Objects.requireNonNull(id, "id");
|
||||
public MapClientScopeEntity(String id, String realmId) {
|
||||
Objects.requireNonNull(realmId, "realmId");
|
||||
|
||||
this.id = id;
|
||||
|
@ -63,7 +62,7 @@ public class MapClientScopeEntity<K> implements AbstractEntity<K>, UpdatableEnti
|
|||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,28 +43,23 @@ public class MapClientScopeProvider<K> implements ClientScopeProvider {
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(MapClientScopeProvider.class);
|
||||
private final KeycloakSession session;
|
||||
private final MapKeycloakTransaction<K, MapClientScopeEntity<K>, ClientScopeModel> tx;
|
||||
private final MapStorage<K, MapClientScopeEntity<K>, ClientScopeModel> clientScopeStore;
|
||||
private final MapKeycloakTransaction<K, MapClientScopeEntity, ClientScopeModel> tx;
|
||||
private final MapStorage<K, MapClientScopeEntity, ClientScopeModel> clientScopeStore;
|
||||
|
||||
public MapClientScopeProvider(KeycloakSession session, MapStorage<K, MapClientScopeEntity<K>, ClientScopeModel> clientScopeStore) {
|
||||
public MapClientScopeProvider(KeycloakSession session, MapStorage<K, MapClientScopeEntity, ClientScopeModel> clientScopeStore) {
|
||||
this.session = session;
|
||||
this.clientScopeStore = clientScopeStore;
|
||||
this.tx = clientScopeStore.createTransaction(session);
|
||||
session.getTransactionManager().enlist(tx);
|
||||
}
|
||||
|
||||
private Function<MapClientScopeEntity<K>, ClientScopeModel> entityToAdapterFunc(RealmModel realm) {
|
||||
private Function<MapClientScopeEntity, ClientScopeModel> entityToAdapterFunc(RealmModel realm) {
|
||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||
|
||||
return origEntity -> new MapClientScopeAdapter<K>(session, realm, origEntity) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return clientScopeStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
};
|
||||
return origEntity -> new MapClientScopeAdapter(session, realm, origEntity);
|
||||
}
|
||||
|
||||
private Predicate<MapClientScopeEntity<K>> entityRealmFilter(RealmModel realm) {
|
||||
private Predicate<MapClientScopeEntity> entityRealmFilter(RealmModel realm) {
|
||||
if (realm == null || realm.getId() == null) {
|
||||
return c -> false;
|
||||
}
|
||||
|
@ -92,13 +87,11 @@ public class MapClientScopeProvider<K> implements ClientScopeProvider {
|
|||
throw new ModelDuplicateException("Client scope with name '" + name + "' in realm " + realm.getName());
|
||||
}
|
||||
|
||||
final K entityId = id == null ? clientScopeStore.getKeyConvertor().yieldNewUniqueKey() : clientScopeStore.getKeyConvertor().fromString(id);
|
||||
|
||||
LOG.tracef("addClientScope(%s, %s, %s)%s", realm, id, name, getShortStackTrace());
|
||||
|
||||
MapClientScopeEntity<K> entity = new MapClientScopeEntity<>(entityId, realm.getId());
|
||||
MapClientScopeEntity entity = new MapClientScopeEntity(id, realm.getId());
|
||||
entity.setName(KeycloakModelUtils.convertClientScopeName(name));
|
||||
if (tx.read(entity.getId()) != null) {
|
||||
if (tx.read(id) != null) {
|
||||
throw new ModelDuplicateException("Client scope exists: " + id);
|
||||
}
|
||||
entity = tx.create(entity);
|
||||
|
@ -127,7 +120,7 @@ public class MapClientScopeProvider<K> implements ClientScopeProvider {
|
|||
}
|
||||
});
|
||||
|
||||
tx.delete(clientScopeStore.getKeyConvertor().fromString(id));
|
||||
tx.delete(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -149,14 +142,7 @@ public class MapClientScopeProvider<K> implements ClientScopeProvider {
|
|||
|
||||
LOG.tracef("getClientScopeById(%s, %s)%s", realm, id, getShortStackTrace());
|
||||
|
||||
K uuid;
|
||||
try {
|
||||
uuid = clientScopeStore.getKeyConvertor().fromStringSafe(id);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MapClientScopeEntity<K> entity = tx.read(uuid);
|
||||
MapClientScopeEntity entity = tx.read(id);
|
||||
return (entity == null || ! entityRealmFilter(realm).test(entity))
|
||||
? null
|
||||
: entityToAdapterFunc(realm).apply(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<K>, ClientScopeModel> implements ClientScopeProviderFactory {
|
||||
public class MapClientScopeProviderFactory<K> extends AbstractMapProviderFactory<ClientScopeProvider, K, MapClientScopeEntity, ClientScopeModel> implements ClientScopeProviderFactory {
|
||||
|
||||
public MapClientScopeProviderFactory() {
|
||||
super(ClientScopeModel.class);
|
||||
|
|
|
@ -20,8 +20,8 @@ package org.keycloak.models.map.common;
|
|||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public interface AbstractEntity<K> {
|
||||
public interface AbstractEntity {
|
||||
|
||||
K getId();
|
||||
String getId();
|
||||
|
||||
}
|
||||
|
|
|
@ -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<K>, M> implements AmphibianProviderFactory<T>, EnvironmentDependentProviderFactory {
|
||||
public abstract class AbstractMapProviderFactory<T extends Provider, K, V extends AbstractEntity, M> implements AmphibianProviderFactory<T>, EnvironmentDependentProviderFactory {
|
||||
|
||||
public static final String PROVIDER_ID = "map";
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.keycloak.models.map.common;
|
||||
|
||||
import org.keycloak.common.util.reflections.Reflections;
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
@ -32,7 +33,10 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
|
|||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||
import com.fasterxml.jackson.datatype.jdk8.StreamSerializer;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
|
@ -47,15 +51,19 @@ public class Serialization {
|
|||
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
||||
.setVisibility(PropertyAccessor.ALL, Visibility.NONE)
|
||||
.setVisibility(PropertyAccessor.FIELD, Visibility.ANY)
|
||||
.addMixIn(UpdatableEntity.class, IgnoreUpdatedMixIn.class);
|
||||
.addMixIn(UpdatableEntity.class, IgnoreUpdatedMixIn.class)
|
||||
.addMixIn(AbstractEntity.class, AbstractEntityMixIn.class)
|
||||
;
|
||||
|
||||
public static final ConcurrentHashMap<Class<?>, ObjectReader> READERS = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentHashMap<Class<?>, ObjectWriter> WRITERS = new ConcurrentHashMap<>();
|
||||
|
||||
abstract class IgnoreUpdatedMixIn {
|
||||
@JsonIgnore public abstract boolean isUpdated();
|
||||
|
||||
@JsonTypeInfo(use=Id.CLASS, include=As.WRAPPER_ARRAY)
|
||||
}
|
||||
|
||||
abstract class AbstractEntityMixIn {
|
||||
@JsonTypeInfo(property="id", use=Id.CLASS, include=As.WRAPPER_ARRAY)
|
||||
abstract Object getId();
|
||||
}
|
||||
|
||||
|
@ -68,6 +76,10 @@ public class Serialization {
|
|||
|
||||
|
||||
public static <T extends AbstractEntity> T from(T orig) {
|
||||
return from(orig, null);
|
||||
}
|
||||
|
||||
public static <T extends AbstractEntity> T from(T orig, String newId) {
|
||||
if (orig == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -78,11 +90,28 @@ public class Serialization {
|
|||
try {
|
||||
ObjectReader reader = READERS.computeIfAbsent(origClass, MAPPER::readerFor);
|
||||
ObjectWriter writer = WRITERS.computeIfAbsent(origClass, MAPPER::writerFor);
|
||||
final T res = reader.readValue(writer.writeValueAsBytes(orig));
|
||||
final T res;
|
||||
res = reader.readValue(writer.writeValueAsBytes(orig));
|
||||
if (newId != null) {
|
||||
updateId(origClass, res, newId);
|
||||
}
|
||||
return res;
|
||||
} catch (IOException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static <K> void updateId(Class<?> origClass, AbstractEntity res, K newId) {
|
||||
Field field = Reflections.findDeclaredField(origClass, "id");
|
||||
if (field == null) {
|
||||
throw new IllegalArgumentException("Cannot find id for " + origClass + " class");
|
||||
}
|
||||
try {
|
||||
Reflections.setAccessible(field).set(res, newId);
|
||||
} catch (IllegalArgumentException | IllegalAccessException ex) {
|
||||
Logger.getLogger(Serialization.class.getName()).log(Level.SEVERE, null, ex);
|
||||
throw new IllegalArgumentException("Cannot set id for " + origClass + " class");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.models.map.storage;
|
||||
package org.keycloak.models.map.common;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.UUID;
|
|
@ -29,11 +29,16 @@ import java.util.Map;
|
|||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
public abstract class MapGroupAdapter<K> extends AbstractGroupModel<MapGroupEntity<K>> {
|
||||
public MapGroupAdapter(KeycloakSession session, RealmModel realm, MapGroupEntity<K> entity) {
|
||||
public class MapGroupAdapter extends AbstractGroupModel<MapGroupEntity> {
|
||||
public MapGroupAdapter(KeycloakSession session, RealmModel realm, MapGroupEntity entity) {
|
||||
super(session, realm, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return entity.getName();
|
||||
|
|
|
@ -31,9 +31,9 @@ import java.util.Set;
|
|||
*
|
||||
* @author mhajas
|
||||
*/
|
||||
public class MapGroupEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
||||
public class MapGroupEntity implements AbstractEntity, UpdatableEntity {
|
||||
|
||||
private final K id;
|
||||
private final String id;
|
||||
private final String realmId;
|
||||
|
||||
private String name;
|
||||
|
@ -51,8 +51,7 @@ public class MapGroupEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
|||
this.realmId = null;
|
||||
}
|
||||
|
||||
public MapGroupEntity(K id, String realmId) {
|
||||
Objects.requireNonNull(id, "id");
|
||||
public MapGroupEntity(String id, String realmId) {
|
||||
Objects.requireNonNull(realmId, "realmId");
|
||||
|
||||
this.id = id;
|
||||
|
@ -60,7 +59,7 @@ public class MapGroupEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,24 +46,19 @@ public class MapGroupProvider<K> implements GroupProvider {
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(MapGroupProvider.class);
|
||||
private final KeycloakSession session;
|
||||
final MapKeycloakTransaction<K, MapGroupEntity<K>, GroupModel> tx;
|
||||
private final MapStorage<K, MapGroupEntity<K>, GroupModel> groupStore;
|
||||
final MapKeycloakTransaction<K, MapGroupEntity, GroupModel> tx;
|
||||
private final MapStorage<K, MapGroupEntity, GroupModel> groupStore;
|
||||
|
||||
public MapGroupProvider(KeycloakSession session, MapStorage<K, MapGroupEntity<K>, GroupModel> groupStore) {
|
||||
public MapGroupProvider(KeycloakSession session, MapStorage<K, MapGroupEntity, GroupModel> groupStore) {
|
||||
this.session = session;
|
||||
this.groupStore = groupStore;
|
||||
this.tx = groupStore.createTransaction(session);
|
||||
session.getTransactionManager().enlist(tx);
|
||||
}
|
||||
|
||||
private Function<MapGroupEntity<K>, GroupModel> entityToAdapterFunc(RealmModel realm) {
|
||||
private Function<MapGroupEntity, GroupModel> entityToAdapterFunc(RealmModel realm) {
|
||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||
return origEntity -> new MapGroupAdapter<K>(session, realm, origEntity) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return groupStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
};
|
||||
return origEntity -> new MapGroupAdapter(session, realm, origEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -74,14 +69,7 @@ public class MapGroupProvider<K> implements GroupProvider {
|
|||
|
||||
LOG.tracef("getGroupById(%s, %s)%s", realm, id, getShortStackTrace());
|
||||
|
||||
K uid;
|
||||
try {
|
||||
uid = groupStore.getKeyConvertor().fromStringSafe(id);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MapGroupEntity<K> entity = tx.read(uid);
|
||||
MapGroupEntity entity = tx.read(id);
|
||||
String realmId = realm.getId();
|
||||
return (entity == null || ! Objects.equals(realmId, entity.getRealmId()))
|
||||
? null
|
||||
|
@ -115,7 +103,7 @@ public class MapGroupProvider<K> implements GroupProvider {
|
|||
@Override
|
||||
public Stream<GroupModel> getGroupsStream(RealmModel realm, Stream<String> ids, String search, Integer first, Integer max) {
|
||||
ModelCriteriaBuilder<GroupModel> mcb = groupStore.createCriteriaBuilder()
|
||||
.compare(SearchableFields.ID, Operator.IN, ids.map(groupStore.getKeyConvertor()::fromString))
|
||||
.compare(SearchableFields.ID, Operator.IN, ids)
|
||||
.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId());
|
||||
|
||||
if (search != null) {
|
||||
|
@ -187,7 +175,6 @@ public class MapGroupProvider<K> implements GroupProvider {
|
|||
|
||||
return tx.read(withCriteria(mcb).pagination(firstResult, maxResults, SearchableFields.NAME))
|
||||
.map(MapGroupEntity::getId)
|
||||
.map(groupStore.getKeyConvertor()::keyToString)
|
||||
.map(id -> {
|
||||
GroupModel groupById = session.groups().getGroupById(realm, id);
|
||||
while (Objects.nonNull(groupById.getParentId())) {
|
||||
|
@ -200,8 +187,6 @@ public class MapGroupProvider<K> implements GroupProvider {
|
|||
@Override
|
||||
public GroupModel createGroup(RealmModel realm, String id, String name, GroupModel toParent) {
|
||||
LOG.tracef("createGroup(%s, %s, %s, %s)%s", realm, id, name, toParent, getShortStackTrace());
|
||||
final K entityId = id == null ? groupStore.getKeyConvertor().yieldNewUniqueKey() : groupStore.getKeyConvertor().fromString(id);
|
||||
|
||||
// Check Db constraint: uniqueConstraints = { @UniqueConstraint(columnNames = {"REALM_ID", "PARENT_GROUP", "NAME"})}
|
||||
String parentId = toParent == null ? null : toParent.getId();
|
||||
ModelCriteriaBuilder<GroupModel> mcb = groupStore.createCriteriaBuilder()
|
||||
|
@ -213,11 +198,11 @@ public class MapGroupProvider<K> implements GroupProvider {
|
|||
throw new ModelDuplicateException("Group with name '" + name + "' in realm " + realm.getName() + " already exists for requested parent" );
|
||||
}
|
||||
|
||||
MapGroupEntity<K> entity = new MapGroupEntity<K>(entityId, realm.getId());
|
||||
MapGroupEntity entity = new MapGroupEntity(id, realm.getId());
|
||||
entity.setName(name);
|
||||
entity.setParentId(toParent == null ? null : toParent.getId());
|
||||
if (tx.read(entity.getId()) != null) {
|
||||
throw new ModelDuplicateException("Group exists: " + entityId);
|
||||
if (id != null && tx.read(id) != null) {
|
||||
throw new ModelDuplicateException("Group exists: " + id);
|
||||
}
|
||||
entity = tx.create(entity);
|
||||
|
||||
|
@ -255,7 +240,7 @@ public class MapGroupProvider<K> implements GroupProvider {
|
|||
|
||||
// TODO: ^^^^^^^ Up to here
|
||||
|
||||
tx.delete(groupStore.getKeyConvertor().fromString(group.getId()));
|
||||
tx.delete(group.getId());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -276,7 +261,7 @@ public class MapGroupProvider<K> implements GroupProvider {
|
|||
.compare(SearchableFields.PARENT_ID, Operator.EQ, parentId)
|
||||
.compare(SearchableFields.NAME, Operator.EQ, group.getName());
|
||||
|
||||
try (Stream<MapGroupEntity<K>> possibleSiblings = tx.read(withCriteria(mcb))) {
|
||||
try (Stream<MapGroupEntity> possibleSiblings = tx.read(withCriteria(mcb))) {
|
||||
if (possibleSiblings.findAny().isPresent()) {
|
||||
throw new ModelDuplicateException("Parent already contains subgroup named '" + group.getName() + "'");
|
||||
}
|
||||
|
@ -298,7 +283,7 @@ public class MapGroupProvider<K> implements GroupProvider {
|
|||
.compare(SearchableFields.PARENT_ID, Operator.EQ, (Object) null)
|
||||
.compare(SearchableFields.NAME, Operator.EQ, subGroup.getName());
|
||||
|
||||
try (Stream<MapGroupEntity<K>> possibleSiblings = tx.read(withCriteria(mcb))) {
|
||||
try (Stream<MapGroupEntity> possibleSiblings = tx.read(withCriteria(mcb))) {
|
||||
if (possibleSiblings.findAny().isPresent()) {
|
||||
throw new ModelDuplicateException("There is already a top level group named '" + subGroup.getName() + "'");
|
||||
}
|
||||
|
@ -312,9 +297,9 @@ public class MapGroupProvider<K> implements GroupProvider {
|
|||
ModelCriteriaBuilder<GroupModel> mcb = groupStore.createCriteriaBuilder()
|
||||
.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
|
||||
.compare(SearchableFields.ASSIGNED_ROLE, Operator.EQ, role.getId());
|
||||
try (Stream<MapGroupEntity<K>> toRemove = tx.read(withCriteria(mcb))) {
|
||||
try (Stream<MapGroupEntity> toRemove = tx.read(withCriteria(mcb))) {
|
||||
toRemove
|
||||
.map(groupEntity -> session.groups().getGroupById(realm, groupEntity.getId().toString()))
|
||||
.map(groupEntity -> session.groups().getGroupById(realm, groupEntity.getId()))
|
||||
.forEach(groupModel -> groupModel.deleteRoleMapping(role));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
|||
*
|
||||
* @author mhajas
|
||||
*/
|
||||
public class MapGroupProviderFactory<K> extends AbstractMapProviderFactory<GroupProvider, K, MapGroupEntity<K>, GroupModel> implements GroupProviderFactory, ProviderEventListener {
|
||||
public class MapGroupProviderFactory<K> extends AbstractMapProviderFactory<GroupProvider, K, MapGroupEntity, GroupModel> implements GroupProviderFactory, ProviderEventListener {
|
||||
|
||||
private Runnable onClose;
|
||||
|
||||
|
|
|
@ -22,11 +22,16 @@ import org.keycloak.models.RealmModel;
|
|||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public abstract class MapUserLoginFailureAdapter<K> extends AbstractUserLoginFailureModel<MapUserLoginFailureEntity<K>> {
|
||||
public MapUserLoginFailureAdapter(KeycloakSession session, RealmModel realm, MapUserLoginFailureEntity<K> entity) {
|
||||
public class MapUserLoginFailureAdapter extends AbstractUserLoginFailureModel<MapUserLoginFailureEntity> {
|
||||
public MapUserLoginFailureAdapter(KeycloakSession session, RealmModel realm, MapUserLoginFailureEntity entity) {
|
||||
super(session, realm, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserId() {
|
||||
return entity.getUserId();
|
||||
|
|
|
@ -24,8 +24,8 @@ import java.util.Objects;
|
|||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public class MapUserLoginFailureEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
||||
private K id;
|
||||
public class MapUserLoginFailureEntity implements AbstractEntity, UpdatableEntity {
|
||||
private String id;
|
||||
private String realmId;
|
||||
private String userId;
|
||||
|
||||
|
@ -45,14 +45,14 @@ public class MapUserLoginFailureEntity<K> implements AbstractEntity<K>, Updatabl
|
|||
this.userId = null;
|
||||
}
|
||||
|
||||
public MapUserLoginFailureEntity(K id, String realmId, String userId) {
|
||||
public MapUserLoginFailureEntity(String id, String realmId, String userId) {
|
||||
this.id = id;
|
||||
this.realmId = realmId;
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,10 +37,10 @@ public class MapUserLoginFailureProvider<K> implements UserLoginFailureProvider
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(MapUserLoginFailureProvider.class);
|
||||
private final KeycloakSession session;
|
||||
protected final MapKeycloakTransaction<K, MapUserLoginFailureEntity<K>, UserLoginFailureModel> userLoginFailureTx;
|
||||
private final MapStorage<K, MapUserLoginFailureEntity<K>, UserLoginFailureModel> userLoginFailureStore;
|
||||
protected final MapKeycloakTransaction<K, MapUserLoginFailureEntity, UserLoginFailureModel> userLoginFailureTx;
|
||||
private final MapStorage<K, MapUserLoginFailureEntity, UserLoginFailureModel> userLoginFailureStore;
|
||||
|
||||
public MapUserLoginFailureProvider(KeycloakSession session, MapStorage<K, MapUserLoginFailureEntity<K>, UserLoginFailureModel> userLoginFailureStore) {
|
||||
public MapUserLoginFailureProvider(KeycloakSession session, MapStorage<K, MapUserLoginFailureEntity, UserLoginFailureModel> userLoginFailureStore) {
|
||||
this.session = session;
|
||||
this.userLoginFailureStore = userLoginFailureStore;
|
||||
|
||||
|
@ -48,14 +48,9 @@ public class MapUserLoginFailureProvider<K> implements UserLoginFailureProvider
|
|||
session.getTransactionManager().enlistAfterCompletion(userLoginFailureTx);
|
||||
}
|
||||
|
||||
private Function<MapUserLoginFailureEntity<K>, UserLoginFailureModel> userLoginFailureEntityToAdapterFunc(RealmModel realm) {
|
||||
private Function<MapUserLoginFailureEntity, UserLoginFailureModel> userLoginFailureEntityToAdapterFunc(RealmModel realm) {
|
||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||
return origEntity -> new MapUserLoginFailureAdapter<K>(session, realm, origEntity) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return userLoginFailureStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
};
|
||||
return origEntity -> new MapUserLoginFailureAdapter(session, realm, origEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -80,10 +75,10 @@ public class MapUserLoginFailureProvider<K> implements UserLoginFailureProvider
|
|||
|
||||
LOG.tracef("addUserLoginFailure(%s, %s)%s", realm, userId, getShortStackTrace());
|
||||
|
||||
MapUserLoginFailureEntity<K> userLoginFailureEntity = userLoginFailureTx.read(withCriteria(mcb)).findFirst().orElse(null);
|
||||
MapUserLoginFailureEntity userLoginFailureEntity = userLoginFailureTx.read(withCriteria(mcb)).findFirst().orElse(null);
|
||||
|
||||
if (userLoginFailureEntity == null) {
|
||||
userLoginFailureEntity = new MapUserLoginFailureEntity<>(userLoginFailureStore.getKeyConvertor().yieldNewUniqueKey(), realm.getId(), userId);
|
||||
userLoginFailureEntity = new MapUserLoginFailureEntity(null, realm.getId(), userId);
|
||||
|
||||
userLoginFailureEntity = userLoginFailureTx.create(userLoginFailureEntity);
|
||||
}
|
||||
|
|
|
@ -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<K>, UserLoginFailureModel>
|
||||
public class MapUserLoginFailureProviderFactory<K> extends AbstractMapProviderFactory<UserLoginFailureProvider, K, MapUserLoginFailureEntity, UserLoginFailureModel>
|
||||
implements UserLoginFailureProviderFactory, ProviderEventListener {
|
||||
|
||||
private Runnable onClose;
|
||||
|
|
|
@ -62,7 +62,7 @@ import org.keycloak.models.map.realm.entity.MapRequiredCredentialEntity;
|
|||
import org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntity;
|
||||
import org.keycloak.models.utils.ComponentUtil;
|
||||
|
||||
public abstract class MapRealmAdapter<K> extends AbstractRealmModel<MapRealmEntity<K>> implements RealmModel {
|
||||
public class MapRealmAdapter extends AbstractRealmModel<MapRealmEntity> implements RealmModel {
|
||||
|
||||
private static final String ACTION_TOKEN_GENERATED_BY_USER_LIFESPAN = "actionTokenGeneratedByUserLifespan";
|
||||
private static final String DEFAULT_SIGNATURE_ALGORITHM = "defaultSignatureAlgorithm";
|
||||
|
@ -77,10 +77,15 @@ public abstract class MapRealmAdapter<K> extends AbstractRealmModel<MapRealmEnti
|
|||
|
||||
private PasswordPolicy passwordPolicy;
|
||||
|
||||
public MapRealmAdapter(KeycloakSession session, MapRealmEntity<K> entity) {
|
||||
public MapRealmAdapter(KeycloakSession session, MapRealmEntity entity) {
|
||||
super(session, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return entity.getName();
|
||||
|
|
|
@ -43,9 +43,9 @@ import org.keycloak.models.map.realm.entity.MapRequiredActionProviderEntity;
|
|||
import org.keycloak.models.map.realm.entity.MapRequiredCredentialEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntity;
|
||||
|
||||
public class MapRealmEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
||||
public class MapRealmEntity implements AbstractEntity, UpdatableEntity {
|
||||
|
||||
private final K id;
|
||||
private final String id;
|
||||
private String name;
|
||||
|
||||
private Boolean enabled = false;
|
||||
|
@ -134,14 +134,12 @@ public class MapRealmEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
|||
this.id = null;
|
||||
}
|
||||
|
||||
public MapRealmEntity(K id) {
|
||||
Objects.requireNonNull(id, "id");
|
||||
|
||||
public MapRealmEntity(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,23 +44,18 @@ public class MapRealmProvider<K> implements RealmProvider {
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(MapRealmProvider.class);
|
||||
private final KeycloakSession session;
|
||||
final MapKeycloakTransaction<K, MapRealmEntity<K>, RealmModel> tx;
|
||||
private final MapStorage<K, MapRealmEntity<K>, RealmModel> realmStore;
|
||||
final MapKeycloakTransaction<K, MapRealmEntity, RealmModel> tx;
|
||||
private final MapStorage<K, MapRealmEntity, RealmModel> realmStore;
|
||||
|
||||
public MapRealmProvider(KeycloakSession session, MapStorage<K, MapRealmEntity<K>, RealmModel> realmStore) {
|
||||
public MapRealmProvider(KeycloakSession session, MapStorage<K, MapRealmEntity, RealmModel> realmStore) {
|
||||
this.session = session;
|
||||
this.realmStore = realmStore;
|
||||
this.tx = realmStore.createTransaction(session);
|
||||
session.getTransactionManager().enlist(tx);
|
||||
}
|
||||
|
||||
private RealmModel entityToAdapter(MapRealmEntity<K> entity) {
|
||||
return new MapRealmAdapter<K>(session, entity) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return realmStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
};
|
||||
private RealmModel entityToAdapter(MapRealmEntity entity) {
|
||||
return new MapRealmAdapter(session, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -74,18 +69,13 @@ public class MapRealmProvider<K> implements RealmProvider {
|
|||
throw new ModelDuplicateException("Realm with given name exists: " + name);
|
||||
}
|
||||
|
||||
K kId = id == null ? null : realmStore.getKeyConvertor().fromString(id);
|
||||
if (kId != null) {
|
||||
if (tx.read(kId) != null) {
|
||||
throw new ModelDuplicateException("Realm exists: " + kId);
|
||||
}
|
||||
} else {
|
||||
kId = realmStore.getKeyConvertor().yieldNewUniqueKey();
|
||||
if (id != null && tx.read(id) != null) {
|
||||
throw new ModelDuplicateException("Realm exists: " + id);
|
||||
}
|
||||
|
||||
LOG.tracef("createRealm(%s, %s)%s", kId, name, getShortStackTrace());
|
||||
LOG.tracef("createRealm(%s, %s)%s", id, name, getShortStackTrace());
|
||||
|
||||
MapRealmEntity<K> entity = new MapRealmEntity<>(kId);
|
||||
MapRealmEntity entity = new MapRealmEntity(id);
|
||||
entity.setName(name);
|
||||
|
||||
entity = tx.create(entity);
|
||||
|
@ -98,7 +88,7 @@ public class MapRealmProvider<K> implements RealmProvider {
|
|||
|
||||
LOG.tracef("getRealm(%s)%s", id, getShortStackTrace());
|
||||
|
||||
MapRealmEntity<K> entity = tx.read(realmStore.getKeyConvertor().fromStringSafe(id));
|
||||
MapRealmEntity entity = tx.read(id);
|
||||
return entity == null ? null : entityToAdapter(entity);
|
||||
}
|
||||
|
||||
|
@ -111,12 +101,12 @@ public class MapRealmProvider<K> implements RealmProvider {
|
|||
ModelCriteriaBuilder<RealmModel> mcb = realmStore.createCriteriaBuilder()
|
||||
.compare(SearchableFields.NAME, Operator.EQ, name);
|
||||
|
||||
K realmId = tx.read(withCriteria(mcb))
|
||||
String realmId = tx.read(withCriteria(mcb))
|
||||
.findFirst()
|
||||
.map(MapRealmEntity<K>::getId)
|
||||
.map(MapRealmEntity::getId)
|
||||
.orElse(null);
|
||||
//we need to go via session.realms() not to bypass cache
|
||||
return realmId == null ? null : session.realms().getRealm(realmStore.getKeyConvertor().keyToString(realmId));
|
||||
return realmId == null ? null : session.realms().getRealm(realmId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -165,7 +155,7 @@ public class MapRealmProvider<K> implements RealmProvider {
|
|||
});
|
||||
// TODO: ^^^^^^^ Up to here
|
||||
|
||||
tx.delete(realmStore.getKeyConvertor().fromString(id));
|
||||
tx.delete(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -175,7 +165,7 @@ public class MapRealmProvider<K> implements RealmProvider {
|
|||
.compare(SearchableFields.CLIENT_INITIAL_ACCESS, Operator.EXISTS);
|
||||
|
||||
tx.read(withCriteria(mcb))
|
||||
.forEach(MapRealmEntity<K>::removeExpiredClientInitialAccesses);
|
||||
.forEach(MapRealmEntity::removeExpiredClientInitialAccesses);
|
||||
}
|
||||
|
||||
//TODO move the following method to adapter
|
||||
|
|
|
@ -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<K>, RealmModel> implements RealmProviderFactory {
|
||||
public class MapRealmProviderFactory<K> extends AbstractMapProviderFactory<RealmProvider, K, MapRealmEntity, RealmModel> implements RealmProviderFactory {
|
||||
|
||||
public MapRealmProviderFactory() {
|
||||
super(RealmModel.class);
|
||||
|
|
|
@ -30,14 +30,19 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.models.RoleContainerModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
public abstract class MapRoleAdapter<K> extends AbstractRoleModel<MapRoleEntity<K>> implements RoleModel {
|
||||
public class MapRoleAdapter extends AbstractRoleModel<MapRoleEntity> implements RoleModel {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MapRoleAdapter.class);
|
||||
|
||||
public MapRoleAdapter(KeycloakSession session, RealmModel realm, MapRoleEntity<K> entity) {
|
||||
public MapRoleAdapter(KeycloakSession session, RealmModel realm, MapRoleEntity entity) {
|
||||
super(session, realm, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return entity.getName();
|
||||
|
|
|
@ -25,9 +25,9 @@ import java.util.Set;
|
|||
import org.keycloak.models.map.common.AbstractEntity;
|
||||
import org.keycloak.models.map.common.UpdatableEntity;
|
||||
|
||||
public class MapRoleEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
||||
public class MapRoleEntity implements AbstractEntity, UpdatableEntity {
|
||||
|
||||
private K id;
|
||||
private String id;
|
||||
private String realmId;
|
||||
|
||||
private String name;
|
||||
|
@ -47,8 +47,7 @@ public class MapRoleEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
|||
this.realmId = null;
|
||||
}
|
||||
|
||||
public MapRoleEntity(K id, String realmId) {
|
||||
Objects.requireNonNull(id, "id");
|
||||
public MapRoleEntity(String id, String realmId) {
|
||||
Objects.requireNonNull(realmId, "realmId");
|
||||
|
||||
this.id = id;
|
||||
|
@ -56,7 +55,7 @@ public class MapRoleEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,24 +44,19 @@ public class MapRoleProvider<K> implements RoleProvider {
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(MapRoleProvider.class);
|
||||
private final KeycloakSession session;
|
||||
final MapKeycloakTransaction<K, MapRoleEntity<K>, RoleModel> tx;
|
||||
private final MapStorage<K, MapRoleEntity<K>, RoleModel> roleStore;
|
||||
final MapKeycloakTransaction<K, MapRoleEntity, RoleModel> tx;
|
||||
private final MapStorage<K, MapRoleEntity, RoleModel> roleStore;
|
||||
|
||||
public MapRoleProvider(KeycloakSession session, MapStorage<K, MapRoleEntity<K>, RoleModel> roleStore) {
|
||||
public MapRoleProvider(KeycloakSession session, MapStorage<K, MapRoleEntity, RoleModel> roleStore) {
|
||||
this.session = session;
|
||||
this.roleStore = roleStore;
|
||||
this.tx = roleStore.createTransaction(session);
|
||||
session.getTransactionManager().enlist(tx);
|
||||
}
|
||||
|
||||
private Function<MapRoleEntity<K>, RoleModel> entityToAdapterFunc(RealmModel realm) {
|
||||
private Function<MapRoleEntity, RoleModel> entityToAdapterFunc(RealmModel realm) {
|
||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||
return origEntity -> new MapRoleAdapter<K>(session, realm, origEntity) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return roleStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
};
|
||||
return origEntity -> new MapRoleAdapter(session, realm, origEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -70,11 +65,9 @@ public class MapRoleProvider<K> implements RoleProvider {
|
|||
throw new ModelDuplicateException("Role exists: " + id);
|
||||
}
|
||||
|
||||
final K entityId = id == null ? roleStore.getKeyConvertor().yieldNewUniqueKey() : roleStore.getKeyConvertor().fromString(id);
|
||||
|
||||
LOG.tracef("addRealmRole(%s, %s, %s)%s", realm, id, name, getShortStackTrace());
|
||||
|
||||
MapRoleEntity<K> entity = new MapRoleEntity<K>(entityId, realm.getId());
|
||||
MapRoleEntity entity = new MapRoleEntity(id, realm.getId());
|
||||
entity.setName(name);
|
||||
entity.setRealmId(realm.getId());
|
||||
if (tx.read(entity.getId()) != null) {
|
||||
|
@ -110,11 +103,9 @@ public class MapRoleProvider<K> implements RoleProvider {
|
|||
throw new ModelDuplicateException("Role exists: " + id);
|
||||
}
|
||||
|
||||
final K entityId = id == null ? roleStore.getKeyConvertor().yieldNewUniqueKey() : roleStore.getKeyConvertor().fromString(id);
|
||||
|
||||
LOG.tracef("addClientRole(%s, %s, %s)%s", client, id, name, getShortStackTrace());
|
||||
|
||||
MapRoleEntity<K> entity = new MapRoleEntity<K>(entityId, client.getRealm().getId());
|
||||
MapRoleEntity entity = new MapRoleEntity(id, client.getRealm().getId());
|
||||
entity.setName(name);
|
||||
entity.setClientRole(true);
|
||||
entity.setClientId(client.getId());
|
||||
|
@ -166,7 +157,7 @@ public class MapRoleProvider<K> implements RoleProvider {
|
|||
});
|
||||
// TODO: ^^^^^^^ Up to here
|
||||
|
||||
tx.delete(roleStore.getKeyConvertor().fromString(role.getId()));
|
||||
tx.delete(role.getId());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -230,7 +221,7 @@ public class MapRoleProvider<K> implements RoleProvider {
|
|||
|
||||
LOG.tracef("getRoleById(%s, %s)%s", realm, id, getShortStackTrace());
|
||||
|
||||
MapRoleEntity<K> entity = tx.read(roleStore.getKeyConvertor().fromStringSafe(id));
|
||||
MapRoleEntity entity = tx.read(id);
|
||||
String realmId = realm.getId();
|
||||
return (entity == null || ! Objects.equals(realmId, entity.getRealmId()))
|
||||
? null
|
||||
|
|
|
@ -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<K>, RoleModel> implements RoleProviderFactory {
|
||||
public class MapRoleProviderFactory<K> extends AbstractMapProviderFactory<RoleProvider, K, MapRoleEntity, RoleModel> implements RoleProviderFactory {
|
||||
|
||||
public MapRoleProviderFactory() {
|
||||
super(RoleModel.class);
|
||||
|
|
|
@ -23,7 +23,7 @@ import java.util.function.Function;
|
|||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface MapKeycloakTransaction<K, V extends AbstractEntity<K>, M> extends KeycloakTransaction {
|
||||
public interface MapKeycloakTransaction<K, V extends AbstractEntity, M> extends KeycloakTransaction {
|
||||
|
||||
/**
|
||||
* Instructs this transaction to add a new value into the underlying store on commit.
|
||||
|
@ -44,7 +44,7 @@ public interface MapKeycloakTransaction<K, V extends AbstractEntity<K>, M> exten
|
|||
* @param key identifier of a value
|
||||
* @return a value associated with the given {@code key}
|
||||
*/
|
||||
V read(K key);
|
||||
V read(String key);
|
||||
|
||||
/**
|
||||
* Returns a stream of values from underlying storage that are updated based on the current transaction changes;
|
||||
|
@ -76,7 +76,7 @@ public interface MapKeycloakTransaction<K, V extends AbstractEntity<K>, M> exten
|
|||
* @return Returns {@code true} if the object has been deleted or result cannot be determined, {@code false} otherwise.
|
||||
* @param key identifier of a value
|
||||
*/
|
||||
boolean delete(K key);
|
||||
boolean delete(String key);
|
||||
|
||||
/**
|
||||
* Instructs this transaction to remove values (identified by {@code mcb} filter) from the underlying store on commit.
|
||||
|
|
|
@ -36,7 +36,7 @@ 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<K>, M> {
|
||||
public interface MapStorage<K, V extends AbstractEntity, M> {
|
||||
|
||||
/**
|
||||
* Creates an object in the store. ID of the {@code value} may be prescribed in id of the {@code value}.
|
||||
|
@ -56,7 +56,7 @@ public interface MapStorage<K, V extends AbstractEntity<K>, M> {
|
|||
* @return See description
|
||||
* @throws NullPointerException if the {@code key} is {@code null}
|
||||
*/
|
||||
V read(K key);
|
||||
V read(String key);
|
||||
|
||||
/**
|
||||
* Returns stream of objects satisfying given {@code criteria} from the storage.
|
||||
|
@ -94,7 +94,7 @@ public interface MapStorage<K, V extends AbstractEntity<K>, M> {
|
|||
* @param key
|
||||
* @return Returns {@code true} if the object has been deleted or result cannot be determined, {@code false} otherwise.
|
||||
*/
|
||||
boolean delete(K key);
|
||||
boolean delete(String key);
|
||||
|
||||
/**
|
||||
* Deletes objects that match the given criteria.
|
||||
|
@ -131,12 +131,4 @@ public interface MapStorage<K, V extends AbstractEntity<K>, M> {
|
|||
*/
|
||||
MapKeycloakTransaction<K, V, M> createTransaction(KeycloakSession session);
|
||||
|
||||
/**
|
||||
* Returns a {@link StringKeyConvertor} that is used to convert primary keys
|
||||
* from {@link String} to internal representation and vice versa.
|
||||
*
|
||||
* @return See above. Never returns {@code null}.
|
||||
*/
|
||||
StringKeyConvertor<K> getKeyConvertor();
|
||||
|
||||
}
|
||||
|
|
|
@ -36,5 +36,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<K>, M> MapStorage<K, V, M> getStorage(Class<M> modelType, Flag... flags);
|
||||
<K, V extends AbstractEntity, M> MapStorage<K, V, M> getStorage(Class<M> modelType, Flag... flags);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.keycloak.models.map.storage.chm;
|
||||
|
||||
import org.keycloak.models.map.common.StringKeyConvertor;
|
||||
import org.keycloak.models.map.common.AbstractEntity;
|
||||
import org.keycloak.models.map.common.Serialization;
|
||||
import org.keycloak.models.map.common.UpdatableEntity;
|
||||
|
@ -35,21 +36,23 @@ 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<K> & UpdatableEntity, M> implements MapKeycloakTransaction<K, V, M> {
|
||||
public class ConcurrentHashMapKeycloakTransaction<K, V extends AbstractEntity & UpdatableEntity, M> implements MapKeycloakTransaction<K, V, M> {
|
||||
|
||||
private final static Logger log = Logger.getLogger(ConcurrentHashMapKeycloakTransaction.class);
|
||||
|
||||
private boolean active;
|
||||
private boolean rollback;
|
||||
private final Map<K, MapTaskWithValue> tasks = new LinkedHashMap<>();
|
||||
private final Map<String, MapTaskWithValue> tasks = new LinkedHashMap<>();
|
||||
private final MapStorage<K, V, M> map;
|
||||
private final StringKeyConvertor<K> keyConvertor;
|
||||
|
||||
enum MapOperation {
|
||||
CREATE, UPDATE, DELETE,
|
||||
}
|
||||
|
||||
public ConcurrentHashMapKeycloakTransaction(MapStorage<K, V, M> map) {
|
||||
public ConcurrentHashMapKeycloakTransaction(MapStorage<K, V, M> map, StringKeyConvertor<K> keyConvertor) {
|
||||
this.map = map;
|
||||
this.keyConvertor = keyConvertor;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -93,11 +96,10 @@ public class ConcurrentHashMapKeycloakTransaction<K, V extends AbstractEntity<K>
|
|||
/**
|
||||
* Adds a given task if not exists for the given key
|
||||
*/
|
||||
protected void addTask(K key, MapTaskWithValue task) {
|
||||
protected void addTask(String key, MapTaskWithValue task) {
|
||||
log.tracef("Adding operation %s for %s @ %08x", task.getOperation(), key, System.identityHashCode(task.getValue()));
|
||||
|
||||
K taskKey = key;
|
||||
tasks.merge(taskKey, task, MapTaskCompose::new);
|
||||
tasks.merge(key, task, MapTaskCompose::new);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,7 +111,7 @@ public class ConcurrentHashMapKeycloakTransaction<K, V extends AbstractEntity<K>
|
|||
* @return
|
||||
*/
|
||||
public V registerEntityForChanges(V origEntity) {
|
||||
final K key = origEntity.getId();
|
||||
final String key = origEntity.getId();
|
||||
// If the entity is listed in the transaction already, return it directly
|
||||
if (tasks.containsKey(key)) {
|
||||
MapTaskWithValue current = tasks.get(key);
|
||||
|
@ -121,17 +123,17 @@ public class ConcurrentHashMapKeycloakTransaction<K, V extends AbstractEntity<K>
|
|||
}
|
||||
|
||||
@Override
|
||||
public V read(K key) {
|
||||
public V read(String sKey) {
|
||||
try {
|
||||
// TODO: Consider using Optional rather than handling NPE
|
||||
final V entity = read(key, map::read);
|
||||
final V entity = read(sKey, map::read);
|
||||
return registerEntityForChanges(entity);
|
||||
} catch (NullPointerException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public V read(K key, Function<K, V> defaultValueFunc) {
|
||||
public V read(String key, Function<String, V> defaultValueFunc) {
|
||||
MapTaskWithValue current = tasks.get(key);
|
||||
// If the key exists, then it has entered the "tasks" after bulk delete that could have
|
||||
// removed it, so looking through bulk deletes is irrelevant
|
||||
|
@ -207,16 +209,21 @@ public class ConcurrentHashMapKeycloakTransaction<K, V extends AbstractEntity<K>
|
|||
|
||||
@Override
|
||||
public V create(V value) {
|
||||
K key = value.getId();
|
||||
String key = value.getId();
|
||||
if (key == null) {
|
||||
K newKey = keyConvertor.yieldNewUniqueKey();
|
||||
key = keyConvertor.keyToString(newKey);
|
||||
value = Serialization.from(value, key);
|
||||
}
|
||||
addTask(key, new CreateOperation(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
public V updateIfChanged(V value, Predicate<V> shouldPut) {
|
||||
K key = value.getId();
|
||||
String key = value.getId();
|
||||
log.tracef("Adding operation UPDATE_IF_CHANGED for %s @ %08x", key, System.identityHashCode(value));
|
||||
|
||||
K taskKey = key;
|
||||
String taskKey = key;
|
||||
MapTaskWithValue op = new MapTaskWithValue(value) {
|
||||
@Override
|
||||
public void execute() {
|
||||
|
@ -230,7 +237,7 @@ public class ConcurrentHashMapKeycloakTransaction<K, V extends AbstractEntity<K>
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(K key) {
|
||||
public boolean delete(String key) {
|
||||
addTask(key, new DeleteOperation(key));
|
||||
return true;
|
||||
}
|
||||
|
@ -240,14 +247,14 @@ public class ConcurrentHashMapKeycloakTransaction<K, V extends AbstractEntity<K>
|
|||
public long delete(QueryParameters<M> queryParameters) {
|
||||
log.tracef("Adding operation DELETE_BULK");
|
||||
|
||||
K artificialKey = map.getKeyConvertor().yieldNewUniqueKey();
|
||||
K artificialKey = keyConvertor.yieldNewUniqueKey();
|
||||
|
||||
// Remove all tasks that create / update / delete objects deleted by the bulk removal.
|
||||
final BulkDeleteOperation bdo = new BulkDeleteOperation(queryParameters);
|
||||
Predicate<V> filterForNonDeletedObjects = bdo.getFilterForNonDeletedObjects();
|
||||
long res = 0;
|
||||
for (Iterator<Entry<K, MapTaskWithValue>> it = tasks.entrySet().iterator(); it.hasNext();) {
|
||||
Entry<K, MapTaskWithValue> me = it.next();
|
||||
for (Iterator<Entry<String, MapTaskWithValue>> it = tasks.entrySet().iterator(); it.hasNext();) {
|
||||
Entry<String, MapTaskWithValue> me = it.next();
|
||||
if (! filterForNonDeletedObjects.test(me.getValue().getValue())) {
|
||||
log.tracef(" [DELETE_BULK] removing %s", me.getKey());
|
||||
it.remove();
|
||||
|
@ -255,14 +262,14 @@ public class ConcurrentHashMapKeycloakTransaction<K, V extends AbstractEntity<K>
|
|||
}
|
||||
}
|
||||
|
||||
tasks.put(artificialKey, bdo);
|
||||
tasks.put(keyConvertor.keyToString(artificialKey), bdo);
|
||||
|
||||
return res + bdo.getCount();
|
||||
}
|
||||
|
||||
private Stream<V> createdValuesStream(Predicate<? super K> keyFilter, Predicate<? super V> entityFilter) {
|
||||
return this.tasks.entrySet().stream()
|
||||
.filter(me -> keyFilter.test(me.getKey()))
|
||||
.filter(me -> keyFilter.test(keyConvertor.fromStringSafe(me.getKey())))
|
||||
.map(Map.Entry::getValue)
|
||||
.filter(v -> v.containsCreate() && ! v.isReplace())
|
||||
.map(MapTaskWithValue::getValue)
|
||||
|
@ -362,9 +369,9 @@ public class ConcurrentHashMapKeycloakTransaction<K, V extends AbstractEntity<K>
|
|||
}
|
||||
|
||||
private class DeleteOperation extends MapTaskWithValue {
|
||||
private final K key;
|
||||
private final String key;
|
||||
|
||||
public DeleteOperation(K key) {
|
||||
public DeleteOperation(String key) {
|
||||
super(null);
|
||||
this.key = key;
|
||||
}
|
||||
|
@ -398,7 +405,7 @@ public class ConcurrentHashMapKeycloakTransaction<K, V extends AbstractEntity<K>
|
|||
|
||||
Predicate<? super V> entityFilter = mmcb.getEntityFilter();
|
||||
Predicate<? super K> keyFilter = mmcb.getKeyFilter();
|
||||
return v -> v == null || ! (keyFilter.test(v.getId()) && entityFilter.test(v));
|
||||
return v -> v == null || ! (keyFilter.test(keyConvertor.fromStringSafe(v.getId())) && entityFilter.test(v));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
*/
|
||||
package org.keycloak.models.map.storage.chm;
|
||||
|
||||
import org.keycloak.models.map.common.StringKeyConvertor;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.map.storage.MapKeycloakTransaction;
|
||||
import org.keycloak.models.map.common.AbstractEntity;
|
||||
import org.keycloak.models.map.common.Serialization;
|
||||
import org.keycloak.models.map.common.UpdatableEntity;
|
||||
import org.keycloak.models.map.storage.MapStorage;
|
||||
import org.keycloak.models.map.storage.ModelCriteriaBuilder;
|
||||
|
@ -32,7 +34,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.stream.Stream;
|
||||
import org.keycloak.models.map.storage.StringKeyConvertor;
|
||||
import org.keycloak.models.map.storage.chm.MapModelCriteriaBuilder.UpdatePredicatesFunc;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
@ -43,7 +44,7 @@ import static org.keycloak.utils.StreamsUtil.paginatedStream;
|
|||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class ConcurrentHashMapStorage<K, V extends AbstractEntity<K> & UpdatableEntity, M> implements MapStorage<K, V, M> {
|
||||
public class ConcurrentHashMapStorage<K, V extends AbstractEntity & UpdatableEntity, M> implements MapStorage<K, V, M> {
|
||||
|
||||
private final ConcurrentMap<K, V> store = new ConcurrentHashMap<>();
|
||||
|
||||
|
@ -58,25 +59,31 @@ public class ConcurrentHashMapStorage<K, V extends AbstractEntity<K> & Updatable
|
|||
|
||||
@Override
|
||||
public V create(V value) {
|
||||
K key = value.getId();
|
||||
return store.putIfAbsent(key, value);
|
||||
K key = keyConvertor.fromStringSafe(value.getId());
|
||||
if (key == null) {
|
||||
key = keyConvertor.yieldNewUniqueKey();
|
||||
value = Serialization.from(value, keyConvertor.keyToString(key));
|
||||
}
|
||||
store.putIfAbsent(key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V read(K key) {
|
||||
public V read(String key) {
|
||||
Objects.requireNonNull(key, "Key must be non-null");
|
||||
return store.get(key);
|
||||
return store.get(keyConvertor.fromString(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public V update(V value) {
|
||||
K key = value.getId();
|
||||
K key = getKeyConvertor().fromStringSafe(value.getId());
|
||||
return store.replace(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(K key) {
|
||||
return store.remove(key) != null;
|
||||
public boolean delete(String key) {
|
||||
K k = getKeyConvertor().fromStringSafe(key);
|
||||
return store.remove(k) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -114,17 +121,16 @@ public class ConcurrentHashMapStorage<K, V extends AbstractEntity<K> & Updatable
|
|||
|
||||
@Override
|
||||
public ModelCriteriaBuilder<M> createCriteriaBuilder() {
|
||||
return new MapModelCriteriaBuilder<>(fieldPredicates);
|
||||
return new MapModelCriteriaBuilder<>(keyConvertor, fieldPredicates);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public MapKeycloakTransaction<K, V, M> createTransaction(KeycloakSession session) {
|
||||
MapKeycloakTransaction<K, V, M> sessionTransaction = session.getAttribute("map-transaction-" + hashCode(), MapKeycloakTransaction.class);
|
||||
return sessionTransaction == null ? new ConcurrentHashMapKeycloakTransaction<>(this) : sessionTransaction;
|
||||
return sessionTransaction == null ? new ConcurrentHashMapKeycloakTransaction<>(this, keyConvertor) : sessionTransaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringKeyConvertor<K> getKeyConvertor() {
|
||||
return keyConvertor;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ public class ConcurrentHashMapStorageProvider implements MapStorageProvider {
|
|||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <K, V extends AbstractEntity<K>, M> MapStorage<K, V, M> getStorage(Class<M> modelType, Flag... flags) {
|
||||
public <K, V extends AbstractEntity, M> MapStorage<K, V, M> getStorage(Class<M> modelType, Flag... flags) {
|
||||
ConcurrentHashMapStorage storage = factory.getStorage(modelType, flags);
|
||||
return (MapStorage<K, V, M>) storage;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.keycloak.models.map.storage.chm;
|
||||
|
||||
import org.keycloak.models.map.common.StringKeyConvertor;
|
||||
import org.keycloak.component.AmphibianProviderFactory;
|
||||
import org.keycloak.Config.Scope;
|
||||
import org.keycloak.authorization.model.PermissionTicket;
|
||||
|
@ -63,7 +64,6 @@ import org.keycloak.models.map.storage.MapStorageProvider;
|
|||
import org.keycloak.models.map.storage.MapStorageProviderFactory;
|
||||
import org.keycloak.models.map.storage.ModelCriteriaBuilder;
|
||||
import org.keycloak.models.map.userSession.MapAuthenticatedClientSessionEntity;
|
||||
import org.keycloak.models.map.storage.StringKeyConvertor;
|
||||
import org.keycloak.models.map.user.MapUserEntity;
|
||||
import org.keycloak.models.map.userSession.MapUserSessionEntity;
|
||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||
|
@ -241,7 +241,7 @@ public class ConcurrentHashMapStorageProviderFactory implements AmphibianProvide
|
|||
}
|
||||
}
|
||||
|
||||
private <K, V extends AbstractEntity<K> & UpdatableEntity, M> ConcurrentHashMapStorage<K, V, M> loadMap(String mapName,
|
||||
private <K, V extends AbstractEntity & UpdatableEntity, M> ConcurrentHashMapStorage<K, V, M> loadMap(String mapName,
|
||||
Class<M> modelType, EnumSet<Flag> flags) {
|
||||
final StringKeyConvertor kc = keyConvertors.getOrDefault(mapName, defaultKeyConvertor);
|
||||
Class<?> valueType = MODEL_TO_VALUE_TYPE.get(modelType);
|
||||
|
@ -291,7 +291,7 @@ public class ConcurrentHashMapStorageProviderFactory implements AmphibianProvide
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <K, V extends AbstractEntity<K> & UpdatableEntity, M> ConcurrentHashMapStorage<K, V, M> getStorage(
|
||||
public <K, V extends AbstractEntity & UpdatableEntity, M> ConcurrentHashMapStorage<K, V, M> getStorage(
|
||||
Class<M> modelType, Flag... flags) {
|
||||
EnumSet<Flag> f = flags == null || flags.length == 0 ? EnumSet.noneOf(Flag.class) : EnumSet.of(flags[0], flags);
|
||||
String name = MODEL_TO_NAME.getOrDefault(modelType, modelType.getSimpleName());
|
||||
|
|
|
@ -75,21 +75,21 @@ import static org.keycloak.models.UserSessionModel.CORRESPONDING_SESSION_ID;
|
|||
*/
|
||||
public class MapFieldPredicates {
|
||||
|
||||
public static final Map<SearchableModelField<AuthenticatedClientSessionModel>, UpdatePredicatesFunc<Object, MapAuthenticatedClientSessionEntity<Object>, AuthenticatedClientSessionModel>> CLIENT_SESSION_PREDICATES = basePredicates(AuthenticatedClientSessionModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<ClientModel>, UpdatePredicatesFunc<Object, MapClientEntity<Object>, ClientModel>> CLIENT_PREDICATES = basePredicates(ClientModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<ClientScopeModel>, UpdatePredicatesFunc<Object, MapClientScopeEntity<Object>, ClientScopeModel>> CLIENT_SCOPE_PREDICATES = basePredicates(ClientScopeModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<GroupModel>, UpdatePredicatesFunc<Object, MapGroupEntity<Object>, GroupModel>> GROUP_PREDICATES = basePredicates(GroupModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<RoleModel>, UpdatePredicatesFunc<Object, MapRoleEntity<Object>, RoleModel>> ROLE_PREDICATES = basePredicates(RoleModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<RootAuthenticationSessionModel>, UpdatePredicatesFunc<Object, MapRootAuthenticationSessionEntity<Object>, RootAuthenticationSessionModel>> AUTHENTICATION_SESSION_PREDICATES = basePredicates(RootAuthenticationSessionModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<RealmModel>, UpdatePredicatesFunc<Object, MapRealmEntity<Object>, RealmModel>> REALM_PREDICATES = basePredicates(RealmModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<ResourceServer>, UpdatePredicatesFunc<Object, MapResourceServerEntity<Object>, ResourceServer>> AUTHZ_RESOURCE_SERVER_PREDICATES = basePredicates(ResourceServer.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<Resource>, UpdatePredicatesFunc<Object, MapResourceEntity<Object>, Resource>> AUTHZ_RESOURCE_PREDICATES = basePredicates(Resource.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<Scope>, UpdatePredicatesFunc<Object, MapScopeEntity<Object>, Scope>> AUTHZ_SCOPE_PREDICATES = basePredicates(Scope.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<PermissionTicket>, UpdatePredicatesFunc<Object, MapPermissionTicketEntity<Object>, PermissionTicket>> AUTHZ_PERMISSION_TICKET_PREDICATES = basePredicates(PermissionTicket.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<Policy>, UpdatePredicatesFunc<Object, MapPolicyEntity<Object>, Policy>> AUTHZ_POLICY_PREDICATES = basePredicates(Policy.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<UserLoginFailureModel>, UpdatePredicatesFunc<Object, MapUserLoginFailureEntity<Object>, UserLoginFailureModel>> USER_LOGIN_FAILURE_PREDICATES = basePredicates(UserLoginFailureModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<UserModel>, UpdatePredicatesFunc<Object, MapUserEntity<Object>, UserModel>> USER_PREDICATES = basePredicates(UserModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<UserSessionModel>, UpdatePredicatesFunc<Object, MapUserSessionEntity<Object>, UserSessionModel>> USER_SESSION_PREDICATES = basePredicates(UserSessionModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<AuthenticatedClientSessionModel>, UpdatePredicatesFunc<Object, MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel>> CLIENT_SESSION_PREDICATES = basePredicates(AuthenticatedClientSessionModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<ClientModel>, UpdatePredicatesFunc<Object, MapClientEntity, ClientModel>> CLIENT_PREDICATES = basePredicates(ClientModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<ClientScopeModel>, UpdatePredicatesFunc<Object, MapClientScopeEntity, ClientScopeModel>> CLIENT_SCOPE_PREDICATES = basePredicates(ClientScopeModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<GroupModel>, UpdatePredicatesFunc<Object, MapGroupEntity, GroupModel>> GROUP_PREDICATES = basePredicates(GroupModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<RoleModel>, UpdatePredicatesFunc<Object, MapRoleEntity, RoleModel>> ROLE_PREDICATES = basePredicates(RoleModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<RootAuthenticationSessionModel>, UpdatePredicatesFunc<Object, MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel>> AUTHENTICATION_SESSION_PREDICATES = basePredicates(RootAuthenticationSessionModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<RealmModel>, UpdatePredicatesFunc<Object, MapRealmEntity, RealmModel>> REALM_PREDICATES = basePredicates(RealmModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<ResourceServer>, UpdatePredicatesFunc<Object, MapResourceServerEntity, ResourceServer>> AUTHZ_RESOURCE_SERVER_PREDICATES = basePredicates(ResourceServer.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<Resource>, UpdatePredicatesFunc<Object, MapResourceEntity, Resource>> AUTHZ_RESOURCE_PREDICATES = basePredicates(Resource.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<Scope>, UpdatePredicatesFunc<Object, MapScopeEntity, Scope>> AUTHZ_SCOPE_PREDICATES = basePredicates(Scope.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<PermissionTicket>, UpdatePredicatesFunc<Object, MapPermissionTicketEntity, PermissionTicket>> AUTHZ_PERMISSION_TICKET_PREDICATES = basePredicates(PermissionTicket.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<Policy>, UpdatePredicatesFunc<Object, MapPolicyEntity, Policy>> AUTHZ_POLICY_PREDICATES = basePredicates(Policy.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<UserLoginFailureModel>, UpdatePredicatesFunc<Object, MapUserLoginFailureEntity, UserLoginFailureModel>> USER_LOGIN_FAILURE_PREDICATES = basePredicates(UserLoginFailureModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<UserModel>, UpdatePredicatesFunc<Object, MapUserEntity, UserModel>> USER_PREDICATES = basePredicates(UserModel.SearchableFields.ID);
|
||||
public static final Map<SearchableModelField<UserSessionModel>, UpdatePredicatesFunc<Object, MapUserSessionEntity, UserSessionModel>> USER_SESSION_PREDICATES = basePredicates(UserSessionModel.SearchableFields.ID);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final Map<Class<?>, Map> PREDICATES = new HashMap<>();
|
||||
|
@ -212,26 +212,26 @@ public class MapFieldPredicates {
|
|||
PREDICATES.put(UserLoginFailureModel.class, USER_LOGIN_FAILURE_PREDICATES);
|
||||
}
|
||||
|
||||
private static <K, V extends AbstractEntity<K>, M, L extends Comparable<L>> void put(
|
||||
private static <K, V extends AbstractEntity, M, L extends Comparable<L>> void put(
|
||||
Map<SearchableModelField<M>, UpdatePredicatesFunc<K, V, M>> map,
|
||||
SearchableModelField<M> field, Function<V, L> extractor) {
|
||||
COMPARATORS.put(field, Comparator.comparing(extractor));
|
||||
map.put(field, (mcb, op, values) -> mcb.fieldCompare(op, extractor, values));
|
||||
}
|
||||
|
||||
private static <K, V extends AbstractEntity<K>, M> void putIncomparable(
|
||||
private static <K, V extends AbstractEntity, M> void putIncomparable(
|
||||
Map<SearchableModelField<M>, UpdatePredicatesFunc<K, V, M>> map,
|
||||
SearchableModelField<M> field, Function<V, Object> extractor) {
|
||||
map.put(field, (mcb, op, values) -> mcb.fieldCompare(op, extractor, values));
|
||||
}
|
||||
|
||||
private static <K, V extends AbstractEntity<K>, M> void put(
|
||||
private static <K, V extends AbstractEntity, M> void put(
|
||||
Map<SearchableModelField<M>, UpdatePredicatesFunc<K, V, M>> map,
|
||||
SearchableModelField<M> field, UpdatePredicatesFunc<K, V, M> function) {
|
||||
map.put(field, function);
|
||||
}
|
||||
|
||||
private static <V extends AbstractEntity<?>> Function<V, String> predicateForKeyField(Function<V, Object> extractor) {
|
||||
private static <V extends AbstractEntity> Function<V, String> predicateForKeyField(Function<V, Object> extractor) {
|
||||
return entity -> {
|
||||
Object o = extractor.apply(entity);
|
||||
return o == null ? null : o.toString();
|
||||
|
@ -258,30 +258,30 @@ public class MapFieldPredicates {
|
|||
return expectedType.cast(ob);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapClientEntity<Object>, ClientModel> checkScopeMappingRole(MapModelCriteriaBuilder<Object, MapClientEntity<Object>, ClientModel> mcb, Operator op, Object[] values) {
|
||||
private static MapModelCriteriaBuilder<Object, MapClientEntity, ClientModel> checkScopeMappingRole(MapModelCriteriaBuilder<Object, MapClientEntity, ClientModel> mcb, Operator op, Object[] values) {
|
||||
String roleIdS = ensureEqSingleValue(ClientModel.SearchableFields.SCOPE_MAPPING_ROLE, "role_id", op, values);
|
||||
Function<MapClientEntity<Object>, ?> getter;
|
||||
Function<MapClientEntity, ?> getter;
|
||||
getter = ce -> ce.getScopeMappings().contains(roleIdS);
|
||||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapGroupEntity<Object>, GroupModel> checkGrantedGroupRole(MapModelCriteriaBuilder<Object, MapGroupEntity<Object>, GroupModel> mcb, Operator op, Object[] values) {
|
||||
private static MapModelCriteriaBuilder<Object, MapGroupEntity, GroupModel> checkGrantedGroupRole(MapModelCriteriaBuilder<Object, MapGroupEntity, GroupModel> mcb, Operator op, Object[] values) {
|
||||
String roleIdS = ensureEqSingleValue(GroupModel.SearchableFields.ASSIGNED_ROLE, "role_id", op, values);
|
||||
Function<MapGroupEntity<Object>, ?> getter;
|
||||
Function<MapGroupEntity, ?> getter;
|
||||
getter = ge -> ge.getGrantedRoles().contains(roleIdS);
|
||||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapUserEntity<Object>, UserModel> getUserConsentClientFederationLink(MapModelCriteriaBuilder<Object, MapUserEntity<Object>, UserModel> mcb, Operator op, Object[] values) {
|
||||
private static MapModelCriteriaBuilder<Object, MapUserEntity, UserModel> getUserConsentClientFederationLink(MapModelCriteriaBuilder<Object, MapUserEntity, UserModel> mcb, Operator op, Object[] values) {
|
||||
String providerId = ensureEqSingleValue(UserModel.SearchableFields.CONSENT_CLIENT_FEDERATION_LINK, "provider_id", op, values);
|
||||
String providerIdS = new StorageId((String) providerId, "").getId();
|
||||
Function<MapUserEntity<Object>, ?> getter;
|
||||
Function<MapUserEntity, ?> getter;
|
||||
getter = ue -> ue.getUserConsents().map(UserConsentEntity::getClientId).anyMatch(v -> v != null && v.startsWith(providerIdS));
|
||||
|
||||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapUserEntity<Object>, UserModel> checkUserAttributes(MapModelCriteriaBuilder<Object, MapUserEntity<Object>, UserModel> mcb, Operator op, Object[] values) {
|
||||
private static MapModelCriteriaBuilder<Object, MapUserEntity, UserModel> checkUserAttributes(MapModelCriteriaBuilder<Object, MapUserEntity, UserModel> mcb, Operator op, Object[] values) {
|
||||
if (values == null || values.length <= 1) {
|
||||
throw new CriterionNotSupportedException(UserModel.SearchableFields.ATTRIBUTE, op, "Invalid arguments, expected (attribute_name, ...), got: " + Arrays.toString(values));
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ public class MapFieldPredicates {
|
|||
throw new CriterionNotSupportedException(UserModel.SearchableFields.ATTRIBUTE, op, "Invalid arguments, expected (String attribute_name), got: " + Arrays.toString(values));
|
||||
}
|
||||
String attrNameS = (String) attrName;
|
||||
Function<MapUserEntity<Object>, ?> getter;
|
||||
Function<MapUserEntity, ?> getter;
|
||||
Object[] realValues = new Object[values.length - 1];
|
||||
System.arraycopy(values, 1, realValues, 0, values.length - 1);
|
||||
Predicate<Object> valueComparator = CriteriaOperator.predicateFor(op, realValues);
|
||||
|
@ -303,7 +303,7 @@ public class MapFieldPredicates {
|
|||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapClientEntity<Object>, ClientModel> checkClientAttributes(MapModelCriteriaBuilder<Object, MapClientEntity<Object>, ClientModel> mcb, Operator op, Object[] values) {
|
||||
private static MapModelCriteriaBuilder<Object, MapClientEntity, ClientModel> checkClientAttributes(MapModelCriteriaBuilder<Object, MapClientEntity, ClientModel> mcb, Operator op, Object[] values) {
|
||||
if (values == null || values.length != 2) {
|
||||
throw new CriterionNotSupportedException(ClientModel.SearchableFields.ATTRIBUTE, op, "Invalid arguments, expected attribute_name-value pair, got: " + Arrays.toString(values));
|
||||
}
|
||||
|
@ -316,7 +316,7 @@ public class MapFieldPredicates {
|
|||
Object[] realValues = new Object[values.length - 1];
|
||||
System.arraycopy(values, 1, realValues, 0, values.length - 1);
|
||||
Predicate<Object> valueComparator = CriteriaOperator.predicateFor(op, realValues);
|
||||
Function<MapClientEntity<Object>, ?> getter = ue -> {
|
||||
Function<MapClientEntity, ?> getter = ue -> {
|
||||
final List<String> attrs = ue.getAttribute(attrNameS);
|
||||
return attrs != null && attrs.stream().anyMatch(valueComparator);
|
||||
};
|
||||
|
@ -324,16 +324,16 @@ public class MapFieldPredicates {
|
|||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapUserEntity<Object>, UserModel> checkGrantedUserRole(MapModelCriteriaBuilder<Object, MapUserEntity<Object>, UserModel> mcb, Operator op, Object[] values) {
|
||||
private static MapModelCriteriaBuilder<Object, MapUserEntity, UserModel> checkGrantedUserRole(MapModelCriteriaBuilder<Object, MapUserEntity, UserModel> mcb, Operator op, Object[] values) {
|
||||
String roleIdS = ensureEqSingleValue(UserModel.SearchableFields.ASSIGNED_ROLE, "role_id", op, values);
|
||||
Function<MapUserEntity<Object>, ?> getter;
|
||||
Function<MapUserEntity, ?> getter;
|
||||
getter = ue -> ue.getRolesMembership().contains(roleIdS);
|
||||
|
||||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapResourceEntity<Object>, Resource> checkResourceUri(MapModelCriteriaBuilder<Object, MapResourceEntity<Object>, Resource> mcb, Operator op, Object[] values) {
|
||||
Function<MapResourceEntity<Object>, ?> getter;
|
||||
private static MapModelCriteriaBuilder<Object, MapResourceEntity, Resource> checkResourceUri(MapModelCriteriaBuilder<Object, MapResourceEntity, Resource> mcb, Operator op, Object[] values) {
|
||||
Function<MapResourceEntity, ?> getter;
|
||||
|
||||
if (Operator.EXISTS.equals(op)) {
|
||||
getter = re -> re.getUris() != null && !re.getUris().isEmpty();
|
||||
|
@ -348,8 +348,8 @@ public class MapFieldPredicates {
|
|||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapResourceEntity<Object>, Resource> checkResourceScopes(MapModelCriteriaBuilder<Object, MapResourceEntity<Object>, Resource> mcb, Operator op, Object[] values) {
|
||||
Function<MapResourceEntity<Object>, ?> getter;
|
||||
private static MapModelCriteriaBuilder<Object, MapResourceEntity, Resource> checkResourceScopes(MapModelCriteriaBuilder<Object, MapResourceEntity, Resource> mcb, Operator op, Object[] values) {
|
||||
Function<MapResourceEntity, ?> getter;
|
||||
|
||||
if (op == Operator.IN && values != null && values.length == 1 && (values[0] instanceof Collection)) {
|
||||
Collection<?> c = (Collection<?>) values[0];
|
||||
|
@ -362,8 +362,8 @@ public class MapFieldPredicates {
|
|||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapPolicyEntity<Object>, Policy> checkPolicyResources(MapModelCriteriaBuilder<Object, MapPolicyEntity<Object>, Policy> mcb, Operator op, Object[] values) {
|
||||
Function<MapPolicyEntity<Object>, ?> getter;
|
||||
private static MapModelCriteriaBuilder<Object, MapPolicyEntity, Policy> checkPolicyResources(MapModelCriteriaBuilder<Object, MapPolicyEntity, Policy> mcb, Operator op, Object[] values) {
|
||||
Function<MapPolicyEntity, ?> getter;
|
||||
|
||||
if (op == Operator.NOT_EXISTS) {
|
||||
getter = re -> re.getResourceIds().isEmpty();
|
||||
|
@ -378,8 +378,8 @@ public class MapFieldPredicates {
|
|||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapPolicyEntity<Object>, Policy> checkPolicyScopes(MapModelCriteriaBuilder<Object, MapPolicyEntity<Object>, Policy> mcb, Operator op, Object[] values) {
|
||||
Function<MapPolicyEntity<Object>, ?> getter;
|
||||
private static MapModelCriteriaBuilder<Object, MapPolicyEntity, Policy> checkPolicyScopes(MapModelCriteriaBuilder<Object, MapPolicyEntity, Policy> mcb, Operator op, Object[] values) {
|
||||
Function<MapPolicyEntity, ?> getter;
|
||||
|
||||
if (op == Operator.IN && values != null && values.length == 1 && (values[0] instanceof Collection)) {
|
||||
Collection<?> c = (Collection<?>) values[0];
|
||||
|
@ -392,8 +392,8 @@ public class MapFieldPredicates {
|
|||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapPolicyEntity<Object>, Policy> checkPolicyConfig(MapModelCriteriaBuilder<Object, MapPolicyEntity<Object>, Policy> mcb, Operator op, Object[] values) {
|
||||
Function<MapPolicyEntity<Object>, ?> getter;
|
||||
private static MapModelCriteriaBuilder<Object, MapPolicyEntity, Policy> checkPolicyConfig(MapModelCriteriaBuilder<Object, MapPolicyEntity, Policy> mcb, Operator op, Object[] values) {
|
||||
Function<MapPolicyEntity, ?> getter;
|
||||
|
||||
final Object attrName = values[0];
|
||||
if (!(attrName instanceof String)) {
|
||||
|
@ -412,8 +412,8 @@ public class MapFieldPredicates {
|
|||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapPolicyEntity<Object>, Policy> checkAssociatedPolicy(MapModelCriteriaBuilder<Object, MapPolicyEntity<Object>, Policy> mcb, Operator op, Object[] values) {
|
||||
Function<MapPolicyEntity<Object>, ?> getter;
|
||||
private static MapModelCriteriaBuilder<Object, MapPolicyEntity, Policy> checkAssociatedPolicy(MapModelCriteriaBuilder<Object, MapPolicyEntity, Policy> mcb, Operator op, Object[] values) {
|
||||
Function<MapPolicyEntity, ?> getter;
|
||||
|
||||
if (op == Operator.IN && values != null && values.length == 1 && (values[0] instanceof Collection)) {
|
||||
Collection<?> c = (Collection<?>) values[0];
|
||||
|
@ -426,8 +426,8 @@ public class MapFieldPredicates {
|
|||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapUserEntity<Object>, UserModel> checkUserGroup(MapModelCriteriaBuilder<Object, MapUserEntity<Object>, UserModel> mcb, Operator op, Object[] values) {
|
||||
Function<MapUserEntity<Object>, ?> getter;
|
||||
private static MapModelCriteriaBuilder<Object, MapUserEntity, UserModel> checkUserGroup(MapModelCriteriaBuilder<Object, MapUserEntity, UserModel> mcb, Operator op, Object[] values) {
|
||||
Function<MapUserEntity, ?> getter;
|
||||
if (op == Operator.IN && values != null && values.length == 1 && (values[0] instanceof Collection)) {
|
||||
Collection<?> c = (Collection<?>) values[0];
|
||||
getter = ue -> ue.getGroupsMembership().stream().anyMatch(c::contains);
|
||||
|
@ -439,23 +439,23 @@ public class MapFieldPredicates {
|
|||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapUserEntity<Object>, UserModel> checkUserClientConsent(MapModelCriteriaBuilder<Object, MapUserEntity<Object>, UserModel> mcb, Operator op, Object[] values) {
|
||||
private static MapModelCriteriaBuilder<Object, MapUserEntity, UserModel> checkUserClientConsent(MapModelCriteriaBuilder<Object, MapUserEntity, UserModel> mcb, Operator op, Object[] values) {
|
||||
String clientIdS = ensureEqSingleValue(UserModel.SearchableFields.CONSENT_FOR_CLIENT, "client_id", op, values);
|
||||
Function<MapUserEntity<Object>, ?> getter;
|
||||
Function<MapUserEntity, ?> getter;
|
||||
getter = ue -> ue.getUserConsent(clientIdS);
|
||||
|
||||
return mcb.fieldCompare(Operator.EXISTS, getter, null);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapUserEntity<Object>, UserModel> checkUserConsentsWithClientScope(MapModelCriteriaBuilder<Object, MapUserEntity<Object>, UserModel> mcb, Operator op, Object[] values) {
|
||||
private static MapModelCriteriaBuilder<Object, MapUserEntity, UserModel> checkUserConsentsWithClientScope(MapModelCriteriaBuilder<Object, MapUserEntity, UserModel> mcb, Operator op, Object[] values) {
|
||||
String clientScopeIdS = ensureEqSingleValue(UserModel.SearchableFields.CONSENT_FOR_CLIENT, "client_scope_id", op, values);
|
||||
Function<MapUserEntity<Object>, ?> getter;
|
||||
Function<MapUserEntity, ?> getter;
|
||||
getter = ue -> ue.getUserConsents().anyMatch(consent -> consent.getGrantedClientScopesIds().contains(clientScopeIdS));
|
||||
|
||||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapUserEntity<Object>, UserModel> getUserIdpAliasAtIdentityProviderPredicate(MapModelCriteriaBuilder<Object, MapUserEntity<Object>, UserModel> mcb, Operator op, Object[] values) {
|
||||
private static MapModelCriteriaBuilder<Object, MapUserEntity, UserModel> getUserIdpAliasAtIdentityProviderPredicate(MapModelCriteriaBuilder<Object, MapUserEntity, UserModel> mcb, Operator op, Object[] values) {
|
||||
if (op != Operator.EQ) {
|
||||
throw new CriterionNotSupportedException(UserModel.SearchableFields.IDP_AND_USER, op);
|
||||
}
|
||||
|
@ -464,7 +464,7 @@ public class MapFieldPredicates {
|
|||
}
|
||||
|
||||
final Object idpAlias = values[0];
|
||||
Function<MapUserEntity<Object>, ?> getter;
|
||||
Function<MapUserEntity, ?> getter;
|
||||
if (values.length == 1) {
|
||||
getter = ue -> ue.getFederatedIdentities()
|
||||
.anyMatch(aue -> Objects.equals(idpAlias, aue.getIdentityProvider()));
|
||||
|
@ -481,25 +481,25 @@ public class MapFieldPredicates {
|
|||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapRealmEntity<Object>, RealmModel> checkRealmsWithComponentType(MapModelCriteriaBuilder<Object, MapRealmEntity<Object>, RealmModel> mcb, Operator op, Object[] values) {
|
||||
private static MapModelCriteriaBuilder<Object, MapRealmEntity, RealmModel> checkRealmsWithComponentType(MapModelCriteriaBuilder<Object, MapRealmEntity, RealmModel> mcb, Operator op, Object[] values) {
|
||||
String providerType = ensureEqSingleValue(RealmModel.SearchableFields.COMPONENT_PROVIDER_TYPE, "component_provider_type", op, values);
|
||||
Function<MapRealmEntity<Object>, ?> getter = realmEntity -> realmEntity.getComponents().anyMatch(component -> component.getProviderType().equals(providerType));
|
||||
Function<MapRealmEntity, ?> getter = realmEntity -> realmEntity.getComponents().anyMatch(component -> component.getProviderType().equals(providerType));
|
||||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
private static MapModelCriteriaBuilder<Object, MapUserSessionEntity<Object>, UserSessionModel> checkUserSessionContainsAuthenticatedClientSession(MapModelCriteriaBuilder<Object, MapUserSessionEntity<Object>, UserSessionModel> mcb, Operator op, Object[] values) {
|
||||
private static MapModelCriteriaBuilder<Object, MapUserSessionEntity, UserSessionModel> checkUserSessionContainsAuthenticatedClientSession(MapModelCriteriaBuilder<Object, MapUserSessionEntity, UserSessionModel> mcb, Operator op, Object[] values) {
|
||||
String clientId = ensureEqSingleValue(UserSessionModel.SearchableFields.CLIENT_ID, "client_id", op, values);
|
||||
Function<MapUserSessionEntity<Object>, ?> getter = use -> (use.getAuthenticatedClientSessions().containsKey(clientId));
|
||||
Function<MapUserSessionEntity, ?> getter = use -> (use.getAuthenticatedClientSessions().containsKey(clientId));
|
||||
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
|
||||
}
|
||||
|
||||
protected static <K, V extends AbstractEntity<K>, M> Map<SearchableModelField<M>, UpdatePredicatesFunc<K, V, M>> basePredicates(SearchableModelField<M> idField) {
|
||||
protected static <K, V extends AbstractEntity, M> Map<SearchableModelField<M>, UpdatePredicatesFunc<K, V, M>> basePredicates(SearchableModelField<M> idField) {
|
||||
Map<SearchableModelField<M>, UpdatePredicatesFunc<K, V, M>> fieldPredicates = new HashMap<>();
|
||||
fieldPredicates.put(idField, MapModelCriteriaBuilder::idCompare);
|
||||
return fieldPredicates;
|
||||
}
|
||||
|
||||
public static <K, V extends AbstractEntity<K>, M> Comparator<V> getComparator(QueryParameters.OrderBy<M> orderBy) {
|
||||
public static <K, V extends AbstractEntity, M> Comparator<V> getComparator(QueryParameters.OrderBy<M> orderBy) {
|
||||
SearchableModelField<M> searchableModelField = orderBy.getModelField();
|
||||
QueryParameters.Order order = orderBy.getOrder();
|
||||
|
||||
|
@ -518,14 +518,14 @@ public class MapFieldPredicates {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <K, V extends AbstractEntity<K>, M> Comparator<V> getComparator(Stream<QueryParameters.OrderBy<M>> ordering) {
|
||||
public static <K, V extends AbstractEntity, M> Comparator<V> getComparator(Stream<QueryParameters.OrderBy<M>> ordering) {
|
||||
return (Comparator<V>) ordering.map(MapFieldPredicates::getComparator)
|
||||
.reduce(Comparator::thenComparing)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Cannot create comparator for " + ordering));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <K, V extends AbstractEntity<K>, M> Map<SearchableModelField<M>, UpdatePredicatesFunc<K, V, M>> getPredicates(Class<M> clazz) {
|
||||
public static <K, V extends AbstractEntity, M> Map<SearchableModelField<M>, UpdatePredicatesFunc<K, V, M>> getPredicates(Class<M> clazz) {
|
||||
return PREDICATES.get(clazz);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.keycloak.models.map.storage.chm;
|
||||
|
||||
import org.keycloak.models.map.common.StringKeyConvertor;
|
||||
import org.keycloak.models.map.common.AbstractEntity;
|
||||
import org.keycloak.storage.SearchableModelField;
|
||||
import java.util.Map;
|
||||
|
@ -23,15 +24,18 @@ import java.util.function.Function;
|
|||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
import org.keycloak.models.map.storage.ModelCriteriaBuilder;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class MapModelCriteriaBuilder<K, V extends AbstractEntity<K>, M> implements ModelCriteriaBuilder<M> {
|
||||
public class MapModelCriteriaBuilder<K, V extends AbstractEntity, M> implements ModelCriteriaBuilder<M> {
|
||||
|
||||
@FunctionalInterface
|
||||
public static interface UpdatePredicatesFunc<K, V extends AbstractEntity<K>, M> {
|
||||
public static interface UpdatePredicatesFunc<K, V extends AbstractEntity, M> {
|
||||
MapModelCriteriaBuilder<K, V, M> apply(MapModelCriteriaBuilder<K, V, M> builder, Operator op, Object[] params);
|
||||
}
|
||||
|
||||
|
@ -40,12 +44,14 @@ public class MapModelCriteriaBuilder<K, V extends AbstractEntity<K>, M> implemen
|
|||
private final Predicate<? super K> keyFilter;
|
||||
private final Predicate<? super V> entityFilter;
|
||||
private final Map<SearchableModelField<M>, UpdatePredicatesFunc<K, V, M>> fieldPredicates;
|
||||
private final StringKeyConvertor<K> keyConvertor;
|
||||
|
||||
public MapModelCriteriaBuilder(Map<SearchableModelField<M>, UpdatePredicatesFunc<K, V, M>> fieldPredicates) {
|
||||
this(fieldPredicates, ALWAYS_TRUE, ALWAYS_TRUE);
|
||||
public MapModelCriteriaBuilder(StringKeyConvertor<K> keyConvertor, Map<SearchableModelField<M>, UpdatePredicatesFunc<K, V, M>> fieldPredicates) {
|
||||
this(keyConvertor, fieldPredicates, ALWAYS_TRUE, ALWAYS_TRUE);
|
||||
}
|
||||
|
||||
private MapModelCriteriaBuilder(Map<SearchableModelField<M>, UpdatePredicatesFunc<K, V, M>> fieldPredicates, Predicate<? super K> indexReadFilter, Predicate<? super V> sequentialReadFilter) {
|
||||
private MapModelCriteriaBuilder(StringKeyConvertor<K> keyConvertor, Map<SearchableModelField<M>, UpdatePredicatesFunc<K, V, M>> fieldPredicates, Predicate<? super K> indexReadFilter, Predicate<? super V> sequentialReadFilter) {
|
||||
this.keyConvertor = keyConvertor;
|
||||
this.fieldPredicates = fieldPredicates;
|
||||
this.keyFilter = indexReadFilter;
|
||||
this.entityFilter = sequentialReadFilter;
|
||||
|
@ -67,7 +73,7 @@ public class MapModelCriteriaBuilder<K, V extends AbstractEntity<K>, M> implemen
|
|||
public final MapModelCriteriaBuilder<K, V, M> and(ModelCriteriaBuilder<M>... builders) {
|
||||
Predicate<? super K> resIndexFilter = Stream.of(builders).map(MapModelCriteriaBuilder.class::cast).map(MapModelCriteriaBuilder::getKeyFilter).reduce(keyFilter, Predicate::and);
|
||||
Predicate<V> resEntityFilter = Stream.of(builders).map(MapModelCriteriaBuilder.class::cast).map(MapModelCriteriaBuilder::getEntityFilter).reduce(entityFilter, Predicate::and);
|
||||
return new MapModelCriteriaBuilder<>(fieldPredicates, resIndexFilter, resEntityFilter);
|
||||
return new MapModelCriteriaBuilder<>(keyConvertor, fieldPredicates, resIndexFilter, resEntityFilter);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
|
@ -77,6 +83,7 @@ public class MapModelCriteriaBuilder<K, V extends AbstractEntity<K>, M> implemen
|
|||
Predicate<? super K> resIndexFilter = Stream.of(builders).map(MapModelCriteriaBuilder.class::cast).map(MapModelCriteriaBuilder::getKeyFilter).reduce(ALWAYS_FALSE, Predicate::or);
|
||||
Predicate<V> resEntityFilter = Stream.of(builders).map(MapModelCriteriaBuilder.class::cast).map(MapModelCriteriaBuilder::getEntityFilter).reduce(ALWAYS_FALSE, Predicate::or);
|
||||
return new MapModelCriteriaBuilder<>(
|
||||
keyConvertor,
|
||||
fieldPredicates,
|
||||
v -> keyFilter.test(v) && resIndexFilter.test(v),
|
||||
v -> entityFilter.test(v) && resEntityFilter.test(v)
|
||||
|
@ -94,6 +101,7 @@ public class MapModelCriteriaBuilder<K, V extends AbstractEntity<K>, M> implemen
|
|||
Predicate<? super V> resEntityFilter = b.getEntityFilter() == ALWAYS_TRUE ? ALWAYS_TRUE : b.getEntityFilter().negate();
|
||||
|
||||
return new MapModelCriteriaBuilder<>(
|
||||
keyConvertor,
|
||||
fieldPredicates,
|
||||
v -> keyFilter.test(v) && resIndexFilter.test(v),
|
||||
v -> entityFilter.test(v) && resEntityFilter.test(v)
|
||||
|
@ -109,7 +117,7 @@ public class MapModelCriteriaBuilder<K, V extends AbstractEntity<K>, M> implemen
|
|||
}
|
||||
|
||||
protected MapModelCriteriaBuilder<K, V, M> idCompare(Operator op, Object[] values) {
|
||||
|
||||
Object[] convertedValues = convertValuesToKeyType(values);
|
||||
switch (op) {
|
||||
case LT:
|
||||
case LE:
|
||||
|
@ -120,12 +128,35 @@ public class MapModelCriteriaBuilder<K, V extends AbstractEntity<K>, M> implemen
|
|||
case EXISTS:
|
||||
case NOT_EXISTS:
|
||||
case IN:
|
||||
return new MapModelCriteriaBuilder<>(fieldPredicates, this.keyFilter.and(CriteriaOperator.predicateFor(op, values)), this.entityFilter);
|
||||
return new MapModelCriteriaBuilder<>(keyConvertor, fieldPredicates, this.keyFilter.and(CriteriaOperator.predicateFor(op, convertedValues)), this.entityFilter);
|
||||
default:
|
||||
throw new AssertionError("Invalid operator: " + op);
|
||||
}
|
||||
}
|
||||
|
||||
protected Object[] convertValuesToKeyType(Object[] values) {
|
||||
if (values == null) {
|
||||
return null;
|
||||
}
|
||||
Object[] res = new Object[values.length];
|
||||
for (int i = 0; i < values.length; i ++) {
|
||||
Object v = values[i];
|
||||
if (v instanceof String) {
|
||||
res[i] = keyConvertor.fromStringSafe((String) v);
|
||||
} else if (v instanceof Stream) {
|
||||
res[i] = ((Stream<?>) v).map(o -> (o instanceof String) ? keyConvertor.fromStringSafe((String) o) : o);
|
||||
} else if (v instanceof Collection) {
|
||||
res[i] = ((List<?>) v).stream().map(o -> (o instanceof String) ? keyConvertor.fromStringSafe((String) o) : o).collect(Collectors.toList());
|
||||
} else if (v == null) {
|
||||
res[i] = null;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown type: " + v);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
protected MapModelCriteriaBuilder<K, V, M> fieldCompare(Operator op, Function<V, ?> getter, Object[] values) {
|
||||
Predicate<Object> valueComparator = CriteriaOperator.predicateFor(op, values);
|
||||
return fieldCompare(valueComparator, getter);
|
||||
|
@ -139,6 +170,6 @@ public class MapModelCriteriaBuilder<K, V extends AbstractEntity<K>, M> implemen
|
|||
final Predicate<V> p = v -> valueComparator.test(getter.apply(v));
|
||||
resEntityFilter = p.and(entityFilter);
|
||||
}
|
||||
return new MapModelCriteriaBuilder<>(fieldPredicates, this.keyFilter, resEntityFilter);
|
||||
return new MapModelCriteriaBuilder<>(keyConvertor, fieldPredicates, this.keyFilter, resEntityFilter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.keycloak.models.map.storage.chm;
|
||||
|
||||
import org.keycloak.models.map.common.StringKeyConvertor;
|
||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
|
@ -24,7 +25,6 @@ import org.keycloak.models.map.storage.MapKeycloakTransaction;
|
|||
import org.keycloak.models.map.storage.ModelCriteriaBuilder;
|
||||
import org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator;
|
||||
import org.keycloak.models.map.storage.QueryParameters;
|
||||
import org.keycloak.models.map.storage.StringKeyConvertor;
|
||||
import org.keycloak.models.map.userSession.MapAuthenticatedClientSessionEntity;
|
||||
import org.keycloak.models.map.userSession.MapUserSessionEntity;
|
||||
import java.util.Set;
|
||||
|
@ -38,31 +38,29 @@ import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
|
|||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class UserSessionConcurrentHashMapStorage<K> extends ConcurrentHashMapStorage<K, MapUserSessionEntity<K>, UserSessionModel> {
|
||||
public class UserSessionConcurrentHashMapStorage<K> extends ConcurrentHashMapStorage<K, MapUserSessionEntity, UserSessionModel> {
|
||||
|
||||
private final ConcurrentHashMapStorage<K, MapAuthenticatedClientSessionEntity<K>, AuthenticatedClientSessionModel> clientSessionStore;
|
||||
private final ConcurrentHashMapStorage<K, MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionStore;
|
||||
|
||||
private class Transaction extends ConcurrentHashMapKeycloakTransaction<K, MapUserSessionEntity<K>, UserSessionModel> {
|
||||
private class Transaction extends ConcurrentHashMapKeycloakTransaction<K, MapUserSessionEntity, UserSessionModel> {
|
||||
|
||||
private final MapKeycloakTransaction<K, MapAuthenticatedClientSessionEntity<K>, AuthenticatedClientSessionModel> clientSessionTr;
|
||||
private final MapKeycloakTransaction<K, MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionTr;
|
||||
|
||||
public Transaction(MapKeycloakTransaction<K, MapAuthenticatedClientSessionEntity<K>, AuthenticatedClientSessionModel> clientSessionTr) {
|
||||
super(UserSessionConcurrentHashMapStorage.this);
|
||||
public Transaction(MapKeycloakTransaction<K, MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionTr, StringKeyConvertor<K> keyConvertor) {
|
||||
super(UserSessionConcurrentHashMapStorage.this, keyConvertor);
|
||||
this.clientSessionTr = clientSessionTr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long delete(QueryParameters<UserSessionModel> queryParameters) {
|
||||
ModelCriteriaBuilder<UserSessionModel> mcb = queryParameters.getModelCriteriaBuilder();
|
||||
|
||||
Set<K> ids = read(queryParameters).map(AbstractEntity::getId).collect(Collectors.toSet());
|
||||
Set<String> ids = read(queryParameters).map(AbstractEntity::getId).collect(Collectors.toSet());
|
||||
ModelCriteriaBuilder<AuthenticatedClientSessionModel> csMcb = clientSessionStore.createCriteriaBuilder().compare(AuthenticatedClientSessionModel.SearchableFields.USER_SESSION_ID, Operator.IN, ids);
|
||||
clientSessionTr.delete(withCriteria(csMcb));
|
||||
return super.delete(queryParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(K key) {
|
||||
public boolean delete(String key) {
|
||||
ModelCriteriaBuilder<AuthenticatedClientSessionModel> csMcb = clientSessionStore.createCriteriaBuilder().compare(AuthenticatedClientSessionModel.SearchableFields.USER_SESSION_ID, Operator.EQ, key);
|
||||
clientSessionTr.delete(withCriteria(csMcb));
|
||||
return super.delete(key);
|
||||
|
@ -71,7 +69,7 @@ public class UserSessionConcurrentHashMapStorage<K> extends ConcurrentHashMapSto
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public UserSessionConcurrentHashMapStorage(ConcurrentHashMapStorage<K, MapAuthenticatedClientSessionEntity<K>, AuthenticatedClientSessionModel> clientSessionStore,
|
||||
public UserSessionConcurrentHashMapStorage(ConcurrentHashMapStorage<K, MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionStore,
|
||||
StringKeyConvertor<K> keyConvertor) {
|
||||
super(UserSessionModel.class, keyConvertor);
|
||||
this.clientSessionStore = clientSessionStore;
|
||||
|
@ -79,8 +77,8 @@ public class UserSessionConcurrentHashMapStorage<K> extends ConcurrentHashMapSto
|
|||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public MapKeycloakTransaction<K, MapUserSessionEntity<K>, UserSessionModel> createTransaction(KeycloakSession session) {
|
||||
MapKeycloakTransaction<K, MapUserSessionEntity<K>, UserSessionModel> sessionTransaction = session.getAttribute("map-transaction-" + hashCode(), MapKeycloakTransaction.class);
|
||||
return sessionTransaction == null ? new Transaction(clientSessionStore.createTransaction(session)) : sessionTransaction;
|
||||
public MapKeycloakTransaction<K, MapUserSessionEntity, UserSessionModel> createTransaction(KeycloakSession session) {
|
||||
MapKeycloakTransaction<K, MapUserSessionEntity, UserSessionModel> sessionTransaction = session.getAttribute("map-transaction-" + hashCode(), MapKeycloakTransaction.class);
|
||||
return sessionTransaction == null ? new Transaction(clientSessionStore.createTransaction(session), clientSessionStore.getKeyConvertor()) : sessionTransaction;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,11 +36,16 @@ import java.util.Optional;
|
|||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
public abstract class MapUserAdapter<K> extends AbstractUserModel<MapUserEntity<K>> {
|
||||
public MapUserAdapter(KeycloakSession session, RealmModel realm, MapUserEntity<K> entity) {
|
||||
public abstract class MapUserAdapter extends AbstractUserModel<MapUserEntity> {
|
||||
public MapUserAdapter(KeycloakSession session, RealmModel realm, MapUserEntity entity) {
|
||||
super(session, realm, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return entity.getUsername();
|
||||
|
|
|
@ -40,9 +40,9 @@ import java.util.stream.Stream;
|
|||
*
|
||||
* @author mhajas
|
||||
*/
|
||||
public class MapUserEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
||||
public class MapUserEntity implements AbstractEntity, UpdatableEntity {
|
||||
|
||||
private final K id;
|
||||
private final String id;
|
||||
private final String realmId;
|
||||
|
||||
private String username;
|
||||
|
@ -76,8 +76,7 @@ public class MapUserEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
|||
this.realmId = null;
|
||||
}
|
||||
|
||||
public MapUserEntity(K id, String realmId) {
|
||||
Objects.requireNonNull(id, "id");
|
||||
public MapUserEntity(String id, String realmId) {
|
||||
Objects.requireNonNull(realmId, "realmId");
|
||||
|
||||
this.id = id;
|
||||
|
@ -85,7 +84,7 @@ public class MapUserEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,24 +76,19 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(MapUserProvider.class);
|
||||
private final KeycloakSession session;
|
||||
final MapKeycloakTransaction<K, MapUserEntity<K>, UserModel> tx;
|
||||
private final MapStorage<K, MapUserEntity<K>, UserModel> userStore;
|
||||
final MapKeycloakTransaction<K, MapUserEntity, UserModel> tx;
|
||||
private final MapStorage<K, MapUserEntity, UserModel> userStore;
|
||||
|
||||
public MapUserProvider(KeycloakSession session, MapStorage<K, MapUserEntity<K>, UserModel> store) {
|
||||
public MapUserProvider(KeycloakSession session, MapStorage<K, MapUserEntity, UserModel> store) {
|
||||
this.session = session;
|
||||
this.userStore = store;
|
||||
this.tx = userStore.createTransaction(session);
|
||||
session.getTransactionManager().enlist(tx);
|
||||
}
|
||||
|
||||
private Function<MapUserEntity<K>, UserModel> entityToAdapterFunc(RealmModel realm) {
|
||||
private Function<MapUserEntity, UserModel> entityToAdapterFunc(RealmModel realm) {
|
||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||
return origEntity -> new MapUserAdapter<K>(session, realm, origEntity) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return userStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
|
||||
return origEntity -> new MapUserAdapter(session, realm, origEntity) {
|
||||
@Override
|
||||
public boolean checkEmailUniqueness(RealmModel realm, String email) {
|
||||
return getUserByEmail(realm, email) != null;
|
||||
|
@ -106,7 +101,7 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
};
|
||||
}
|
||||
|
||||
private Predicate<MapUserEntity<K>> entityRealmFilter(RealmModel realm) {
|
||||
private Predicate<MapUserEntity> entityRealmFilter(RealmModel realm) {
|
||||
if (realm == null || realm.getId() == null) {
|
||||
return c -> false;
|
||||
}
|
||||
|
@ -118,26 +113,26 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
return new ModelException("Specified user doesn't exist.");
|
||||
}
|
||||
|
||||
private Optional<MapUserEntity<K>> getEntityById(RealmModel realm, String id) {
|
||||
private Optional<MapUserEntity> getEntityById(RealmModel realm, String id) {
|
||||
try {
|
||||
return getEntityById(realm, userStore.getKeyConvertor().fromString(id));
|
||||
MapUserEntity mapUserEntity = tx.read(id);
|
||||
if (mapUserEntity != null && entityRealmFilter(realm).test(mapUserEntity)) {
|
||||
return Optional.of(mapUserEntity);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private MapUserEntity<K> getEntityByIdOrThrow(RealmModel realm, String id) {
|
||||
private MapUserEntity getEntityByIdOrThrow(RealmModel realm, String id) {
|
||||
return getEntityById(realm, id)
|
||||
.orElseThrow(this::userDoesntExistException);
|
||||
}
|
||||
|
||||
private Optional<MapUserEntity<K>> getEntityById(RealmModel realm, K id) {
|
||||
MapUserEntity<K> mapUserEntity = tx.read(id);
|
||||
if (mapUserEntity != null && entityRealmFilter(realm).test(mapUserEntity)) {
|
||||
return Optional.of(mapUserEntity);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
private Optional<MapUserEntity> getRegisteredEntityById(RealmModel realm, String id) {
|
||||
return getEntityById(realm, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -248,7 +243,7 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
public void updateConsent(RealmModel realm, String userId, UserConsentModel consent) {
|
||||
LOG.tracef("updateConsent(%s, %s, %s)%s", realm, userId, consent, getShortStackTrace());
|
||||
|
||||
MapUserEntity<K> user = getEntityByIdOrThrow(realm, userId);
|
||||
MapUserEntity user = getEntityByIdOrThrow(realm, userId);
|
||||
UserConsentEntity userConsentEntity = user.getUserConsent(consent.getClient().getId());
|
||||
if (userConsentEntity == null) {
|
||||
throw new ModelException("Consent not found for client [" + consent.getClient().getId() + "] and user [" + userId + "]");
|
||||
|
@ -319,13 +314,11 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
throw new ModelDuplicateException("User with username '" + username + "' in realm " + realm.getName() + " already exists" );
|
||||
}
|
||||
|
||||
final K entityId = id == null ? userStore.getKeyConvertor().yieldNewUniqueKey() : userStore.getKeyConvertor().fromString(id);
|
||||
|
||||
if (tx.read(entityId) != null) {
|
||||
throw new ModelDuplicateException("User exists: " + entityId);
|
||||
if (tx.read(id) != null) {
|
||||
throw new ModelDuplicateException("User exists: " + id);
|
||||
}
|
||||
|
||||
MapUserEntity<K> entity = new MapUserEntity<>(entityId, realm.getId());
|
||||
MapUserEntity entity = new MapUserEntity(id, realm.getId());
|
||||
entity.setUsername(username.toLowerCase());
|
||||
entity.setCreatedTimestamp(Time.currentTimeMillis());
|
||||
|
||||
|
@ -376,7 +369,7 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
|
||||
.compare(SearchableFields.FEDERATION_LINK, Operator.EQ, storageProviderId);
|
||||
|
||||
try (Stream<MapUserEntity<K>> s = tx.read(withCriteria(mcb))) {
|
||||
try (Stream<MapUserEntity> s = tx.read(withCriteria(mcb))) {
|
||||
s.forEach(userEntity -> userEntity.setFederationLink(null));
|
||||
}
|
||||
}
|
||||
|
@ -389,7 +382,7 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
|
||||
.compare(SearchableFields.ASSIGNED_ROLE, Operator.EQ, roleId);
|
||||
|
||||
try (Stream<MapUserEntity<K>> s = tx.read(withCriteria(mcb))) {
|
||||
try (Stream<MapUserEntity> s = tx.read(withCriteria(mcb))) {
|
||||
s.forEach(userEntity -> userEntity.removeRolesMembership(roleId));
|
||||
}
|
||||
}
|
||||
|
@ -402,7 +395,7 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
|
||||
.compare(SearchableFields.ASSIGNED_GROUP, Operator.EQ, groupId);
|
||||
|
||||
try (Stream<MapUserEntity<K>> s = tx.read(withCriteria(mcb))) {
|
||||
try (Stream<MapUserEntity> s = tx.read(withCriteria(mcb))) {
|
||||
s.forEach(userEntity -> userEntity.removeGroupsMembership(groupId));
|
||||
}
|
||||
}
|
||||
|
@ -415,7 +408,7 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
|
||||
.compare(SearchableFields.CONSENT_FOR_CLIENT, Operator.EQ, clientId);
|
||||
|
||||
try (Stream<MapUserEntity<K>> s = tx.read(withCriteria(mcb))) {
|
||||
try (Stream<MapUserEntity> s = tx.read(withCriteria(mcb))) {
|
||||
s.forEach(userEntity -> userEntity.removeUserConsent(clientId));
|
||||
}
|
||||
}
|
||||
|
@ -434,7 +427,7 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
.compare(SearchableFields.REALM_ID, Operator.EQ, clientScope.getRealm().getId())
|
||||
.compare(SearchableFields.CONSENT_WITH_CLIENT_SCOPE, Operator.EQ, clientScopeId);
|
||||
|
||||
try (Stream<MapUserEntity<K>> s = tx.read(withCriteria(mcb))) {
|
||||
try (Stream<MapUserEntity> s = tx.read(withCriteria(mcb))) {
|
||||
s.flatMap(MapUserEntity::getUserConsents)
|
||||
.forEach(consent -> consent.removeGrantedClientScopesIds(clientScopeId));
|
||||
}
|
||||
|
@ -452,14 +445,14 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
|
||||
.compare(SearchableFields.CONSENT_CLIENT_FEDERATION_LINK, Operator.EQ, componentId);
|
||||
|
||||
try (Stream<MapUserEntity<K>> s = tx.read(withCriteria(mcb))) {
|
||||
try (Stream<MapUserEntity> s = tx.read(withCriteria(mcb))) {
|
||||
String providerIdS = new StorageId(componentId, "").getId();
|
||||
s.forEach(removeConsentsForExternalClient(providerIdS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Consumer<MapUserEntity<K>> removeConsentsForExternalClient(String idPrefix) {
|
||||
private Consumer<MapUserEntity> removeConsentsForExternalClient(String idPrefix) {
|
||||
return userEntity -> {
|
||||
List<String> consentClientIds = userEntity.getUserConsents()
|
||||
.map(UserConsentEntity::getClientId)
|
||||
|
@ -479,7 +472,7 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
ModelCriteriaBuilder<UserModel> mcb = userStore.createCriteriaBuilder()
|
||||
.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId());
|
||||
|
||||
try (Stream<MapUserEntity<K>> s = tx.read(withCriteria(mcb))) {
|
||||
try (Stream<MapUserEntity> s = tx.read(withCriteria(mcb))) {
|
||||
s.forEach(entity -> entity.addRolesMembership(roleId));
|
||||
}
|
||||
}
|
||||
|
@ -498,7 +491,7 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
|
||||
.compare(SearchableFields.USERNAME, Operator.ILIKE, username);
|
||||
|
||||
try (Stream<MapUserEntity<K>> s = tx.read(withCriteria(mcb))) {
|
||||
try (Stream<MapUserEntity> s = tx.read(withCriteria(mcb))) {
|
||||
return s.findFirst()
|
||||
.map(entityToAdapterFunc(realm)).orElse(null);
|
||||
}
|
||||
|
@ -511,7 +504,7 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
|
||||
.compare(SearchableFields.EMAIL, Operator.EQ, email);
|
||||
|
||||
List<MapUserEntity<K>> usersWithEmail = tx.read(withCriteria(mcb))
|
||||
List<MapUserEntity> usersWithEmail = tx.read(withCriteria(mcb))
|
||||
.filter(userEntity -> Objects.equals(userEntity.getEmail(), email))
|
||||
.collect(Collectors.toList());
|
||||
if (usersWithEmail.isEmpty()) return null;
|
||||
|
@ -522,7 +515,7 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
throw new ModelDuplicateException("Multiple users with email '" + email + "' exist in Keycloak.");
|
||||
}
|
||||
|
||||
MapUserEntity<K> userEntity = usersWithEmail.get(0);
|
||||
MapUserEntity userEntity = usersWithEmail.get(0);
|
||||
|
||||
if (!realm.isDuplicateEmailsAllowed()) {
|
||||
if (userEntity.getEmail() != null && !userEntity.getEmail().equals(userEntity.getEmailConstraint())) {
|
||||
|
@ -709,9 +702,9 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
@Override
|
||||
public boolean removeUser(RealmModel realm, UserModel user) {
|
||||
String userId = user.getId();
|
||||
Optional<MapUserEntity<K>> userById = getEntityById(realm, userId);
|
||||
Optional<MapUserEntity> userById = getEntityById(realm, userId);
|
||||
if (userById.isPresent()) {
|
||||
tx.delete(userStore.getKeyConvertor().fromString(userId));
|
||||
tx.delete(userId);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -735,7 +728,7 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
.ifPresent(updateCredential(cred));
|
||||
}
|
||||
|
||||
private Consumer<MapUserEntity<K>> updateCredential(CredentialModel credentialModel) {
|
||||
private Consumer<MapUserEntity> updateCredential(CredentialModel credentialModel) {
|
||||
return user -> {
|
||||
UserCredentialEntity credentialEntity = user.getCredential(credentialModel.getId());
|
||||
if (credentialEntity == null) return;
|
||||
|
@ -804,7 +797,7 @@ public class MapUserProvider<K> implements UserProvider.Streams, UserCredentialS
|
|||
public boolean moveCredentialTo(RealmModel realm, UserModel user, String id, String newPreviousCredentialId) {
|
||||
LOG.tracef("moveCredentialTo(%s, %s, %s, %s)%s", realm, user.getId(), id, newPreviousCredentialId, getShortStackTrace());
|
||||
String userId = user.getId();
|
||||
MapUserEntity<K> userEntity = getEntityById(realm, userId).orElse(null);
|
||||
MapUserEntity userEntity = getEntityById(realm, userId).orElse(null);
|
||||
if (userEntity == null) {
|
||||
LOG.warnf("User with id: [%s] not found", userId);
|
||||
return false;
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
|||
*
|
||||
* @author mhajas
|
||||
*/
|
||||
public class MapUserProviderFactory<K> extends AbstractMapProviderFactory<UserProvider, K, MapUserEntity<K>, UserModel> implements UserProviderFactory {
|
||||
public class MapUserProviderFactory<K> extends AbstractMapProviderFactory<UserProvider, K, MapUserEntity, UserModel> implements UserProviderFactory {
|
||||
|
||||
public MapUserProviderFactory() {
|
||||
super(UserModel.class);
|
||||
|
|
|
@ -28,15 +28,15 @@ import java.util.Objects;
|
|||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public abstract class AbstractAuthenticatedClientSessionModel<K> implements AuthenticatedClientSessionModel {
|
||||
public abstract class AbstractAuthenticatedClientSessionModel implements AuthenticatedClientSessionModel {
|
||||
protected final KeycloakSession session;
|
||||
protected final RealmModel realm;
|
||||
protected ClientModel client;
|
||||
protected UserSessionModel userSession;
|
||||
protected final MapAuthenticatedClientSessionEntity<K> entity;
|
||||
protected final MapAuthenticatedClientSessionEntity entity;
|
||||
|
||||
public AbstractAuthenticatedClientSessionModel(KeycloakSession session, RealmModel realm, ClientModel client,
|
||||
UserSessionModel userSession, MapAuthenticatedClientSessionEntity<K> entity) {
|
||||
UserSessionModel userSession, MapAuthenticatedClientSessionEntity entity) {
|
||||
Objects.requireNonNull(entity, "entity");
|
||||
Objects.requireNonNull(realm, "realm");
|
||||
Objects.requireNonNull(client, "client");
|
||||
|
|
|
@ -29,9 +29,9 @@ import java.util.Objects;
|
|||
public abstract class AbstractUserSessionModel<K> implements UserSessionModel {
|
||||
protected final KeycloakSession session;
|
||||
protected final RealmModel realm;
|
||||
protected final MapUserSessionEntity<K> entity;
|
||||
protected final MapUserSessionEntity entity;
|
||||
|
||||
public AbstractUserSessionModel(KeycloakSession session, RealmModel realm, MapUserSessionEntity<K> entity) {
|
||||
public AbstractUserSessionModel(KeycloakSession session, RealmModel realm, MapUserSessionEntity entity) {
|
||||
Objects.requireNonNull(entity, "entity");
|
||||
Objects.requireNonNull(realm, "realm");
|
||||
|
||||
|
|
|
@ -26,13 +26,18 @@ import java.util.Map;
|
|||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public abstract class MapAuthenticatedClientSessionAdapter<K> extends AbstractAuthenticatedClientSessionModel<K> {
|
||||
public abstract class MapAuthenticatedClientSessionAdapter extends AbstractAuthenticatedClientSessionModel {
|
||||
|
||||
public MapAuthenticatedClientSessionAdapter(KeycloakSession session, RealmModel realm, ClientModel client,
|
||||
UserSessionModel userSession, MapAuthenticatedClientSessionEntity<K> entity) {
|
||||
UserSessionModel userSession, MapAuthenticatedClientSessionEntity entity) {
|
||||
super(session, realm, client, userSession, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimestamp() {
|
||||
return entity.getTimestamp();
|
||||
|
|
|
@ -27,9 +27,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public class MapAuthenticatedClientSessionEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
||||
public class MapAuthenticatedClientSessionEntity implements AbstractEntity, UpdatableEntity {
|
||||
|
||||
private K id;
|
||||
private String id;
|
||||
private String userSessionId;
|
||||
private String realmId;
|
||||
private String clientId;
|
||||
|
@ -57,8 +57,7 @@ public class MapAuthenticatedClientSessionEntity<K> implements AbstractEntity<K>
|
|||
this.realmId = null;
|
||||
}
|
||||
|
||||
public MapAuthenticatedClientSessionEntity(K id, String userSessionId, String realmId, String clientId, boolean offline) {
|
||||
Objects.requireNonNull(id, "id");
|
||||
public MapAuthenticatedClientSessionEntity(String id, String userSessionId, String realmId, String clientId, boolean offline) {
|
||||
Objects.requireNonNull(userSessionId, "userSessionId");
|
||||
Objects.requireNonNull(realmId, "realmId");
|
||||
Objects.requireNonNull(clientId, "clientId");
|
||||
|
@ -72,7 +71,7 @@ public class MapAuthenticatedClientSessionEntity<K> implements AbstractEntity<K>
|
|||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,18 +30,22 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public abstract class MapUserSessionAdapter<K> extends AbstractUserSessionModel<K> {
|
||||
public abstract class MapUserSessionAdapter extends AbstractUserSessionModel {
|
||||
|
||||
public MapUserSessionAdapter(KeycloakSession session, RealmModel realm, MapUserSessionEntity<K> entity) {
|
||||
public MapUserSessionAdapter(KeycloakSession session, RealmModel realm, MapUserSessionEntity entity) {
|
||||
super(session, realm, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel getRealm() {
|
||||
return realm;
|
||||
|
|
|
@ -30,8 +30,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
/**
|
||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||
*/
|
||||
public class MapUserSessionEntity<K> implements AbstractEntity<K>, UpdatableEntity {
|
||||
private K id;
|
||||
public class MapUserSessionEntity implements AbstractEntity, UpdatableEntity {
|
||||
private String id;
|
||||
|
||||
private String realmId;
|
||||
|
||||
|
@ -74,15 +74,14 @@ public class MapUserSessionEntity<K> implements AbstractEntity<K>, UpdatableEnti
|
|||
this.realmId = null;
|
||||
}
|
||||
|
||||
public MapUserSessionEntity(K id, String realmId) {
|
||||
Objects.requireNonNull(id, "id");
|
||||
public MapUserSessionEntity(String id, String realmId) {
|
||||
Objects.requireNonNull(realmId, "realmId");
|
||||
|
||||
this.id = id;
|
||||
this.realmId = realmId;
|
||||
}
|
||||
|
||||
public MapUserSessionEntity(K id, RealmModel realm, UserModel user, String loginUsername, String ipAddress,
|
||||
public MapUserSessionEntity(String id, RealmModel realm, UserModel user, String loginUsername, String ipAddress,
|
||||
String authMethod, boolean rememberMe, String brokerSessionId, String brokerUserId,
|
||||
boolean offline) {
|
||||
this.id = id;
|
||||
|
@ -100,7 +99,7 @@ public class MapUserSessionEntity<K> implements AbstractEntity<K>, UpdatableEnti
|
|||
}
|
||||
|
||||
@Override
|
||||
public K getId() {
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,18 +57,18 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(MapUserSessionProvider.class);
|
||||
private final KeycloakSession session;
|
||||
protected final MapKeycloakTransaction<UK, MapUserSessionEntity<UK>, UserSessionModel> userSessionTx;
|
||||
protected final MapKeycloakTransaction<CK, MapAuthenticatedClientSessionEntity<CK>, AuthenticatedClientSessionModel> clientSessionTx;
|
||||
private final MapStorage<UK, MapUserSessionEntity<UK>, UserSessionModel> userSessionStore;
|
||||
private final MapStorage<CK, MapAuthenticatedClientSessionEntity<CK>, AuthenticatedClientSessionModel> clientSessionStore;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Storage for transient user sessions which lifespan is limited to one request.
|
||||
*/
|
||||
private final Map<UK, MapUserSessionEntity<UK>> transientUserSessions = new HashMap<>();
|
||||
private final Map<String, MapUserSessionEntity> transientUserSessions = new HashMap<>();
|
||||
|
||||
public MapUserSessionProvider(KeycloakSession session, MapStorage<UK, MapUserSessionEntity<UK>, UserSessionModel> userSessionStore,
|
||||
MapStorage<CK, MapAuthenticatedClientSessionEntity<CK>, AuthenticatedClientSessionModel> clientSessionStore) {
|
||||
public MapUserSessionProvider(KeycloakSession session, MapStorage<UK, MapUserSessionEntity, UserSessionModel> userSessionStore,
|
||||
MapStorage<CK, MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientSessionStore) {
|
||||
this.session = session;
|
||||
this.userSessionStore = userSessionStore;
|
||||
this.clientSessionStore = clientSessionStore;
|
||||
|
@ -79,7 +79,7 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
session.getTransactionManager().enlistAfterCompletion(clientSessionTx);
|
||||
}
|
||||
|
||||
private Function<MapUserSessionEntity<UK>, UserSessionModel> userEntityToAdapterFunc(RealmModel realm) {
|
||||
private Function<MapUserSessionEntity, UserSessionModel> userEntityToAdapterFunc(RealmModel realm) {
|
||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||
return (origEntity) -> {
|
||||
if (origEntity.getExpiration() <= Time.currentTime()) {
|
||||
|
@ -89,12 +89,7 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
userSessionTx.delete(origEntity.getId());
|
||||
return null;
|
||||
} else {
|
||||
return new MapUserSessionAdapter<UK>(session, realm, origEntity) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return userSessionStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
|
||||
return new MapUserSessionAdapter(session, realm, origEntity) {
|
||||
@Override
|
||||
public void removeAuthenticatedClientSessions(Collection<String> removedClientUKS) {
|
||||
removedClientUKS.forEach(entity::removeAuthenticatedClientSession);
|
||||
|
@ -111,7 +106,7 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
};
|
||||
}
|
||||
|
||||
private Function<MapAuthenticatedClientSessionEntity<CK>, AuthenticatedClientSessionModel> clientEntityToAdapterFunc(RealmModel realm,
|
||||
private Function<MapAuthenticatedClientSessionEntity, AuthenticatedClientSessionModel> clientEntityToAdapterFunc(RealmModel realm,
|
||||
ClientModel client,
|
||||
UserSessionModel userSession) {
|
||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||
|
@ -121,12 +116,7 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
clientSessionTx.delete(origEntity.getId());
|
||||
return null;
|
||||
} else {
|
||||
return new MapAuthenticatedClientSessionAdapter<CK>(session, realm, client, userSession, origEntity) {
|
||||
@Override
|
||||
public String getId() {
|
||||
return clientSessionStore.getKeyConvertor().keyToString(entity.getId());
|
||||
}
|
||||
|
||||
return new MapAuthenticatedClientSessionAdapter(session, realm, client, userSession, origEntity) {
|
||||
@Override
|
||||
public void detachFromUserSession() {
|
||||
this.userSession = null;
|
||||
|
@ -152,8 +142,8 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
|
||||
@Override
|
||||
public AuthenticatedClientSessionModel createClientSession(RealmModel realm, ClientModel client, UserSessionModel userSession) {
|
||||
MapAuthenticatedClientSessionEntity<CK> entity =
|
||||
new MapAuthenticatedClientSessionEntity<>(clientSessionStore.getKeyConvertor().yieldNewUniqueKey(), userSession.getId(), realm.getId(), client.getId(), false);
|
||||
MapAuthenticatedClientSessionEntity entity =
|
||||
new MapAuthenticatedClientSessionEntity(null, userSession.getId(), realm.getId(), client.getId(), false);
|
||||
entity.getNotes().put(AuthenticatedClientSessionModel.STARTED_AT_NOTE, String.valueOf(entity.getTimestamp()));
|
||||
setClientSessionExpiration(entity, realm, client);
|
||||
|
||||
|
@ -161,13 +151,13 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
|
||||
entity = clientSessionTx.create(entity);
|
||||
|
||||
MapUserSessionEntity<UK> userSessionEntity = getUserSessionById(userSessionStore.getKeyConvertor().fromString(userSession.getId()));
|
||||
MapUserSessionEntity userSessionEntity = getUserSessionById(userSession.getId());
|
||||
|
||||
if (userSessionEntity == null) {
|
||||
throw new IllegalStateException("User session entity does not exist: " + userSession.getId());
|
||||
}
|
||||
|
||||
userSessionEntity.addAuthenticatedClientSession(client.getId(), clientSessionStore.getKeyConvertor().keyToString(entity.getId()));
|
||||
userSessionEntity.addAuthenticatedClientSession(client.getId(), entity.getId());
|
||||
|
||||
return clientEntityToAdapterFunc(realm, client, userSession).apply(entity);
|
||||
}
|
||||
|
@ -184,9 +174,8 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
return null;
|
||||
}
|
||||
|
||||
CK ck = clientSessionStore.getKeyConvertor().fromStringSafe(clientSessionId);
|
||||
ModelCriteriaBuilder<AuthenticatedClientSessionModel> mcb = clientSessionStore.createCriteriaBuilder()
|
||||
.compare(AuthenticatedClientSessionModel.SearchableFields.ID, ModelCriteriaBuilder.Operator.EQ, ck)
|
||||
.compare(AuthenticatedClientSessionModel.SearchableFields.ID, ModelCriteriaBuilder.Operator.EQ, clientSessionId)
|
||||
.compare(AuthenticatedClientSessionModel.SearchableFields.USER_SESSION_ID, ModelCriteriaBuilder.Operator.EQ, userSession.getId())
|
||||
.compare(AuthenticatedClientSessionModel.SearchableFields.REALM_ID, ModelCriteriaBuilder.Operator.EQ, userSession.getRealm().getId())
|
||||
.compare(AuthenticatedClientSessionModel.SearchableFields.CLIENT_ID, ModelCriteriaBuilder.Operator.EQ, client.getId())
|
||||
|
@ -209,16 +198,14 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
public UserSessionModel createUserSession(String id, RealmModel realm, UserModel user, String loginUsername,
|
||||
String ipAddress, String authMethod, boolean rememberMe, String brokerSessionId,
|
||||
String brokerUserId, UserSessionModel.SessionPersistenceState persistenceState) {
|
||||
final UK entityId = id == null ? userSessionStore.getKeyConvertor().yieldNewUniqueKey(): userSessionStore.getKeyConvertor().fromString(id);
|
||||
|
||||
LOG.tracef("createUserSession(%s, %s, %s, %s)%s", id, realm, loginUsername, persistenceState, getShortStackTrace());
|
||||
|
||||
MapUserSessionEntity<UK> entity = new MapUserSessionEntity<>(entityId, realm, user, loginUsername, ipAddress, authMethod, rememberMe, brokerSessionId, brokerUserId, false);
|
||||
MapUserSessionEntity entity = new MapUserSessionEntity(id, realm, user, loginUsername, ipAddress, authMethod, rememberMe, brokerSessionId, brokerUserId, false);
|
||||
entity.setPersistenceState(persistenceState);
|
||||
setUserSessionExpiration(entity, realm);
|
||||
|
||||
if (Objects.equals(persistenceState, TRANSIENT)) {
|
||||
transientUserSessions.put(entityId, entity);
|
||||
transientUserSessions.put(entity.getId(), entity);
|
||||
} else {
|
||||
if (userSessionTx.read(entity.getId()) != null) {
|
||||
throw new ModelDuplicateException("User session exists: " + entity.getId());
|
||||
|
@ -242,18 +229,13 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
|
||||
LOG.tracef("getUserSession(%s, %s)%s", realm, id, getShortStackTrace());
|
||||
|
||||
UK uuid = userSessionStore.getKeyConvertor().fromStringSafe(id);
|
||||
if (uuid == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MapUserSessionEntity<UK> userSessionEntity = transientUserSessions.get(uuid);
|
||||
MapUserSessionEntity userSessionEntity = transientUserSessions.get(id);
|
||||
if (userSessionEntity != null) {
|
||||
return userEntityToAdapterFunc(realm).apply(userSessionEntity);
|
||||
}
|
||||
|
||||
ModelCriteriaBuilder<UserSessionModel> mcb = realmAndOfflineCriteriaBuilder(realm, false)
|
||||
.compare(UserSessionModel.SearchableFields.ID, ModelCriteriaBuilder.Operator.EQ, uuid);
|
||||
.compare(UserSessionModel.SearchableFields.ID, ModelCriteriaBuilder.Operator.EQ, id);
|
||||
|
||||
return userSessionTx.read(withCriteria(mcb))
|
||||
.findFirst()
|
||||
|
@ -374,9 +356,8 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
public void removeUserSession(RealmModel realm, UserSessionModel session) {
|
||||
Objects.requireNonNull(session, "The provided user session can't be null!");
|
||||
|
||||
UK uk = userSessionStore.getKeyConvertor().fromString(session.getId());
|
||||
ModelCriteriaBuilder<UserSessionModel> mcb = realmAndOfflineCriteriaBuilder(realm, false)
|
||||
.compare(UserSessionModel.SearchableFields.ID, ModelCriteriaBuilder.Operator.EQ, uk);
|
||||
.compare(UserSessionModel.SearchableFields.ID, ModelCriteriaBuilder.Operator.EQ, session.getId());
|
||||
|
||||
LOG.tracef("removeUserSession(%s, %s)%s", realm, session, getShortStackTrace());
|
||||
|
||||
|
@ -429,7 +410,7 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
public UserSessionModel createOfflineUserSession(UserSessionModel userSession) {
|
||||
LOG.tracef("createOfflineUserSession(%s)%s", userSession, getShortStackTrace());
|
||||
|
||||
MapUserSessionEntity<UK> offlineUserSession = createUserSessionEntityInstance(userSession, true);
|
||||
MapUserSessionEntity offlineUserSession = createUserSessionEntityInstance(userSession, true);
|
||||
|
||||
// set a reference for the offline user session to the original online user session
|
||||
userSession.setNote(CORRESPONDING_SESSION_ID, offlineUserSession.getId().toString());
|
||||
|
@ -462,9 +443,9 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
|
||||
ModelCriteriaBuilder<UserSessionModel> mcb;
|
||||
if (userSession.isOffline()) {
|
||||
userSessionTx.delete(userSessionStore.getKeyConvertor().fromString(userSession.getId()));
|
||||
userSessionTx.delete(userSession.getId());
|
||||
} else if (userSession.getNote(CORRESPONDING_SESSION_ID) != null) {
|
||||
UK uk = userSessionStore.getKeyConvertor().fromString(userSession.getNote(CORRESPONDING_SESSION_ID));
|
||||
String uk = userSession.getNote(CORRESPONDING_SESSION_ID);
|
||||
mcb = realmAndOfflineCriteriaBuilder(realm, true)
|
||||
.compare(UserSessionModel.SearchableFields.ID, ModelCriteriaBuilder.Operator.EQ, uk);
|
||||
userSessionTx.delete(withCriteria(mcb));
|
||||
|
@ -477,15 +458,15 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
UserSessionModel offlineUserSession) {
|
||||
LOG.tracef("createOfflineClientSession(%s, %s)%s", clientSession, offlineUserSession, getShortStackTrace());
|
||||
|
||||
MapAuthenticatedClientSessionEntity<CK> clientSessionEntity = createAuthenticatedClientSessionInstance(clientSession, offlineUserSession, true);
|
||||
MapAuthenticatedClientSessionEntity clientSessionEntity = createAuthenticatedClientSessionInstance(clientSession, offlineUserSession, true);
|
||||
int currentTime = Time.currentTime();
|
||||
clientSessionEntity.getNotes().put(AuthenticatedClientSessionModel.STARTED_AT_NOTE, String.valueOf(currentTime));
|
||||
clientSessionEntity.setTimestamp(currentTime);
|
||||
setClientSessionExpiration(clientSessionEntity, clientSession.getRealm(), clientSession.getClient());
|
||||
|
||||
Optional<MapUserSessionEntity<UK>> userSessionEntity = getOfflineUserSessionEntityStream(clientSession.getRealm(), offlineUserSession.getId()).findFirst();
|
||||
Optional<MapUserSessionEntity> userSessionEntity = getOfflineUserSessionEntityStream(clientSession.getRealm(), offlineUserSession.getId()).findFirst();
|
||||
if (userSessionEntity.isPresent()) {
|
||||
userSessionEntity.get().addAuthenticatedClientSession(clientSession.getClient().getId(), clientSessionStore.getKeyConvertor().keyToString(clientSessionEntity.getId()));
|
||||
userSessionEntity.get().addAuthenticatedClientSession(clientSession.getClient().getId(), clientSessionEntity.getId());
|
||||
}
|
||||
|
||||
clientSessionEntity = clientSessionTx.create(clientSessionEntity);
|
||||
|
@ -563,17 +544,17 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
|
||||
persistentUserSessions.stream()
|
||||
.map(pus -> {
|
||||
MapUserSessionEntity<UK> userSessionEntity = new MapUserSessionEntity<UK>(userSessionStore.getKeyConvertor().yieldNewUniqueKey(), pus.getRealm(), pus.getUser(),
|
||||
MapUserSessionEntity userSessionEntity = new MapUserSessionEntity(null, pus.getRealm(), pus.getUser(),
|
||||
pus.getLoginUsername(), pus.getIpAddress(), pus.getAuthMethod(),
|
||||
pus.isRememberMe(), pus.getBrokerSessionId(), pus.getBrokerUserId(), offline);
|
||||
|
||||
for (Map.Entry<String, AuthenticatedClientSessionModel> entry : pus.getAuthenticatedClientSessions().entrySet()) {
|
||||
MapAuthenticatedClientSessionEntity<CK> clientSession = createAuthenticatedClientSessionInstance(entry.getValue(), entry.getValue().getUserSession(), offline);
|
||||
MapAuthenticatedClientSessionEntity clientSession = createAuthenticatedClientSessionInstance(entry.getValue(), entry.getValue().getUserSession(), offline);
|
||||
|
||||
// Update timestamp to same value as userSession. LastSessionRefresh of userSession from DB will have correct value
|
||||
clientSession.setTimestamp(userSessionEntity.getLastSessionRefresh());
|
||||
|
||||
userSessionEntity.addAuthenticatedClientSession(entry.getKey(), clientSessionStore.getKeyConvertor().keyToString(clientSession.getId()));
|
||||
userSessionEntity.addAuthenticatedClientSession(entry.getKey(), clientSession.getId());
|
||||
|
||||
clientSession = clientSessionTx.create(clientSession);
|
||||
}
|
||||
|
@ -588,19 +569,18 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
|
||||
}
|
||||
|
||||
private Stream<MapUserSessionEntity<UK>> getOfflineUserSessionEntityStream(RealmModel realm, String userSessionId) {
|
||||
UK uuid = userSessionStore.getKeyConvertor().fromStringSafe(userSessionId);
|
||||
if (uuid == null) {
|
||||
private Stream<MapUserSessionEntity> getOfflineUserSessionEntityStream(RealmModel realm, String userSessionId) {
|
||||
if (userSessionId == null) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
// first get a user entity by ID
|
||||
ModelCriteriaBuilder<UserSessionModel> mcb = userSessionStore.createCriteriaBuilder()
|
||||
.compare(UserSessionModel.SearchableFields.REALM_ID, ModelCriteriaBuilder.Operator.EQ, realm.getId())
|
||||
.compare(UserSessionModel.SearchableFields.ID, ModelCriteriaBuilder.Operator.EQ, uuid);
|
||||
.compare(UserSessionModel.SearchableFields.ID, ModelCriteriaBuilder.Operator.EQ, userSessionId);
|
||||
|
||||
// check if it's an offline user session
|
||||
MapUserSessionEntity<UK> userSessionEntity = userSessionTx.read(withCriteria(mcb)).findFirst().orElse(null);
|
||||
MapUserSessionEntity userSessionEntity = userSessionTx.read(withCriteria(mcb)).findFirst().orElse(null);
|
||||
if (userSessionEntity != null) {
|
||||
if (userSessionEntity.isOffline()) {
|
||||
return Stream.of(userSessionEntity);
|
||||
|
@ -615,9 +595,8 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
// it's online user session so lookup offline user session by corresponding session id reference
|
||||
String offlineUserSessionId = userSessionEntity.getNote(CORRESPONDING_SESSION_ID);
|
||||
if (offlineUserSessionId != null) {
|
||||
UK uk = userSessionStore.getKeyConvertor().fromStringSafe(offlineUserSessionId);
|
||||
mcb = realmAndOfflineCriteriaBuilder(realm, true)
|
||||
.compare(UserSessionModel.SearchableFields.ID, ModelCriteriaBuilder.Operator.EQ, uk);
|
||||
.compare(UserSessionModel.SearchableFields.ID, ModelCriteriaBuilder.Operator.EQ, offlineUserSessionId);
|
||||
return userSessionTx.read(withCriteria(mcb));
|
||||
}
|
||||
|
||||
|
@ -630,18 +609,18 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
.compare(UserSessionModel.SearchableFields.IS_OFFLINE, ModelCriteriaBuilder.Operator.EQ, offline);
|
||||
}
|
||||
|
||||
private MapUserSessionEntity<UK> getUserSessionById(UK id) {
|
||||
MapUserSessionEntity<UK> userSessionEntity = transientUserSessions.get(id);
|
||||
private MapUserSessionEntity getUserSessionById(String id) {
|
||||
MapUserSessionEntity userSessionEntity = transientUserSessions.get(id);
|
||||
|
||||
if (userSessionEntity == null) {
|
||||
MapUserSessionEntity<UK> userSession = userSessionTx.read(id);
|
||||
MapUserSessionEntity userSession = userSessionTx.read(id);
|
||||
return userSession;
|
||||
}
|
||||
return userSessionEntity;
|
||||
}
|
||||
|
||||
private MapUserSessionEntity<UK> createUserSessionEntityInstance(UserSessionModel userSession, boolean offline) {
|
||||
MapUserSessionEntity<UK> entity = new MapUserSessionEntity<UK>(userSessionStore.getKeyConvertor().yieldNewUniqueKey(), userSession.getRealm().getId());
|
||||
private MapUserSessionEntity createUserSessionEntityInstance(UserSessionModel userSession, boolean offline) {
|
||||
MapUserSessionEntity entity = new MapUserSessionEntity(null, userSession.getRealm().getId());
|
||||
|
||||
entity.setAuthMethod(userSession.getAuthMethod());
|
||||
entity.setBrokerSessionId(userSession.getBrokerSessionId());
|
||||
|
@ -663,9 +642,9 @@ public class MapUserSessionProvider<UK, CK> implements UserSessionProvider {
|
|||
return entity;
|
||||
}
|
||||
|
||||
private MapAuthenticatedClientSessionEntity<CK> createAuthenticatedClientSessionInstance(AuthenticatedClientSessionModel clientSession,
|
||||
private MapAuthenticatedClientSessionEntity createAuthenticatedClientSessionInstance(AuthenticatedClientSessionModel clientSession,
|
||||
UserSessionModel userSession, boolean offline) {
|
||||
MapAuthenticatedClientSessionEntity<CK> entity = new MapAuthenticatedClientSessionEntity<CK>(clientSessionStore.getKeyConvertor().yieldNewUniqueKey(),
|
||||
MapAuthenticatedClientSessionEntity entity = new MapAuthenticatedClientSessionEntity(null,
|
||||
userSession.getId(), clientSession.getRealm().getId(), clientSession.getClient().getId(), offline);
|
||||
|
||||
entity.setAction(clientSession.getAction());
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.keycloak.protocol.oidc.OIDCConfigAttributes;
|
|||
*/
|
||||
public class SessionExpiration {
|
||||
|
||||
public static <K> void setClientSessionExpiration(MapAuthenticatedClientSessionEntity<K> entity, RealmModel realm, ClientModel client) {
|
||||
public static <K> 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<K> entity, RealmModel realm) {
|
||||
public static <K> void setUserSessionExpiration(MapUserSessionEntity entity, RealmModel realm) {
|
||||
if (entity.isOffline()) {
|
||||
long sessionExpires = entity.getLastSessionRefresh() + realm.getOfflineSessionIdleTimeout();
|
||||
if (realm.isOfflineSessionMaxLifespanEnabled()) {
|
||||
|
|
|
@ -28,11 +28,11 @@ import java.util.stream.Collectors;
|
|||
|
||||
public class AbstractUserEntityCredentialsOrderTest {
|
||||
|
||||
private MapUserEntity<Integer> user;
|
||||
private MapUserEntity user;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
user = new MapUserEntity<Integer>(1, "realmId") {};
|
||||
user = new MapUserEntity("1", "realmId");
|
||||
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
UserCredentialEntity credentialModel = new UserCredentialEntity();
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.keycloak.models.map.client.MapClientProviderFactory;
|
|||
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.storage.StringKeyConvertor;
|
||||
import org.keycloak.models.map.common.StringKeyConvertor;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.provider.InvalidationHandler.ObjectType;
|
||||
import org.hamcrest.Matchers;
|
||||
|
@ -81,10 +81,10 @@ public class MapStorageTest extends KeycloakModelTest {
|
|||
String component1Id = createMapStorageComponent("component1", "keyType", "ulong");
|
||||
String component2Id = createMapStorageComponent("component2", "keyType", "string");
|
||||
|
||||
Object[] ids = withRealm(realmId, (session, realm) -> {
|
||||
MapStorage<K, MapClientEntity<K>, ClientModel> storageMain = (MapStorage) session.getProvider(MapStorageProvider.class).getStorage(ClientModel.class);
|
||||
MapStorage<K1, MapClientEntity<K1>, ClientModel> storage1 = (MapStorage) session.getComponentProvider(MapStorageProvider.class, component1Id).getStorage(ClientModel.class);
|
||||
MapStorage<K2, MapClientEntity<K2>, ClientModel> storage2 = (MapStorage) session.getComponentProvider(MapStorageProvider.class, component2Id).getStorage(ClientModel.class);
|
||||
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);
|
||||
|
||||
// Assert that the map storage can be used both as a standalone store and a component
|
||||
assertThat(storageMain, notNullValue());
|
||||
|
@ -95,9 +95,9 @@ public class MapStorageTest extends KeycloakModelTest {
|
|||
final StringKeyConvertor<K1> kc1 = storage1.getKeyConvertor();
|
||||
final StringKeyConvertor<K2> kc2 = storage2.getKeyConvertor();
|
||||
|
||||
K idMain = kcMain.yieldNewUniqueKey();
|
||||
K1 id1 = kc1.yieldNewUniqueKey();
|
||||
K2 id2 = kc2.yieldNewUniqueKey();
|
||||
String idMain = kcMain.keyToString(kcMain.yieldNewUniqueKey());
|
||||
String id1 = kc1.keyToString(kc1.yieldNewUniqueKey());
|
||||
String id2 = kc2.keyToString(kc2.yieldNewUniqueKey());
|
||||
|
||||
assertThat(idMain, notNullValue());
|
||||
assertThat(id1, notNullValue());
|
||||
|
@ -115,20 +115,20 @@ public class MapStorageTest extends KeycloakModelTest {
|
|||
assertClientDoesNotExist(storage2, idMain, kcMain, kc2);
|
||||
assertClientDoesNotExist(storage2, id1, kc1, kc2);
|
||||
|
||||
MapClientEntity<K> clientMain = new MapClientEntityImpl<>(idMain, realmId);
|
||||
MapClientEntity<K1> client1 = new MapClientEntityImpl<>(id1, realmId);
|
||||
MapClientEntity<K2> client2 = new MapClientEntityImpl<>(id2, realmId);
|
||||
MapClientEntity clientMain = new MapClientEntityImpl<>(idMain, realmId);
|
||||
MapClientEntity client1 = new MapClientEntityImpl<>(id1, realmId);
|
||||
MapClientEntity client2 = new MapClientEntityImpl<>(id2, realmId);
|
||||
|
||||
storageMain.create(clientMain);
|
||||
storage1.create(client1);
|
||||
storage2.create(client2);
|
||||
clientMain = storageMain.create(clientMain);
|
||||
client1 = storage1.create(client1);
|
||||
client2 = storage2.create(client2);
|
||||
|
||||
return new Object[] {idMain, id1, id2};
|
||||
return new String[] {clientMain.getId(), client1.getId(), client2.getId()};
|
||||
});
|
||||
|
||||
K idMain = (K) ids[0];
|
||||
K1 id1 = (K1) ids[1];
|
||||
K2 id2 = (K2) ids[2];
|
||||
String idMain = ids[0];
|
||||
String id1 = ids[1];
|
||||
String id2 = ids[2];
|
||||
|
||||
LOG.debugf("Object IDs: %s, %s, %s", idMain, id1, id2);
|
||||
|
||||
|
@ -147,25 +147,24 @@ public class MapStorageTest extends KeycloakModelTest {
|
|||
assertClientsPersisted(component1Id, component2Id, idMain, id1, id2);
|
||||
}
|
||||
|
||||
private <K,K1> void assertClientDoesNotExist(MapStorage<K, MapClientEntity<K>, ClientModel> storage, K1 id, final StringKeyConvertor<K1> kc, final StringKeyConvertor<K> kcStorage) {
|
||||
private <K,K1> void assertClientDoesNotExist(MapStorage<K, 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 {
|
||||
final K keyInStorageFormat = kcStorage.fromString(kc.keyToString(id));
|
||||
assertThat(storage.read(keyInStorageFormat), nullValue());
|
||||
assertThat(storage.read(id), nullValue());
|
||||
} catch (Exception ex) {
|
||||
// If the format is incompatible then the object does not exist in the store
|
||||
}
|
||||
}
|
||||
|
||||
private <K, K1, K2> void assertClientsPersisted(String component1Id, String component2Id, K idMain, K1 id1, K2 id2) {
|
||||
private <K, K1, K2> void assertClientsPersisted(String component1Id, String component2Id, String idMain, String id1, String id2) {
|
||||
// Check that in the next transaction, the objects are still there
|
||||
withRealm(realmId, (session, realm) -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
MapStorage<K, MapClientEntity<K>, ClientModel> storageMain = (MapStorage) session.getProvider(MapStorageProvider.class).getStorage(ClientModel.class);
|
||||
MapStorage<K, MapClientEntity, ClientModel> storageMain = (MapStorage) session.getProvider(MapStorageProvider.class).getStorage(ClientModel.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
MapStorage<K1, MapClientEntity<K1>, ClientModel> storage1 = (MapStorage) session.getComponentProvider(MapStorageProvider.class, component1Id).getStorage(ClientModel.class);
|
||||
MapStorage<K1, MapClientEntity, ClientModel> storage1 = (MapStorage) session.getComponentProvider(MapStorageProvider.class, component1Id).getStorage(ClientModel.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
MapStorage<K2, MapClientEntity<K2>, ClientModel> storage2 = (MapStorage) session.getComponentProvider(MapStorageProvider.class, component2Id).getStorage(ClientModel.class);
|
||||
MapStorage<K2, MapClientEntity, ClientModel> storage2 = (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