Remove EXPIRATION fields and add expired entities filtering to all queries automatically

Closes #12563
This commit is contained in:
Michal Hajas 2022-06-20 11:48:57 +02:00 committed by Hynek Mlnařík
parent 22f9b0fee3
commit 0719d3e49b
22 changed files with 76 additions and 97 deletions

View file

@ -23,9 +23,12 @@ import org.infinispan.commons.util.CloseableIterator;
import org.infinispan.query.dsl.Query; import org.infinispan.query.dsl.Query;
import org.infinispan.query.dsl.QueryFactory; import org.infinispan.query.dsl.QueryFactory;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.keycloak.common.util.Time;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.map.common.AbstractEntity; import org.keycloak.models.map.common.AbstractEntity;
import org.keycloak.models.map.common.DeepCloner; import org.keycloak.models.map.common.DeepCloner;
import org.keycloak.models.map.common.ExpirableEntity;
import org.keycloak.models.map.storage.ModelEntityUtil;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity; import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
import org.keycloak.models.map.storage.hotRod.common.HotRodEntityDelegate; import org.keycloak.models.map.storage.hotRod.common.HotRodEntityDelegate;
import org.keycloak.models.map.storage.hotRod.common.HotRodEntityDescriptor; import org.keycloak.models.map.storage.hotRod.common.HotRodEntityDescriptor;
@ -48,6 +51,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
import static org.keycloak.models.map.common.ExpirationUtils.isExpired;
import static org.keycloak.models.map.storage.hotRod.common.HotRodUtils.paginateQuery; import static org.keycloak.models.map.storage.hotRod.common.HotRodUtils.paginateQuery;
import static org.keycloak.utils.StreamsUtil.closing; import static org.keycloak.utils.StreamsUtil.closing;
@ -60,6 +64,7 @@ public class HotRodMapStorage<K, E extends AbstractHotRodEntity, V extends HotRo
protected final HotRodEntityDescriptor<E, V> storedEntityDescriptor; protected final HotRodEntityDescriptor<E, V> storedEntityDescriptor;
private final Function<E, V> delegateProducer; private final Function<E, V> delegateProducer;
protected final DeepCloner cloner; protected final DeepCloner cloner;
protected boolean isExpirableEntity;
public HotRodMapStorage(RemoteCache<K, E> remoteCache, StringKeyConverter<K> keyConverter, HotRodEntityDescriptor<E, V> storedEntityDescriptor, DeepCloner cloner) { public HotRodMapStorage(RemoteCache<K, E> remoteCache, StringKeyConverter<K> keyConverter, HotRodEntityDescriptor<E, V> storedEntityDescriptor, DeepCloner cloner) {
this.remoteCache = remoteCache; this.remoteCache = remoteCache;
@ -67,6 +72,7 @@ public class HotRodMapStorage<K, E extends AbstractHotRodEntity, V extends HotRo
this.storedEntityDescriptor = storedEntityDescriptor; this.storedEntityDescriptor = storedEntityDescriptor;
this.cloner = cloner; this.cloner = cloner;
this.delegateProducer = storedEntityDescriptor.getHotRodDelegateProvider(); this.delegateProducer = storedEntityDescriptor.getHotRodDelegateProvider();
this.isExpirableEntity = ExpirableEntity.class.isAssignableFrom(ModelEntityUtil.getEntityType(storedEntityDescriptor.getModelTypeClass()));
} }
@Override @Override
@ -86,7 +92,10 @@ public class HotRodMapStorage<K, E extends AbstractHotRodEntity, V extends HotRo
public V read(String key) { public V read(String key) {
Objects.requireNonNull(key, "Key must be non-null"); Objects.requireNonNull(key, "Key must be non-null");
K k = keyConverter.fromStringSafe(key); K k = keyConverter.fromStringSafe(key);
return delegateProducer.apply(remoteCache.get(k));
V v = delegateProducer.apply(remoteCache.get(k));
if (v == null || v.getHotRodEntity() == null) return null;
return isExpirableEntity && isExpired((ExpirableEntity) v, true) ? null : v;
} }
@Override @Override
@ -109,12 +118,22 @@ public class HotRodMapStorage<K, E extends AbstractHotRodEntity, V extends HotRo
return modelFieldName + " " + orderString; return modelFieldName + " " + orderString;
} }
private static String isNotExpiredIckleWhereClause() {
return "(" + IckleQueryOperators.C + ".expiration > " + Time.currentTimeMillis() + " OR "
+ IckleQueryOperators.C + ".expiration is null)";
}
@Override @Override
public Stream<V> read(QueryParameters<M> queryParameters) { public Stream<V> read(QueryParameters<M> queryParameters) {
IckleQueryMapModelCriteriaBuilder<E, M> iqmcb = queryParameters.getModelCriteriaBuilder() IckleQueryMapModelCriteriaBuilder<E, M> iqmcb = queryParameters.getModelCriteriaBuilder()
.flashToModelCriteriaBuilder(createCriteriaBuilder()); .flashToModelCriteriaBuilder(createCriteriaBuilder());
String queryString = iqmcb.getIckleQuery(); String queryString = iqmcb.getIckleQuery();
// Temporary solution until https://github.com/keycloak/keycloak/issues/12068 is fixed
if (isExpirableEntity) {
queryString += (queryString.contains("WHERE") ? " AND " : " WHERE ") + isNotExpiredIckleWhereClause();
}
if (!queryParameters.getOrderBy().isEmpty()) { if (!queryParameters.getOrderBy().isEmpty()) {
queryString += " ORDER BY " + queryParameters.getOrderBy().stream().map(HotRodMapStorage::toOrderString) queryString += " ORDER BY " + queryParameters.getOrderBy().stream().map(HotRodMapStorage::toOrderString)
.collect(Collectors.joining(", ")); .collect(Collectors.joining(", "));

View file

@ -52,17 +52,6 @@ public class JpaRootAuthenticationSessionModelCriteriaBuilder extends JpaModelCr
throw new CriterionNotSupportedException(modelField, op); throw new CriterionNotSupportedException(modelField, op);
} }
case LT:
if (modelField == SearchableFields.EXPIRATION) {
validateValue(value, modelField, op, Number.class);
Number expiration = (Number) value[0];
return new JpaRootAuthenticationSessionModelCriteriaBuilder((cb, root) ->
cb.lt(root.get(modelField.getName()), expiration)
);
} else {
throw new CriterionNotSupportedException(modelField, op);
}
default: default:
throw new CriterionNotSupportedException(modelField, op); throw new CriterionNotSupportedException(modelField, op);
} }

View file

@ -135,21 +135,14 @@ public class MapRootAuthenticationSessionProvider implements AuthenticationSessi
@Override @Override
public void removeAllExpired() { public void removeAllExpired() {
session.realms().getRealmsStream().forEach(this::removeExpired); LOG.tracef("removeAllExpired()%s", getShortStackTrace());
LOG.warnf("Clearing expired entities should not be triggered manually. It is responsibility of the store to clear these.");
} }
@Override @Override
public void removeExpired(RealmModel realm) { public void removeExpired(RealmModel realm) {
Objects.requireNonNull(realm, "The provided realm can't be null!"); LOG.tracef("removeExpired(%s)%s", realm, getShortStackTrace());
LOG.debugf("Removing expired sessions"); LOG.warnf("Clearing expired entities should not be triggered manually. It is responsibility of the store to clear these.");
DefaultModelCriteria<RootAuthenticationSessionModel> mcb = criteria();
mcb = mcb.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
.compare(SearchableFields.EXPIRATION, Operator.LT, Time.currentTimeMillis());
long deletedCount = tx.delete(withCriteria(mcb));
LOG.debugf("Removed %d expired authentication sessions for realm '%s'", deletedCount, realm.getName());
} }
@Override @Override

View file

@ -35,4 +35,8 @@ public class ExpirationUtils {
if (!allowInfiniteValues && expiration == null) return false; if (!allowInfiniteValues && expiration == null) return false;
return expiration != null && expiration <= Time.currentTimeMillis(); return expiration != null && expiration <= Time.currentTimeMillis();
} }
public static boolean isNotExpired(Object entity) {
return !isExpired((ExpirableEntity) entity, true);
}
} }

View file

@ -126,14 +126,6 @@ public class MapAdminEventQuery implements AdminEventQuery {
@Override @Override
public Stream<AdminEvent> getResultStream() { public Stream<AdminEvent> getResultStream() {
// Add expiration condition to not load expired events
mcb = mcb.and(
criteria.or(
criteria.compare(AdminEvent.SearchableFields.EXPIRATION, ModelCriteriaBuilder.Operator.NOT_EXISTS),
criteria.compare(AdminEvent.SearchableFields.EXPIRATION, ModelCriteriaBuilder.Operator.GT,
Time.currentTimeMillis())
));
return resultProducer.apply(QueryParameters.withCriteria(mcb) return resultProducer.apply(QueryParameters.withCriteria(mcb)
.offset(firstResult) .offset(firstResult)
.limit(maxResults) .limit(maxResults)

View file

@ -106,14 +106,6 @@ public class MapAuthEventQuery implements EventQuery {
@Override @Override
public Stream<Event> getResultStream() { public Stream<Event> getResultStream() {
// Add expiration condition to not load expired events
mcb = mcb.and(
criteria.or(
criteria.compare(Event.SearchableFields.EXPIRATION, ModelCriteriaBuilder.Operator.NOT_EXISTS),
criteria.compare(Event.SearchableFields.EXPIRATION, ModelCriteriaBuilder.Operator.GT,
Time.currentTimeMillis())
));
return resultProducer.apply(QueryParameters.withCriteria(mcb) return resultProducer.apply(QueryParameters.withCriteria(mcb)
.offset(firstResult) .offset(firstResult)
.limit(maxResults) .limit(maxResults)

View file

@ -123,14 +123,7 @@ public class MapEventStoreProvider implements EventStoreProvider {
@Override @Override
public void clearExpiredEvents() { public void clearExpiredEvents() {
LOG.tracef("clearExpiredEvents()%s", getShortStackTrace()); LOG.tracef("clearExpiredEvents()%s", getShortStackTrace());
LOG.warnf("Clearing expired entities should not be triggered manually. It is responsibility of the store to clear these.");
authEventsTX.delete(QueryParameters.withCriteria(DefaultModelCriteria.<Event>criteria()
.compare(Event.SearchableFields.EXPIRATION, ModelCriteriaBuilder.Operator.LE,
Time.currentTimeMillis())));
adminEventsTX.delete(QueryParameters.withCriteria(DefaultModelCriteria.<AdminEvent>criteria()
.compare(AdminEvent.SearchableFields.EXPIRATION, ModelCriteriaBuilder.Operator.LE,
Time.currentTimeMillis())));
} }
/** ADMIN EVENTS **/ /** ADMIN EVENTS **/

View file

@ -75,8 +75,7 @@ public class MapSingleUseObjectProvider implements ActionTokenStoreProvider, Sin
DefaultModelCriteria<ActionTokenValueModel> mcb = criteria(); DefaultModelCriteria<ActionTokenValueModel> mcb = criteria();
mcb = mcb.compare(ActionTokenValueModel.SearchableFields.USER_ID, ModelCriteriaBuilder.Operator.EQ, actionTokenKey.getUserId()) mcb = mcb.compare(ActionTokenValueModel.SearchableFields.USER_ID, ModelCriteriaBuilder.Operator.EQ, actionTokenKey.getUserId())
.compare(ActionTokenValueModel.SearchableFields.ACTION_ID, ModelCriteriaBuilder.Operator.EQ, actionTokenKey.getActionId()) .compare(ActionTokenValueModel.SearchableFields.ACTION_ID, ModelCriteriaBuilder.Operator.EQ, actionTokenKey.getActionId())
.compare(ActionTokenValueModel.SearchableFields.ACTION_VERIFICATION_NONCE, ModelCriteriaBuilder.Operator.EQ, actionTokenKey.getActionVerificationNonce().toString()) .compare(ActionTokenValueModel.SearchableFields.ACTION_VERIFICATION_NONCE, ModelCriteriaBuilder.Operator.EQ, actionTokenKey.getActionVerificationNonce().toString());
.compare(ActionTokenValueModel.SearchableFields.EXPIRATION, ModelCriteriaBuilder.Operator.GT, Time.currentTimeMillis());
ActionTokenValueModel existing = actionTokenStoreTx.read(withCriteria(mcb)) ActionTokenValueModel existing = actionTokenStoreTx.read(withCriteria(mcb))
.findFirst().map(this::singleUseEntityToAdapter).orElse(null); .findFirst().map(this::singleUseEntityToAdapter).orElse(null);
@ -106,8 +105,7 @@ public class MapSingleUseObjectProvider implements ActionTokenStoreProvider, Sin
DefaultModelCriteria<ActionTokenValueModel> mcb = criteria(); DefaultModelCriteria<ActionTokenValueModel> mcb = criteria();
mcb = mcb.compare(ActionTokenValueModel.SearchableFields.USER_ID, ModelCriteriaBuilder.Operator.EQ, key.getUserId()) mcb = mcb.compare(ActionTokenValueModel.SearchableFields.USER_ID, ModelCriteriaBuilder.Operator.EQ, key.getUserId())
.compare(ActionTokenValueModel.SearchableFields.ACTION_ID, ModelCriteriaBuilder.Operator.EQ, key.getActionId()) .compare(ActionTokenValueModel.SearchableFields.ACTION_ID, ModelCriteriaBuilder.Operator.EQ, key.getActionId())
.compare(ActionTokenValueModel.SearchableFields.ACTION_VERIFICATION_NONCE, ModelCriteriaBuilder.Operator.EQ, key.getActionVerificationNonce().toString()) .compare(ActionTokenValueModel.SearchableFields.ACTION_VERIFICATION_NONCE, ModelCriteriaBuilder.Operator.EQ, key.getActionVerificationNonce().toString());
.compare(ActionTokenValueModel.SearchableFields.EXPIRATION, ModelCriteriaBuilder.Operator.GT, Time.currentTimeMillis());
return actionTokenStoreTx.read(withCriteria(mcb)) return actionTokenStoreTx.read(withCriteria(mcb))
.findFirst().map(this::singleUseEntityToAdapter).orElse(null); .findFirst().map(this::singleUseEntityToAdapter).orElse(null);
@ -124,9 +122,7 @@ public class MapSingleUseObjectProvider implements ActionTokenStoreProvider, Sin
DefaultModelCriteria<ActionTokenValueModel> mcb = criteria(); DefaultModelCriteria<ActionTokenValueModel> mcb = criteria();
mcb = mcb.compare(ActionTokenValueModel.SearchableFields.USER_ID, ModelCriteriaBuilder.Operator.EQ, key.getUserId()) mcb = mcb.compare(ActionTokenValueModel.SearchableFields.USER_ID, ModelCriteriaBuilder.Operator.EQ, key.getUserId())
.compare(ActionTokenValueModel.SearchableFields.ACTION_ID, ModelCriteriaBuilder.Operator.EQ, key.getActionId()) .compare(ActionTokenValueModel.SearchableFields.ACTION_ID, ModelCriteriaBuilder.Operator.EQ, key.getActionId())
.compare(ActionTokenValueModel.SearchableFields.ACTION_VERIFICATION_NONCE, ModelCriteriaBuilder.Operator.EQ, key.getActionVerificationNonce().toString()) .compare(ActionTokenValueModel.SearchableFields.ACTION_VERIFICATION_NONCE, ModelCriteriaBuilder.Operator.EQ, key.getActionVerificationNonce().toString());
.compare(ActionTokenValueModel.SearchableFields.EXPIRATION, ModelCriteriaBuilder.Operator.GT, Time.currentTimeMillis());
MapSingleUseObjectEntity mapSingleUseObjectEntity = actionTokenStoreTx.read(withCriteria(mcb)).findFirst().orElse(null); MapSingleUseObjectEntity mapSingleUseObjectEntity = actionTokenStoreTx.read(withCriteria(mcb)).findFirst().orElse(null);
if (mapSingleUseObjectEntity != null) { if (mapSingleUseObjectEntity != null) {
ActionTokenValueModel actionToken = singleUseEntityToAdapter(mapSingleUseObjectEntity); ActionTokenValueModel actionToken = singleUseEntityToAdapter(mapSingleUseObjectEntity);

View file

@ -43,6 +43,9 @@ public interface MapKeycloakTransaction<V extends AbstractEntity, M> extends Key
* in current transaction. Updates to the returned instance would be visible in the current transaction * in current transaction. Updates to the returned instance would be visible in the current transaction
* and will propagate into the underlying store upon commit. * and will propagate into the underlying store upon commit.
* *
* If {@code V} implements {@link org.keycloak.models.map.common.ExpirableEntity} this method should not return
* entities that are expired. See {@link org.keycloak.models.map.common.ExpirableEntity} JavaDoc for more details.
*
* @param key identifier of a value * @param key identifier of a value
* @return a value associated with the given {@code key} * @return a value associated with the given {@code key}
*/ */
@ -57,6 +60,9 @@ public interface MapKeycloakTransaction<V extends AbstractEntity, M> extends Key
* Updates to the returned instances of {@code V} would be visible in the current transaction * Updates to the returned instances of {@code V} would be visible in the current transaction
* and will propagate into the underlying store upon commit. * and will propagate into the underlying store upon commit.
* *
* If {@code V} implements {@link org.keycloak.models.map.common.ExpirableEntity} this method should not return
* entities that are expired. See {@link org.keycloak.models.map.common.ExpirableEntity} JavaDoc for more details.
*
* @param queryParameters parameters for the query like firstResult, maxResult, requested ordering, etc. * @param queryParameters parameters for the query like firstResult, maxResult, requested ordering, etc.
* @return values that fulfill the given criteria, that are updated based on changes in the current transaction * @return values that fulfill the given criteria, that are updated based on changes in the current transaction
*/ */

View file

@ -23,6 +23,9 @@ public interface ConcurrentHashMapCrudOperations<V extends AbstractEntity & Upda
/** /**
* Returns object with the given {@code key} from the storage or {@code null} if object does not exist. * Returns object with the given {@code key} from the storage or {@code null} if object does not exist.
* <br> * <br>
* If {@code V} implements {@link org.keycloak.models.map.common.ExpirableEntity} this method should not return
* entities that are expired. See {@link org.keycloak.models.map.common.ExpirableEntity} JavaDoc for more details.
*
* TODO: Consider returning {@code Optional<V>} instead. * TODO: Consider returning {@code Optional<V>} instead.
* @param key Key of the object. Must not be {@code null}. * @param key Key of the object. Must not be {@code null}.
* @return See description * @return See description
@ -57,6 +60,9 @@ public interface ConcurrentHashMapCrudOperations<V extends AbstractEntity & Upda
* Returns stream of objects satisfying given {@code criteria} from the storage. * Returns stream of objects satisfying given {@code criteria} from the storage.
* The criteria are specified in the given criteria builder based on model properties. * The criteria are specified in the given criteria builder based on model properties.
* *
* If {@code V} implements {@link org.keycloak.models.map.common.ExpirableEntity} this method should not return
* entities that are expired. See {@link org.keycloak.models.map.common.ExpirableEntity} JavaDoc for more details.
*
* @param queryParameters parameters for the query like firstResult, maxResult, requested ordering, etc. * @param queryParameters parameters for the query like firstResult, maxResult, requested ordering, etc.
* @return Stream of objects. Never returns {@code null}. * @return Stream of objects. Never returns {@code null}.
*/ */

View file

@ -16,6 +16,8 @@
*/ */
package org.keycloak.models.map.storage.chm; package org.keycloak.models.map.storage.chm;
import org.keycloak.models.map.common.ExpirableEntity;
import org.keycloak.models.map.common.ExpirationUtils;
import org.keycloak.models.map.common.StringKeyConverter; import org.keycloak.models.map.common.StringKeyConverter;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.map.storage.MapKeycloakTransaction; import org.keycloak.models.map.storage.MapKeycloakTransaction;
@ -23,6 +25,7 @@ import org.keycloak.models.map.common.AbstractEntity;
import org.keycloak.models.map.common.DeepCloner; import org.keycloak.models.map.common.DeepCloner;
import org.keycloak.models.map.common.UpdatableEntity; import org.keycloak.models.map.common.UpdatableEntity;
import org.keycloak.models.map.storage.MapStorage; import org.keycloak.models.map.storage.MapStorage;
import org.keycloak.models.map.storage.ModelEntityUtil;
import org.keycloak.models.map.storage.QueryParameters; import org.keycloak.models.map.storage.QueryParameters;
import org.keycloak.models.map.storage.criteria.DefaultModelCriteria; import org.keycloak.models.map.storage.criteria.DefaultModelCriteria;
import org.keycloak.storage.SearchableModelField; import org.keycloak.storage.SearchableModelField;
@ -38,6 +41,7 @@ import org.keycloak.models.map.storage.chm.MapModelCriteriaBuilder.UpdatePredica
import java.util.Objects; import java.util.Objects;
import java.util.function.Predicate; import java.util.function.Predicate;
import static org.keycloak.models.map.common.ExpirationUtils.isExpired;
import static org.keycloak.utils.StreamsUtil.paginatedStream; import static org.keycloak.utils.StreamsUtil.paginatedStream;
/** /**
@ -56,12 +60,14 @@ public class ConcurrentHashMapStorage<K, V extends AbstractEntity & UpdatableEnt
protected final Map<SearchableModelField<? super M>, UpdatePredicatesFunc<K, V, M>> fieldPredicates; protected final Map<SearchableModelField<? super M>, UpdatePredicatesFunc<K, V, M>> fieldPredicates;
protected final StringKeyConverter<K> keyConverter; protected final StringKeyConverter<K> keyConverter;
protected final DeepCloner cloner; protected final DeepCloner cloner;
private final boolean isExpirableEntity;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public ConcurrentHashMapStorage(Class<M> modelClass, StringKeyConverter<K> keyConverter, DeepCloner cloner) { public ConcurrentHashMapStorage(Class<M> modelClass, StringKeyConverter<K> keyConverter, DeepCloner cloner) {
this.fieldPredicates = MapFieldPredicates.getPredicates(modelClass); this.fieldPredicates = MapFieldPredicates.getPredicates(modelClass);
this.keyConverter = keyConverter; this.keyConverter = keyConverter;
this.cloner = cloner; this.cloner = cloner;
this.isExpirableEntity = ExpirableEntity.class.isAssignableFrom(ModelEntityUtil.getEntityType(modelClass));
} }
@Override @Override
@ -79,7 +85,10 @@ public class ConcurrentHashMapStorage<K, V extends AbstractEntity & UpdatableEnt
public V read(String key) { public V read(String key) {
Objects.requireNonNull(key, "Key must be non-null"); Objects.requireNonNull(key, "Key must be non-null");
K k = keyConverter.fromStringSafe(key); K k = keyConverter.fromStringSafe(key);
return store.get(k);
V v = store.get(k);
if (v == null) return null;
return isExpirableEntity && isExpired((ExpirableEntity) v, true) ? null : v;
} }
@Override @Override
@ -157,7 +166,14 @@ public class ConcurrentHashMapStorage<K, V extends AbstractEntity & UpdatableEnt
Stream<Entry<K, V>> stream = store.entrySet().stream(); Stream<Entry<K, V>> stream = store.entrySet().stream();
Predicate<? super K> keyFilter = mcb.getKeyFilter(); Predicate<? super K> keyFilter = mcb.getKeyFilter();
Predicate<? super V> entityFilter = mcb.getEntityFilter(); Predicate<? super V> entityFilter;
if (isExpirableEntity) {
entityFilter = mcb.getEntityFilter().and(ExpirationUtils::isNotExpired);
} else {
entityFilter = mcb.getEntityFilter();
}
Stream<V> valueStream = stream.filter(me -> keyFilter.test(me.getKey()) && entityFilter.test(me.getValue())) Stream<V> valueStream = stream.filter(me -> keyFilter.test(me.getKey()) && entityFilter.test(me.getValue()))
.map(Map.Entry::getValue); .map(Map.Entry::getValue);

View file

@ -151,7 +151,6 @@ public class MapFieldPredicates {
put(USER_PREDICATES, UserModel.SearchableFields.SERVICE_ACCOUNT_CLIENT, MapUserEntity::getServiceAccountClientLink); put(USER_PREDICATES, UserModel.SearchableFields.SERVICE_ACCOUNT_CLIENT, MapUserEntity::getServiceAccountClientLink);
put(AUTHENTICATION_SESSION_PREDICATES, RootAuthenticationSessionModel.SearchableFields.REALM_ID, MapRootAuthenticationSessionEntity::getRealmId); put(AUTHENTICATION_SESSION_PREDICATES, RootAuthenticationSessionModel.SearchableFields.REALM_ID, MapRootAuthenticationSessionEntity::getRealmId);
put(AUTHENTICATION_SESSION_PREDICATES, RootAuthenticationSessionModel.SearchableFields.EXPIRATION, MapRootAuthenticationSessionEntity::getExpiration);
put(AUTHZ_RESOURCE_SERVER_PREDICATES, ResourceServer.SearchableFields.ID, predicateForKeyField(MapResourceServerEntity::getId)); put(AUTHZ_RESOURCE_SERVER_PREDICATES, ResourceServer.SearchableFields.ID, predicateForKeyField(MapResourceServerEntity::getId));
put(AUTHZ_RESOURCE_SERVER_PREDICATES, ResourceServer.SearchableFields.CLIENT_ID, MapResourceServerEntity::getClientId); put(AUTHZ_RESOURCE_SERVER_PREDICATES, ResourceServer.SearchableFields.CLIENT_ID, MapResourceServerEntity::getClientId);
@ -201,14 +200,12 @@ public class MapFieldPredicates {
put(USER_SESSION_PREDICATES, UserSessionModel.SearchableFields.BROKER_USER_ID, MapUserSessionEntity::getBrokerUserId); put(USER_SESSION_PREDICATES, UserSessionModel.SearchableFields.BROKER_USER_ID, MapUserSessionEntity::getBrokerUserId);
put(USER_SESSION_PREDICATES, UserSessionModel.SearchableFields.IS_OFFLINE, MapUserSessionEntity::isOffline); put(USER_SESSION_PREDICATES, UserSessionModel.SearchableFields.IS_OFFLINE, MapUserSessionEntity::isOffline);
put(USER_SESSION_PREDICATES, UserSessionModel.SearchableFields.LAST_SESSION_REFRESH, MapUserSessionEntity::getLastSessionRefresh); put(USER_SESSION_PREDICATES, UserSessionModel.SearchableFields.LAST_SESSION_REFRESH, MapUserSessionEntity::getLastSessionRefresh);
put(USER_SESSION_PREDICATES, UserSessionModel.SearchableFields.EXPIRATION, MapUserSessionEntity::getExpiration);
put(CLIENT_SESSION_PREDICATES, AuthenticatedClientSessionModel.SearchableFields.REALM_ID, MapAuthenticatedClientSessionEntity::getRealmId); put(CLIENT_SESSION_PREDICATES, AuthenticatedClientSessionModel.SearchableFields.REALM_ID, MapAuthenticatedClientSessionEntity::getRealmId);
put(CLIENT_SESSION_PREDICATES, AuthenticatedClientSessionModel.SearchableFields.CLIENT_ID, MapAuthenticatedClientSessionEntity::getClientId); put(CLIENT_SESSION_PREDICATES, AuthenticatedClientSessionModel.SearchableFields.CLIENT_ID, MapAuthenticatedClientSessionEntity::getClientId);
put(CLIENT_SESSION_PREDICATES, AuthenticatedClientSessionModel.SearchableFields.USER_SESSION_ID, MapAuthenticatedClientSessionEntity::getUserSessionId); put(CLIENT_SESSION_PREDICATES, AuthenticatedClientSessionModel.SearchableFields.USER_SESSION_ID, MapAuthenticatedClientSessionEntity::getUserSessionId);
put(CLIENT_SESSION_PREDICATES, AuthenticatedClientSessionModel.SearchableFields.IS_OFFLINE, MapAuthenticatedClientSessionEntity::isOffline); put(CLIENT_SESSION_PREDICATES, AuthenticatedClientSessionModel.SearchableFields.IS_OFFLINE, MapAuthenticatedClientSessionEntity::isOffline);
put(CLIENT_SESSION_PREDICATES, AuthenticatedClientSessionModel.SearchableFields.TIMESTAMP, MapAuthenticatedClientSessionEntity::getTimestamp); put(CLIENT_SESSION_PREDICATES, AuthenticatedClientSessionModel.SearchableFields.TIMESTAMP, MapAuthenticatedClientSessionEntity::getTimestamp);
put(CLIENT_SESSION_PREDICATES, AuthenticatedClientSessionModel.SearchableFields.EXPIRATION, MapAuthenticatedClientSessionEntity::getExpiration);
put(USER_LOGIN_FAILURE_PREDICATES, UserLoginFailureModel.SearchableFields.REALM_ID, MapUserLoginFailureEntity::getRealmId); put(USER_LOGIN_FAILURE_PREDICATES, UserLoginFailureModel.SearchableFields.REALM_ID, MapUserLoginFailureEntity::getRealmId);
put(USER_LOGIN_FAILURE_PREDICATES, UserLoginFailureModel.SearchableFields.USER_ID, MapUserLoginFailureEntity::getUserId); put(USER_LOGIN_FAILURE_PREDICATES, UserLoginFailureModel.SearchableFields.USER_ID, MapUserLoginFailureEntity::getUserId);
@ -217,13 +214,11 @@ public class MapFieldPredicates {
put(AUTH_EVENTS_PREDICATES, Event.SearchableFields.CLIENT_ID, MapAuthEventEntity::getClientId); put(AUTH_EVENTS_PREDICATES, Event.SearchableFields.CLIENT_ID, MapAuthEventEntity::getClientId);
put(AUTH_EVENTS_PREDICATES, Event.SearchableFields.USER_ID, MapAuthEventEntity::getUserId); put(AUTH_EVENTS_PREDICATES, Event.SearchableFields.USER_ID, MapAuthEventEntity::getUserId);
put(AUTH_EVENTS_PREDICATES, Event.SearchableFields.TIMESTAMP, MapAuthEventEntity::getTimestamp); put(AUTH_EVENTS_PREDICATES, Event.SearchableFields.TIMESTAMP, MapAuthEventEntity::getTimestamp);
put(AUTH_EVENTS_PREDICATES, Event.SearchableFields.EXPIRATION, MapAuthEventEntity::getExpiration);
put(AUTH_EVENTS_PREDICATES, Event.SearchableFields.IP_ADDRESS, MapAuthEventEntity::getIpAddress); put(AUTH_EVENTS_PREDICATES, Event.SearchableFields.IP_ADDRESS, MapAuthEventEntity::getIpAddress);
put(AUTH_EVENTS_PREDICATES, Event.SearchableFields.EVENT_TYPE, MapAuthEventEntity::getType); put(AUTH_EVENTS_PREDICATES, Event.SearchableFields.EVENT_TYPE, MapAuthEventEntity::getType);
put(ADMIN_EVENTS_PREDICATES, AdminEvent.SearchableFields.REALM_ID, MapAdminEventEntity::getRealmId); put(ADMIN_EVENTS_PREDICATES, AdminEvent.SearchableFields.REALM_ID, MapAdminEventEntity::getRealmId);
put(ADMIN_EVENTS_PREDICATES, AdminEvent.SearchableFields.TIMESTAMP, MapAdminEventEntity::getTimestamp); put(ADMIN_EVENTS_PREDICATES, AdminEvent.SearchableFields.TIMESTAMP, MapAdminEventEntity::getTimestamp);
put(ADMIN_EVENTS_PREDICATES, AdminEvent.SearchableFields.EXPIRATION, MapAdminEventEntity::getExpiration);
put(ADMIN_EVENTS_PREDICATES, AdminEvent.SearchableFields.AUTH_REALM_ID, MapAdminEventEntity::getAuthRealmId); put(ADMIN_EVENTS_PREDICATES, AdminEvent.SearchableFields.AUTH_REALM_ID, MapAdminEventEntity::getAuthRealmId);
put(ADMIN_EVENTS_PREDICATES, AdminEvent.SearchableFields.AUTH_CLIENT_ID, MapAdminEventEntity::getAuthClientId); put(ADMIN_EVENTS_PREDICATES, AdminEvent.SearchableFields.AUTH_CLIENT_ID, MapAdminEventEntity::getAuthClientId);
put(ADMIN_EVENTS_PREDICATES, AdminEvent.SearchableFields.AUTH_USER_ID, MapAdminEventEntity::getAuthUserId); put(ADMIN_EVENTS_PREDICATES, AdminEvent.SearchableFields.AUTH_USER_ID, MapAdminEventEntity::getAuthUserId);
@ -235,7 +230,6 @@ public class MapFieldPredicates {
put(ACTION_TOKEN_PREDICATES, ActionTokenValueModel.SearchableFields.USER_ID, MapSingleUseObjectEntity::getUserId); put(ACTION_TOKEN_PREDICATES, ActionTokenValueModel.SearchableFields.USER_ID, MapSingleUseObjectEntity::getUserId);
put(ACTION_TOKEN_PREDICATES, ActionTokenValueModel.SearchableFields.ACTION_ID, MapSingleUseObjectEntity::getActionId); put(ACTION_TOKEN_PREDICATES, ActionTokenValueModel.SearchableFields.ACTION_ID, MapSingleUseObjectEntity::getActionId);
put(ACTION_TOKEN_PREDICATES, ActionTokenValueModel.SearchableFields.ACTION_VERIFICATION_NONCE, MapSingleUseObjectEntity::getActionVerificationNonce); put(ACTION_TOKEN_PREDICATES, ActionTokenValueModel.SearchableFields.ACTION_VERIFICATION_NONCE, MapSingleUseObjectEntity::getActionVerificationNonce);
put(ACTION_TOKEN_PREDICATES, ActionTokenValueModel.SearchableFields.EXPIRATION, MapSingleUseObjectEntity::getExpiration);
} }
static { static {

View file

@ -29,8 +29,6 @@ import org.keycloak.models.map.storage.criteria.DefaultModelCriteria;
import java.util.stream.Stream; import java.util.stream.Stream;
import static org.keycloak.models.map.common.ExpirationUtils.isExpired;
/** /**
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a> * @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
*/ */
@ -74,8 +72,7 @@ public class SingleUseObjectConcurrentHashMapStorage<K, V extends AbstractEntity
SingleUseObjectModelCriteriaBuilder mcb = criteria.flashToModelCriteriaBuilder(createSingleUseObjectCriteriaBuilder()); SingleUseObjectModelCriteriaBuilder mcb = criteria.flashToModelCriteriaBuilder(createSingleUseObjectCriteriaBuilder());
if (mcb.isValid()) { if (mcb.isValid()) {
MapSingleUseObjectEntity value = read(mcb.getKey()); MapSingleUseObjectEntity value = read(mcb.getKey());
if (value == null || (mcb.checkExpiration() && isExpired(value, false))) return Stream.empty(); return value != null ? Stream.of(value) : Stream.empty();
return Stream.of(value);
} }
return super.read(queryParameters); return super.read(queryParameters);

View file

@ -17,7 +17,6 @@
package org.keycloak.models.map.storage.chm; package org.keycloak.models.map.storage.chm;
import org.keycloak.models.ActionTokenValueModel;
import org.keycloak.models.map.storage.ModelCriteriaBuilder; import org.keycloak.models.map.storage.ModelCriteriaBuilder;
import org.keycloak.storage.SearchableModelField; import org.keycloak.storage.SearchableModelField;
@ -32,16 +31,13 @@ public class SingleUseObjectModelCriteriaBuilder implements ModelCriteriaBuilder
private String actionVerificationNonce; private String actionVerificationNonce;
private Boolean checkExpiration;
public SingleUseObjectModelCriteriaBuilder() { public SingleUseObjectModelCriteriaBuilder() {
} }
public SingleUseObjectModelCriteriaBuilder(String userId, String actionId, String actionVerificationNonce, Boolean checkExpiration) { public SingleUseObjectModelCriteriaBuilder(String userId, String actionId, String actionVerificationNonce) {
this.userId = userId; this.userId = userId;
this.actionId = actionId; this.actionId = actionId;
this.actionVerificationNonce = actionVerificationNonce; this.actionVerificationNonce = actionVerificationNonce;
this.checkExpiration = checkExpiration;
} }
@Override @Override
@ -52,11 +48,8 @@ public class SingleUseObjectModelCriteriaBuilder implements ModelCriteriaBuilder
actionId = value[0].toString(); actionId = value[0].toString();
} else if (modelField == org.keycloak.models.ActionTokenValueModel.SearchableFields.ACTION_VERIFICATION_NONCE) { } else if (modelField == org.keycloak.models.ActionTokenValueModel.SearchableFields.ACTION_VERIFICATION_NONCE) {
actionVerificationNonce = value[0].toString(); actionVerificationNonce = value[0].toString();
} else if (modelField == ActionTokenValueModel.SearchableFields.EXPIRATION && op == Operator.GT) {
checkExpiration = true;
} }
return new SingleUseObjectModelCriteriaBuilder(userId, actionId, actionVerificationNonce);
return new SingleUseObjectModelCriteriaBuilder(userId, actionId, actionVerificationNonce, checkExpiration);
} }
@Override @Override
@ -64,7 +57,6 @@ public class SingleUseObjectModelCriteriaBuilder implements ModelCriteriaBuilder
String userId = null; String userId = null;
String actionId = null; String actionId = null;
String actionVerificationNonce = null; String actionVerificationNonce = null;
Boolean checkExpiration = null;
for (ModelCriteriaBuilder builder: builders) { for (ModelCriteriaBuilder builder: builders) {
SingleUseObjectModelCriteriaBuilder suoMcb = (SingleUseObjectModelCriteriaBuilder) builder; SingleUseObjectModelCriteriaBuilder suoMcb = (SingleUseObjectModelCriteriaBuilder) builder;
@ -77,11 +69,8 @@ public class SingleUseObjectModelCriteriaBuilder implements ModelCriteriaBuilder
if (suoMcb.actionVerificationNonce != null) { if (suoMcb.actionVerificationNonce != null) {
actionVerificationNonce = suoMcb.actionVerificationNonce; actionVerificationNonce = suoMcb.actionVerificationNonce;
} }
if (suoMcb.checkExpiration != null) {
checkExpiration = suoMcb.checkExpiration;
} }
} return new SingleUseObjectModelCriteriaBuilder(userId, actionId, actionVerificationNonce);
return new SingleUseObjectModelCriteriaBuilder(userId, actionId, actionVerificationNonce, checkExpiration);
} }
@Override @Override
@ -98,10 +87,6 @@ public class SingleUseObjectModelCriteriaBuilder implements ModelCriteriaBuilder
return userId != null && actionId != null && actionVerificationNonce != null; return userId != null && actionId != null && actionVerificationNonce != null;
} }
public boolean checkExpiration() {
return checkExpiration != null && checkExpiration;
}
public String getKey() { public String getKey() {
return userId + ":" + actionId + ":" + actionVerificationNonce; return userId + ":" + actionId + ":" + actionVerificationNonce;
} }

View file

@ -207,8 +207,7 @@ public class MapUserSessionProvider implements UserSessionProvider {
.compare(AuthenticatedClientSessionModel.SearchableFields.USER_SESSION_ID, Operator.EQ, userSession.getId()) .compare(AuthenticatedClientSessionModel.SearchableFields.USER_SESSION_ID, Operator.EQ, userSession.getId())
.compare(AuthenticatedClientSessionModel.SearchableFields.REALM_ID, Operator.EQ, userSession.getRealm().getId()) .compare(AuthenticatedClientSessionModel.SearchableFields.REALM_ID, Operator.EQ, userSession.getRealm().getId())
.compare(AuthenticatedClientSessionModel.SearchableFields.CLIENT_ID, Operator.EQ, client.getId()) .compare(AuthenticatedClientSessionModel.SearchableFields.CLIENT_ID, Operator.EQ, client.getId())
.compare(AuthenticatedClientSessionModel.SearchableFields.IS_OFFLINE, Operator.EQ, offline) .compare(AuthenticatedClientSessionModel.SearchableFields.IS_OFFLINE, Operator.EQ, offline);
.compare(AuthenticatedClientSessionModel.SearchableFields.EXPIRATION, Operator.GT, Time.currentTimeMillis());
return clientSessionTx.read(withCriteria(mcb)) return clientSessionTx.read(withCriteria(mcb))
.findFirst() .findFirst()
@ -606,9 +605,7 @@ public class MapUserSessionProvider implements UserSessionProvider {
// first get a user entity by ID // first get a user entity by ID
DefaultModelCriteria<UserSessionModel> mcb = criteria(); DefaultModelCriteria<UserSessionModel> mcb = criteria();
mcb = mcb.compare(UserSessionModel.SearchableFields.REALM_ID, Operator.EQ, realm.getId()) mcb = mcb.compare(UserSessionModel.SearchableFields.REALM_ID, Operator.EQ, realm.getId())
.compare(UserSessionModel.SearchableFields.ID, Operator.EQ, userSessionId) .compare(UserSessionModel.SearchableFields.ID, Operator.EQ, userSessionId);
.compare(UserSessionModel.SearchableFields.EXPIRATION, Operator.GT, Time.currentTimeMillis())
;
// check if it's an offline user session // check if it's an offline user session
MapUserSessionEntity userSessionEntity = userSessionTx.read(withCriteria(mcb)).findFirst().orElse(null); MapUserSessionEntity userSessionEntity = userSessionTx.read(withCriteria(mcb)).findFirst().orElse(null);
@ -637,8 +634,7 @@ public class MapUserSessionProvider implements UserSessionProvider {
private DefaultModelCriteria<UserSessionModel> realmAndOfflineCriteriaBuilder(RealmModel realm, boolean offline) { private DefaultModelCriteria<UserSessionModel> realmAndOfflineCriteriaBuilder(RealmModel realm, boolean offline) {
return DefaultModelCriteria.<UserSessionModel>criteria() return DefaultModelCriteria.<UserSessionModel>criteria()
.compare(UserSessionModel.SearchableFields.REALM_ID, Operator.EQ, realm.getId()) .compare(UserSessionModel.SearchableFields.REALM_ID, Operator.EQ, realm.getId())
.compare(UserSessionModel.SearchableFields.IS_OFFLINE, Operator.EQ, offline) .compare(UserSessionModel.SearchableFields.IS_OFFLINE, Operator.EQ, offline);
.compare(UserSessionModel.SearchableFields.EXPIRATION, Operator.GT, Time.currentTimeMillis());
} }
private MapUserSessionEntity getUserSessionById(String id) { private MapUserSessionEntity getUserSessionById(String id) {

View file

@ -33,7 +33,6 @@ public class Event {
public static final SearchableModelField<Event> CLIENT_ID = new SearchableModelField<>("clientId", String.class); public static final SearchableModelField<Event> CLIENT_ID = new SearchableModelField<>("clientId", String.class);
public static final SearchableModelField<Event> USER_ID = new SearchableModelField<>("userId", String.class); public static final SearchableModelField<Event> USER_ID = new SearchableModelField<>("userId", String.class);
public static final SearchableModelField<Event> TIMESTAMP = new SearchableModelField<>("timestamp", Long.class); public static final SearchableModelField<Event> TIMESTAMP = new SearchableModelField<>("timestamp", Long.class);
public static final SearchableModelField<Event> EXPIRATION = new SearchableModelField<>("expiration", Long.class);
public static final SearchableModelField<Event> IP_ADDRESS = new SearchableModelField<>("ipAddress", String.class); public static final SearchableModelField<Event> IP_ADDRESS = new SearchableModelField<>("ipAddress", String.class);
public static final SearchableModelField<Event> EVENT_TYPE = new SearchableModelField<>("eventType", EventType.class); public static final SearchableModelField<Event> EVENT_TYPE = new SearchableModelField<>("eventType", EventType.class);
} }

View file

@ -28,7 +28,6 @@ public class AdminEvent {
public static final SearchableModelField<AdminEvent> ID = new SearchableModelField<>("id", String.class); public static final SearchableModelField<AdminEvent> ID = new SearchableModelField<>("id", String.class);
public static final SearchableModelField<AdminEvent> REALM_ID = new SearchableModelField<>("realmId", String.class); public static final SearchableModelField<AdminEvent> REALM_ID = new SearchableModelField<>("realmId", String.class);
public static final SearchableModelField<AdminEvent> TIMESTAMP = new SearchableModelField<>("timestamp", Long.class); public static final SearchableModelField<AdminEvent> TIMESTAMP = new SearchableModelField<>("timestamp", Long.class);
public static final SearchableModelField<AdminEvent> EXPIRATION = new SearchableModelField<>("expiration", Long.class);
public static final SearchableModelField<AdminEvent> AUTH_REALM_ID = new SearchableModelField<>("authRealmId", String.class); public static final SearchableModelField<AdminEvent> AUTH_REALM_ID = new SearchableModelField<>("authRealmId", String.class);
public static final SearchableModelField<AdminEvent> AUTH_CLIENT_ID = new SearchableModelField<>("authClientId", String.class); public static final SearchableModelField<AdminEvent> AUTH_CLIENT_ID = new SearchableModelField<>("authClientId", String.class);
public static final SearchableModelField<AdminEvent> AUTH_USER_ID = new SearchableModelField<>("authUserId", String.class); public static final SearchableModelField<AdminEvent> AUTH_USER_ID = new SearchableModelField<>("authUserId", String.class);

View file

@ -31,7 +31,6 @@ public interface ActionTokenValueModel {
public static final SearchableModelField<ActionTokenValueModel> USER_ID = new SearchableModelField<>("userId", String.class); public static final SearchableModelField<ActionTokenValueModel> USER_ID = new SearchableModelField<>("userId", String.class);
public static final SearchableModelField<ActionTokenValueModel> ACTION_ID = new SearchableModelField<>("actionId", String.class); public static final SearchableModelField<ActionTokenValueModel> ACTION_ID = new SearchableModelField<>("actionId", String.class);
public static final SearchableModelField<ActionTokenValueModel> ACTION_VERIFICATION_NONCE = new SearchableModelField<>("actionVerificationNonce", String.class); public static final SearchableModelField<ActionTokenValueModel> ACTION_VERIFICATION_NONCE = new SearchableModelField<>("actionVerificationNonce", String.class);
public static final SearchableModelField<ActionTokenValueModel> EXPIRATION = new SearchableModelField<>("expiration", Long.class);
} }
/** /**

View file

@ -35,7 +35,6 @@ public interface AuthenticatedClientSessionModel extends CommonClientSessionMode
public static final SearchableModelField<AuthenticatedClientSessionModel> USER_SESSION_ID = new SearchableModelField<>("userSessionId", String.class); public static final SearchableModelField<AuthenticatedClientSessionModel> USER_SESSION_ID = new SearchableModelField<>("userSessionId", String.class);
public static final SearchableModelField<AuthenticatedClientSessionModel> IS_OFFLINE = new SearchableModelField<>("isOffline", Boolean.class); public static final SearchableModelField<AuthenticatedClientSessionModel> IS_OFFLINE = new SearchableModelField<>("isOffline", Boolean.class);
public static final SearchableModelField<AuthenticatedClientSessionModel> TIMESTAMP = new SearchableModelField<>("timestamp", Long.class); public static final SearchableModelField<AuthenticatedClientSessionModel> TIMESTAMP = new SearchableModelField<>("timestamp", Long.class);
public static final SearchableModelField<AuthenticatedClientSessionModel> EXPIRATION = new SearchableModelField<>("expiration", Long.class);
} }
String STARTED_AT_NOTE = "startedAt"; String STARTED_AT_NOTE = "startedAt";

View file

@ -44,7 +44,6 @@ public interface UserSessionModel {
public static final SearchableModelField<UserSessionModel> BROKER_USER_ID = new SearchableModelField<>("brokerUserId", String.class); public static final SearchableModelField<UserSessionModel> BROKER_USER_ID = new SearchableModelField<>("brokerUserId", String.class);
public static final SearchableModelField<UserSessionModel> IS_OFFLINE = new SearchableModelField<>("isOffline", Boolean.class); public static final SearchableModelField<UserSessionModel> IS_OFFLINE = new SearchableModelField<>("isOffline", Boolean.class);
public static final SearchableModelField<UserSessionModel> LAST_SESSION_REFRESH = new SearchableModelField<>("lastSessionRefresh", Long.class); public static final SearchableModelField<UserSessionModel> LAST_SESSION_REFRESH = new SearchableModelField<>("lastSessionRefresh", Long.class);
public static final SearchableModelField<UserSessionModel> EXPIRATION = new SearchableModelField<>("expiration", Long.class);
} }
/** /**

View file

@ -74,12 +74,19 @@ public interface AuthenticationSessionProvider extends Provider {
/** /**
* Remove expired authentication sessions in all the realms * Remove expired authentication sessions in all the realms
*
* @deprecated manual removal of expired entities should not be used anymore. It is responsibility of the store
* implementation to handle expirable entities
*/ */
void removeAllExpired(); void removeAllExpired();
/** /**
* Removes all expired root authentication sessions for the given realm. * Removes all expired root authentication sessions for the given realm.
* @param realm {@code RealmModel} Can't be {@code null}. * @param realm {@code RealmModel} Can't be {@code null}.
*
*
* @deprecated manual removal of expired entities should not be used anymore. It is responsibility of the store
* implementation to handle expirable entities
*/ */
void removeExpired(RealmModel realm); void removeExpired(RealmModel realm);

View file

@ -34,7 +34,6 @@ public interface RootAuthenticationSessionModel {
public static class SearchableFields { public static class SearchableFields {
public static final SearchableModelField<RootAuthenticationSessionModel> ID = new SearchableModelField<>("id", String.class); public static final SearchableModelField<RootAuthenticationSessionModel> ID = new SearchableModelField<>("id", String.class);
public static final SearchableModelField<RootAuthenticationSessionModel> REALM_ID = new SearchableModelField<>("realmId", String.class); public static final SearchableModelField<RootAuthenticationSessionModel> REALM_ID = new SearchableModelField<>("realmId", String.class);
public static final SearchableModelField<RootAuthenticationSessionModel> EXPIRATION = new SearchableModelField<>("expiration", Long.class);
} }
/** /**