Add HotRod no downtime store for events

Closes #9676
This commit is contained in:
Michal Hajas 2022-05-18 15:21:41 +02:00 committed by Hynek Mlnařík
parent 0a8e132c7c
commit 09c0a69a8f
18 changed files with 664 additions and 36 deletions

View file

@ -26,6 +26,8 @@ import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.model.Scope; import org.keycloak.authorization.model.Scope;
import org.keycloak.common.Profile; import org.keycloak.common.Profile;
import org.keycloak.component.AmphibianProviderFactory; import org.keycloak.component.AmphibianProviderFactory;
import org.keycloak.events.Event;
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.models.AuthenticatedClientSessionModel; import org.keycloak.models.AuthenticatedClientSessionModel;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel; import org.keycloak.models.ClientScopeModel;
@ -47,6 +49,8 @@ import org.keycloak.models.map.authSession.MapRootAuthenticationSessionEntity;
import org.keycloak.models.map.clientscope.MapClientScopeEntity; import org.keycloak.models.map.clientscope.MapClientScopeEntity;
import org.keycloak.models.map.common.AbstractEntity; import org.keycloak.models.map.common.AbstractEntity;
import org.keycloak.models.map.common.StringKeyConverter; import org.keycloak.models.map.common.StringKeyConverter;
import org.keycloak.models.map.events.MapAdminEventEntity;
import org.keycloak.models.map.events.MapAuthEventEntity;
import org.keycloak.models.map.group.MapGroupEntity; import org.keycloak.models.map.group.MapGroupEntity;
import org.keycloak.models.map.loginFailure.MapUserLoginFailureEntity; import org.keycloak.models.map.loginFailure.MapUserLoginFailureEntity;
import org.keycloak.models.map.realm.MapRealmEntity; import org.keycloak.models.map.realm.MapRealmEntity;
@ -77,6 +81,10 @@ import org.keycloak.models.map.storage.hotRod.authorization.HotRodScopeEntity;
import org.keycloak.models.map.storage.hotRod.authorization.HotRodScopeEntityDelegate; import org.keycloak.models.map.storage.hotRod.authorization.HotRodScopeEntityDelegate;
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.events.HotRodAdminEventEntity;
import org.keycloak.models.map.storage.hotRod.events.HotRodAdminEventEntityDelegate;
import org.keycloak.models.map.storage.hotRod.events.HotRodAuthEventEntity;
import org.keycloak.models.map.storage.hotRod.events.HotRodAuthEventEntityDelegate;
import org.keycloak.models.map.storage.hotRod.loginFailure.HotRodUserLoginFailureEntity; import org.keycloak.models.map.storage.hotRod.loginFailure.HotRodUserLoginFailureEntity;
import org.keycloak.models.map.storage.hotRod.loginFailure.HotRodUserLoginFailureEntityDelegate; import org.keycloak.models.map.storage.hotRod.loginFailure.HotRodUserLoginFailureEntityDelegate;
import org.keycloak.models.map.storage.hotRod.role.HotRodRoleEntity; import org.keycloak.models.map.storage.hotRod.role.HotRodRoleEntity;
@ -180,6 +188,9 @@ public class HotRodMapStorageProviderFactory implements AmphibianProviderFactory
.constructor(MapPolicyEntity.class, HotRodPolicyEntityDelegate::new) .constructor(MapPolicyEntity.class, HotRodPolicyEntityDelegate::new)
.constructor(MapPermissionTicketEntity.class, HotRodPermissionTicketEntityDelegate::new) .constructor(MapPermissionTicketEntity.class, HotRodPermissionTicketEntityDelegate::new)
.constructor(MapAuthEventEntity.class, HotRodAuthEventEntityDelegate::new)
.constructor(MapAdminEventEntity.class, HotRodAdminEventEntityDelegate::new)
.build(); .build();
public static final Map<Class<?>, HotRodEntityDescriptor<?, ?>> ENTITY_DESCRIPTOR_MAP = new HashMap<>(); public static final Map<Class<?>, HotRodEntityDescriptor<?, ?>> ENTITY_DESCRIPTOR_MAP = new HashMap<>();
@ -293,6 +304,17 @@ public class HotRodMapStorageProviderFactory implements AmphibianProviderFactory
return "authz"; return "authz";
} }
}); });
// Events
ENTITY_DESCRIPTOR_MAP.put(Event.class,
new HotRodEntityDescriptor<>(Event.class,
HotRodAuthEventEntity.class,
HotRodAuthEventEntityDelegate::new));
ENTITY_DESCRIPTOR_MAP.put(AdminEvent.class,
new HotRodEntityDescriptor<>(AdminEvent.class,
HotRodAdminEventEntity.class,
HotRodAdminEventEntityDelegate::new));
} }
@Override @Override

View file

@ -19,6 +19,7 @@ package org.keycloak.models.map.storage.hotRod;
import org.keycloak.authorization.model.Policy; import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.Resource; import org.keycloak.authorization.model.Resource;
import org.keycloak.events.Event;
import org.keycloak.models.AuthenticatedClientSessionModel; import org.keycloak.models.AuthenticatedClientSessionModel;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.GroupModel; import org.keycloak.models.GroupModel;
@ -36,6 +37,7 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.UnaryOperator;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -49,10 +51,10 @@ public class IckleQueryMapModelCriteriaBuilder<E extends AbstractHotRodEntity, M
private final Class<E> hotRodEntityClass; private final Class<E> hotRodEntityClass;
private final StringBuilder whereClauseBuilder = new StringBuilder(INITIAL_BUILDER_CAPACITY); private final StringBuilder whereClauseBuilder = new StringBuilder(INITIAL_BUILDER_CAPACITY);
private final Map<String, Object> parameters; private final Map<String, Object> parameters;
private static final Pattern LIKE_PATTERN_DELIMITER = Pattern.compile("%+");
private static final Pattern NON_ANALYZED_FIELD_REGEX = Pattern.compile("[%_\\\\]"); private static final Pattern NON_ANALYZED_FIELD_REGEX = Pattern.compile("[%_\\\\]");
// private static final Pattern ANALYZED_FIELD_REGEX = Pattern.compile("[+!^\"~*?:\\\\]"); // TODO reevaluate once https://github.com/keycloak/keycloak/issues/9295 is fixed // private static final Pattern ANALYZED_FIELD_REGEX = Pattern.compile("[+!^\"~*?:\\\\]"); // TODO reevaluate once https://github.com/keycloak/keycloak/issues/9295 is fixed
private static final Pattern ANALYZED_FIELD_REGEX = Pattern.compile("\\\\"); // escape "\" with extra "\" private static final Pattern ANALYZED_FIELD_REGEX = Pattern.compile("\\\\"); // escape "\" with extra "\"
private static final Pattern SINGLE_PERCENT_CHARACTER = Pattern.compile("^%+$");
public static final Map<SearchableModelField<?>, String> INFINISPAN_NAME_OVERRIDES = new HashMap<>(); public static final Map<SearchableModelField<?>, String> INFINISPAN_NAME_OVERRIDES = new HashMap<>();
public static final Set<SearchableModelField<?>> ANALYZED_MODEL_FIELDS = new HashSet<>(); public static final Set<SearchableModelField<?>> ANALYZED_MODEL_FIELDS = new HashSet<>();
@ -87,6 +89,8 @@ public class IckleQueryMapModelCriteriaBuilder<E extends AbstractHotRodEntity, M
INFINISPAN_NAME_OVERRIDES.put(Policy.SearchableFields.SCOPE_ID, "scopeIds"); INFINISPAN_NAME_OVERRIDES.put(Policy.SearchableFields.SCOPE_ID, "scopeIds");
INFINISPAN_NAME_OVERRIDES.put(Policy.SearchableFields.ASSOCIATED_POLICY_ID, "associatedPolicyIds"); INFINISPAN_NAME_OVERRIDES.put(Policy.SearchableFields.ASSOCIATED_POLICY_ID, "associatedPolicyIds");
INFINISPAN_NAME_OVERRIDES.put(Policy.SearchableFields.CONFIG, "configs"); INFINISPAN_NAME_OVERRIDES.put(Policy.SearchableFields.CONFIG, "configs");
INFINISPAN_NAME_OVERRIDES.put(Event.SearchableFields.EVENT_TYPE, "type");
} }
static { static {
@ -223,21 +227,9 @@ public class IckleQueryMapModelCriteriaBuilder<E extends AbstractHotRodEntity, M
return whereClauseBuilder; return whereClauseBuilder;
} }
public static Object sanitize(Object value) { public static Object sanitizeNonAnalyzed(Object value) {
if (value instanceof String) { if (value instanceof String) {
String sValue = (String) value; return sanitizeEachUnitAndReplaceDelimiter((String) value, IckleQueryMapModelCriteriaBuilder::sanitizeSingleUnitNonAnalyzed, "%");
if(SINGLE_PERCENT_CHARACTER.matcher(sValue).matches()) {
return value;
}
boolean anyBeginning = sValue.startsWith("%");
boolean anyEnd = sValue.endsWith("%");
String sanitizedString = NON_ANALYZED_FIELD_REGEX.matcher(sValue.substring(anyBeginning ? 1 : 0, sValue.length() - (anyEnd ? 1 : 0)))
.replaceAll("\\\\\\\\" + "$0");
return (anyBeginning ? "%" : "") + sanitizedString + (anyEnd ? "%" : "");
} }
return value; return value;
@ -245,26 +237,31 @@ public class IckleQueryMapModelCriteriaBuilder<E extends AbstractHotRodEntity, M
public static Object sanitizeAnalyzed(Object value) { public static Object sanitizeAnalyzed(Object value) {
if (value instanceof String) { if (value instanceof String) {
String sValue = (String) value; return sanitizeEachUnitAndReplaceDelimiter((String) value, IckleQueryMapModelCriteriaBuilder::sanitizeSingleUnitAnalyzed, "*");
boolean anyBeginning = sValue.startsWith("%");
boolean anyEnd = sValue.endsWith("%");
if(SINGLE_PERCENT_CHARACTER.matcher(sValue).matches()) {
return "*";
}
String sanitizedString = ANALYZED_FIELD_REGEX.matcher(sValue.substring(anyBeginning ? 1 : 0, sValue.length() - (anyEnd ? 1 : 0)))
.replaceAll("\\\\\\\\"); // escape "\" with extra "\"
// .replaceAll("\\\\\\\\" + "$0"); skipped for now because Infinispan is not able to escape
// special characters for analyzed fields
// TODO reevaluate once https://github.com/keycloak/keycloak/issues/9295 is fixed
return (anyBeginning ? "*" : "") + sanitizedString + (anyEnd ? "*" : "");
} }
return value; return value;
} }
private static String sanitizeEachUnitAndReplaceDelimiter(String value, UnaryOperator<String> sanitizeSingleUnit, String replacement) {
return LIKE_PATTERN_DELIMITER.splitAsStream(value)
.map(sanitizeSingleUnit)
.collect(Collectors.joining(replacement))
+ (value.endsWith("%") ? replacement : "");
}
private static String sanitizeSingleUnitNonAnalyzed(String value) {
return NON_ANALYZED_FIELD_REGEX.matcher(value).replaceAll("\\\\\\\\" + "$0");
}
private static String sanitizeSingleUnitAnalyzed(String value) {
return ANALYZED_FIELD_REGEX.matcher(value).replaceAll("\\\\\\\\"); // escape "\" with extra "\"
// .replaceAll("\\\\\\\\" + "$0"); skipped for now because Infinispan is not able to escape
// special characters for analyzed fields
// TODO reevaluate once https://github.com/keycloak/keycloak/issues/9295 is fixed
}
public static boolean isAnalyzedModelField(SearchableModelField<?> modelField) { public static boolean isAnalyzedModelField(SearchableModelField<?> modelField) {
return ANALYZED_MODEL_FIELDS.contains(modelField); return ANALYZED_MODEL_FIELDS.contains(modelField);
} }

View file

@ -95,13 +95,13 @@ public class IckleQueryOperators {
} }
private static String iLike(String modelFieldName, Object[] values, Map<String, Object> parameters) { private static String iLike(String modelFieldName, Object[] values, Map<String, Object> parameters) {
String sanitizedValue = (String) IckleQueryMapModelCriteriaBuilder.sanitize(values[0]); String sanitizedValue = (String) IckleQueryMapModelCriteriaBuilder.sanitizeNonAnalyzed(values[0]);
return singleValueOperator(ModelCriteriaBuilder.Operator.ILIKE) return singleValueOperator(ModelCriteriaBuilder.Operator.ILIKE)
.combine(modelFieldName + "Lowercase", new String[] {sanitizedValue.toLowerCase()}, parameters); .combine(modelFieldName + "Lowercase", new String[] {sanitizedValue.toLowerCase()}, parameters);
} }
private static String like(String modelFieldName, Object[] values, Map<String, Object> parameters) { private static String like(String modelFieldName, Object[] values, Map<String, Object> parameters) {
String sanitizedValue = (String) IckleQueryMapModelCriteriaBuilder.sanitize(values[0]); String sanitizedValue = (String) IckleQueryMapModelCriteriaBuilder.sanitizeNonAnalyzed(values[0]);
return singleValueOperator(ModelCriteriaBuilder.Operator.LIKE) return singleValueOperator(ModelCriteriaBuilder.Operator.LIKE)
.combine(modelFieldName, new String[] {sanitizedValue}, parameters); .combine(modelFieldName, new String[] {sanitizedValue}, parameters);
} }

View file

@ -18,17 +18,25 @@
package org.keycloak.models.map.storage.hotRod; package org.keycloak.models.map.storage.hotRod;
import org.keycloak.authorization.model.Policy; import org.keycloak.authorization.model.Policy;
import org.keycloak.events.Event;
import org.keycloak.events.EventType;
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.events.admin.OperationType;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel; import org.keycloak.models.UserSessionModel;
import org.keycloak.models.map.storage.CriterionNotSupportedException; import org.keycloak.models.map.storage.CriterionNotSupportedException;
import org.keycloak.models.map.storage.ModelCriteriaBuilder; import org.keycloak.models.map.storage.ModelCriteriaBuilder;
import org.keycloak.models.map.storage.hotRod.common.HotRodTypesUtils;
import org.keycloak.storage.SearchableModelField; import org.keycloak.storage.SearchableModelField;
import org.keycloak.storage.StorageId; import org.keycloak.storage.StorageId;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.keycloak.models.map.storage.hotRod.IckleQueryMapModelCriteriaBuilder.getFieldName; import static org.keycloak.models.map.storage.hotRod.IckleQueryMapModelCriteriaBuilder.getFieldName;
import static org.keycloak.models.map.storage.hotRod.IckleQueryMapModelCriteriaBuilder.sanitizeAnalyzed; import static org.keycloak.models.map.storage.hotRod.IckleQueryMapModelCriteriaBuilder.sanitizeAnalyzed;
@ -58,6 +66,8 @@ public class IckleQueryWhereClauses {
WHERE_CLAUSE_PRODUCER_OVERRIDES.put(UserModel.SearchableFields.CONSENT_CLIENT_FEDERATION_LINK, IckleQueryWhereClauses::whereClauseForConsentClientFederationLink); WHERE_CLAUSE_PRODUCER_OVERRIDES.put(UserModel.SearchableFields.CONSENT_CLIENT_FEDERATION_LINK, IckleQueryWhereClauses::whereClauseForConsentClientFederationLink);
WHERE_CLAUSE_PRODUCER_OVERRIDES.put(UserSessionModel.SearchableFields.CORRESPONDING_SESSION_ID, IckleQueryWhereClauses::whereClauseForCorrespondingSessionId); WHERE_CLAUSE_PRODUCER_OVERRIDES.put(UserSessionModel.SearchableFields.CORRESPONDING_SESSION_ID, IckleQueryWhereClauses::whereClauseForCorrespondingSessionId);
WHERE_CLAUSE_PRODUCER_OVERRIDES.put(Policy.SearchableFields.CONFIG, IckleQueryWhereClauses::whereClauseForPolicyConfig); WHERE_CLAUSE_PRODUCER_OVERRIDES.put(Policy.SearchableFields.CONFIG, IckleQueryWhereClauses::whereClauseForPolicyConfig);
WHERE_CLAUSE_PRODUCER_OVERRIDES.put(Event.SearchableFields.EVENT_TYPE, IckleQueryWhereClauses::whereClauseForEventType);
WHERE_CLAUSE_PRODUCER_OVERRIDES.put(AdminEvent.SearchableFields.OPERATION_TYPE, IckleQueryWhereClauses::whereClauseForOperationType);
} }
@FunctionalInterface @FunctionalInterface
@ -204,4 +214,31 @@ public class IckleQueryWhereClauses {
String valueClause = IckleQueryOperators.combineExpressions(op, modelFieldName + ".value", realValues, parameters); String valueClause = IckleQueryOperators.combineExpressions(op, modelFieldName + ".value", realValues, parameters);
return "(" + nameClause + ")" + " AND " + "(" + valueClause + ")"; return "(" + nameClause + ")" + " AND " + "(" + valueClause + ")";
} }
private static String whereClauseForEventType(String modelFieldName, ModelCriteriaBuilder.Operator op, Object[] values, Map<String, Object> parameters) {
if (values != null && values.length == 1) {
if (values[0] instanceof EventType) {
values[0] = HotRodTypesUtils.migrateEventTypeToHotRodEventType((EventType) values[0]);
} else if (values[0] instanceof Collection) {
values[0] = ((Collection<EventType>) values[0]).stream().map(HotRodTypesUtils::migrateEventTypeToHotRodEventType).collect(Collectors.toSet());
} else if (values[0] instanceof Stream) {
values[0] = ((Stream<EventType>) values[0]).map(HotRodTypesUtils::migrateEventTypeToHotRodEventType);
}
}
return produceWhereClause(modelFieldName, op, values, parameters);
}
private static String whereClauseForOperationType(String modelFieldName, ModelCriteriaBuilder.Operator op, Object[] values, Map<String, Object> parameters) {
if (values != null && values.length == 1) {
if (values[0] instanceof OperationType) {
values[0] = HotRodTypesUtils.migrateOperationTypeToHotRodOperationType((OperationType) values[0]);
} else if (values[0] instanceof Collection) {
values[0] = ((Collection<OperationType>) values[0]).stream().map(HotRodTypesUtils::migrateOperationTypeToHotRodOperationType).collect(Collectors.toSet());
} else if (values[0] instanceof Stream) {
values[0] = ((Stream<OperationType>) values[0]).map(HotRodTypesUtils::migrateOperationTypeToHotRodOperationType);
}
}
return produceWhereClause(modelFieldName, op, values, parameters);
}
} }

View file

@ -17,6 +17,8 @@
package org.keycloak.models.map.storage.hotRod.common; package org.keycloak.models.map.storage.hotRod.common;
import org.keycloak.events.EventType;
import org.keycloak.events.admin.OperationType;
import org.keycloak.models.AuthenticationExecutionModel; import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.UserSessionModel; import org.keycloak.models.UserSessionModel;
import org.keycloak.models.map.common.AbstractEntity; import org.keycloak.models.map.common.AbstractEntity;
@ -24,6 +26,8 @@ import org.keycloak.models.map.storage.hotRod.authSession.HotRodAuthenticationSe
import org.keycloak.models.map.storage.hotRod.authorization.HotRodDecisionStrategy; import org.keycloak.models.map.storage.hotRod.authorization.HotRodDecisionStrategy;
import org.keycloak.models.map.storage.hotRod.authorization.HotRodLogic; import org.keycloak.models.map.storage.hotRod.authorization.HotRodLogic;
import org.keycloak.models.map.storage.hotRod.authorization.HotRodPolicyEnforcementMode; import org.keycloak.models.map.storage.hotRod.authorization.HotRodPolicyEnforcementMode;
import org.keycloak.models.map.storage.hotRod.events.HotRodEventType;
import org.keycloak.models.map.storage.hotRod.events.HotRodOperationType;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodLocalizationTexts; import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodLocalizationTexts;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodRequirement; import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodRequirement;
import org.keycloak.models.map.storage.hotRod.user.HotRodUserConsentEntity; import org.keycloak.models.map.storage.hotRod.user.HotRodUserConsentEntity;
@ -195,4 +199,20 @@ public class HotRodTypesUtils {
public static Logic migrateHotRodLogicToLogic(HotRodLogic p0) { public static Logic migrateHotRodLogicToLogic(HotRodLogic p0) {
return p0 == null ? null : Logic.values()[p0.ordinal()]; return p0 == null ? null : Logic.values()[p0.ordinal()];
} }
public static OperationType migrateHotRodOperationTypeToOperationType(HotRodOperationType p0) {
return p0 == null ? null : OperationType.values()[p0.ordinal()];
}
public static HotRodOperationType migrateOperationTypeToHotRodOperationType(OperationType p0) {
return p0 == null ? null : HotRodOperationType.values()[p0.ordinal()];
}
public static HotRodEventType migrateEventTypeToHotRodEventType(EventType p0) {
return p0 == null ? null : HotRodEventType.values()[p0.ordinal()];
}
public static EventType migrateHotRodEventTypeToEventType(HotRodEventType p0) {
return p0 == null ? null : EventType.values()[p0.ordinal()];
}
} }

View file

@ -33,6 +33,10 @@ import org.keycloak.models.map.storage.hotRod.authorization.HotRodScopeEntity;
import org.keycloak.models.map.storage.hotRod.client.HotRodClientEntity; import org.keycloak.models.map.storage.hotRod.client.HotRodClientEntity;
import org.keycloak.models.map.storage.hotRod.client.HotRodProtocolMapperEntity; import org.keycloak.models.map.storage.hotRod.client.HotRodProtocolMapperEntity;
import org.keycloak.models.map.storage.hotRod.clientscope.HotRodClientScopeEntity; import org.keycloak.models.map.storage.hotRod.clientscope.HotRodClientScopeEntity;
import org.keycloak.models.map.storage.hotRod.events.HotRodAdminEventEntity;
import org.keycloak.models.map.storage.hotRod.events.HotRodAuthEventEntity;
import org.keycloak.models.map.storage.hotRod.events.HotRodEventType;
import org.keycloak.models.map.storage.hotRod.events.HotRodOperationType;
import org.keycloak.models.map.storage.hotRod.group.HotRodGroupEntity; import org.keycloak.models.map.storage.hotRod.group.HotRodGroupEntity;
import org.keycloak.models.map.storage.hotRod.loginFailure.HotRodUserLoginFailureEntity; import org.keycloak.models.map.storage.hotRod.loginFailure.HotRodUserLoginFailureEntity;
import org.keycloak.models.map.storage.hotRod.realm.HotRodRealmEntity; import org.keycloak.models.map.storage.hotRod.realm.HotRodRealmEntity;
@ -123,6 +127,12 @@ import org.keycloak.models.map.storage.hotRod.userSession.HotRodUserSessionEntit
HotRodLogic.class, HotRodLogic.class,
HotRodPolicyEnforcementMode.class, HotRodPolicyEnforcementMode.class,
// Events
HotRodAuthEventEntity.class,
HotRodEventType.class,
HotRodAdminEventEntity.class,
HotRodOperationType.class,
// Common // Common
HotRodPair.class, HotRodPair.class,
HotRodStringPair.class, HotRodStringPair.class,

View file

@ -0,0 +1,111 @@
/*
* Copyright 2022 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.models.map.storage.hotRod.events;
import org.infinispan.protostream.annotations.ProtoDoc;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation;
import org.keycloak.models.map.events.MapAdminEventEntity;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
import org.keycloak.models.map.storage.hotRod.common.UpdatableHotRodEntityDelegateImpl;
@GenerateHotRodEntityImplementation(
implementInterface = "org.keycloak.models.map.events.MapAdminEventEntity",
inherits = "org.keycloak.models.map.storage.hotRod.events.HotRodAdminEventEntity.AbstractHotRodAdminEventEntityDelegate"
)
@ProtoDoc("@Indexed")
public class HotRodAdminEventEntity extends AbstractHotRodEntity {
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 1)
public Integer entityVersion = 1;
@ProtoField(number = 2)
public String id;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 3)
public Long expiration;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 4)
public Long timestamp;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 5)
public HotRodOperationType operationType;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 6)
public String authClientId;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 7)
public String authIpAddress;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 8)
public String authRealmId;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 9)
public String authUserId;
@ProtoField(number = 10)
public String error;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 11)
public String realmId;
@ProtoField(number = 12)
public String representation;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 13)
public String resourcePath;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 14)
public String resourceType;
public static abstract class AbstractHotRodAdminEventEntityDelegate extends UpdatableHotRodEntityDelegateImpl<HotRodAdminEventEntity> implements MapAdminEventEntity {
@Override
public String getId() {
return getHotRodEntity().id;
}
@Override
public void setId(String id) {
HotRodAdminEventEntity entity = getHotRodEntity();
if (entity.id != null) throw new IllegalStateException("Id cannot be changed");
entity.id = id;
entity.updated |= id != null;
}
}
@Override
public boolean equals(Object o) {
return HotRodAdminEventEntityDelegate.entityEquals(this, o);
}
@Override
public int hashCode() {
return HotRodAdminEventEntityDelegate.entityHashCode(this);
}
}

View file

@ -0,0 +1,104 @@
/*
* Copyright 2022 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.models.map.storage.hotRod.events;
import org.infinispan.protostream.annotations.ProtoDoc;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation;
import org.keycloak.models.map.events.MapAuthEventEntity;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
import org.keycloak.models.map.storage.hotRod.common.HotRodPair;
import org.keycloak.models.map.storage.hotRod.common.UpdatableHotRodEntityDelegateImpl;
import java.util.Set;
@GenerateHotRodEntityImplementation(
implementInterface = "org.keycloak.models.map.events.MapAuthEventEntity",
inherits = "org.keycloak.models.map.storage.hotRod.events.HotRodAuthEventEntity.AbstractHotRodAuthEventEntityDelegate"
)
@ProtoDoc("@Indexed")
public class HotRodAuthEventEntity extends AbstractHotRodEntity {
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 1)
public Integer entityVersion = 1;
@ProtoField(number = 2)
public String id;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 3)
public HotRodEventType type;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 4)
public Long expiration;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 5)
public Long timestamp;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 6)
public String clientId;
@ProtoField(number = 7)
public String error;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 8)
public String ipAddress;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 9)
public String realmId;
@ProtoField(number = 10)
public String sessionId;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 11)
public String userId;
@ProtoField(number = 12)
public Set<HotRodPair<String, String>> details;
public static abstract class AbstractHotRodAuthEventEntityDelegate extends UpdatableHotRodEntityDelegateImpl<HotRodAuthEventEntity> implements MapAuthEventEntity {
@Override
public String getId() {
return getHotRodEntity().id;
}
@Override
public void setId(String id) {
HotRodAuthEventEntity entity = getHotRodEntity();
if (entity.id != null) throw new IllegalStateException("Id cannot be changed");
entity.id = id;
entity.updated |= id != null;
}
}
@Override
public boolean equals(Object o) {
return HotRodAuthEventEntityDelegate.entityEquals(this, o);
}
@Override
public int hashCode() {
return HotRodAuthEventEntityDelegate.entityHashCode(this);
}
}

View file

@ -0,0 +1,238 @@
/*
* Copyright 2022 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.models.map.storage.hotRod.events;
import org.infinispan.protostream.annotations.ProtoEnumValue;
public enum HotRodEventType {
@ProtoEnumValue(number = 0)
LOGIN,
@ProtoEnumValue(number = 1)
LOGIN_ERROR,
@ProtoEnumValue(number = 2)
REGISTER,
@ProtoEnumValue(number = 3)
REGISTER_ERROR,
@ProtoEnumValue(number = 4)
LOGOUT,
@ProtoEnumValue(number = 5)
LOGOUT_ERROR,
@ProtoEnumValue(number = 6)
CODE_TO_TOKEN,
@ProtoEnumValue(number = 7)
CODE_TO_TOKEN_ERROR,
@ProtoEnumValue(number = 8)
CLIENT_LOGIN,
@ProtoEnumValue(number = 9)
CLIENT_LOGIN_ERROR,
@ProtoEnumValue(number = 10)
REFRESH_TOKEN,
@ProtoEnumValue(number = 11)
REFRESH_TOKEN_ERROR,
@ProtoEnumValue(number = 12)
/**
* @deprecated see KEYCLOAK-2266
*/
@Deprecated
VALIDATE_ACCESS_TOKEN,
@ProtoEnumValue(number = 13)
@Deprecated
VALIDATE_ACCESS_TOKEN_ERROR,
@ProtoEnumValue(number = 14)
INTROSPECT_TOKEN,
@ProtoEnumValue(number = 15)
INTROSPECT_TOKEN_ERROR,
@ProtoEnumValue(number = 16)
FEDERATED_IDENTITY_LINK,
@ProtoEnumValue(number = 17)
FEDERATED_IDENTITY_LINK_ERROR,
@ProtoEnumValue(number = 18)
REMOVE_FEDERATED_IDENTITY,
@ProtoEnumValue(number = 19)
REMOVE_FEDERATED_IDENTITY_ERROR,
@ProtoEnumValue(number = 20)
UPDATE_EMAIL,
@ProtoEnumValue(number = 21)
UPDATE_EMAIL_ERROR,
@ProtoEnumValue(number = 22)
UPDATE_PROFILE,
@ProtoEnumValue(number = 23)
UPDATE_PROFILE_ERROR,
@ProtoEnumValue(number = 24)
UPDATE_PASSWORD,
@ProtoEnumValue(number = 25)
UPDATE_PASSWORD_ERROR,
@ProtoEnumValue(number = 26)
UPDATE_TOTP,
@ProtoEnumValue(number = 27)
UPDATE_TOTP_ERROR,
@ProtoEnumValue(number = 28)
VERIFY_EMAIL,
@ProtoEnumValue(number = 29)
VERIFY_EMAIL_ERROR,
@ProtoEnumValue(number = 30)
VERIFY_PROFILE,
@ProtoEnumValue(number = 31)
VERIFY_PROFILE_ERROR,
@ProtoEnumValue(number = 32)
REMOVE_TOTP,
@ProtoEnumValue(number = 33)
REMOVE_TOTP_ERROR,
@ProtoEnumValue(number = 34)
GRANT_CONSENT,
@ProtoEnumValue(number = 35)
GRANT_CONSENT_ERROR,
@ProtoEnumValue(number = 36)
UPDATE_CONSENT,
@ProtoEnumValue(number = 37)
UPDATE_CONSENT_ERROR,
@ProtoEnumValue(number = 38)
REVOKE_GRANT,
@ProtoEnumValue(number = 39)
REVOKE_GRANT_ERROR,
@ProtoEnumValue(number = 40)
SEND_VERIFY_EMAIL,
@ProtoEnumValue(number = 41)
SEND_VERIFY_EMAIL_ERROR,
@ProtoEnumValue(number = 42)
SEND_RESET_PASSWORD,
@ProtoEnumValue(number = 43)
SEND_RESET_PASSWORD_ERROR,
@ProtoEnumValue(number = 44)
SEND_IDENTITY_PROVIDER_LINK,
@ProtoEnumValue(number = 45)
SEND_IDENTITY_PROVIDER_LINK_ERROR,
@ProtoEnumValue(number = 46)
RESET_PASSWORD,
@ProtoEnumValue(number = 47)
RESET_PASSWORD_ERROR,
@ProtoEnumValue(number = 48)
RESTART_AUTHENTICATION,
@ProtoEnumValue(number = 49)
RESTART_AUTHENTICATION_ERROR,
@ProtoEnumValue(number = 50)
INVALID_SIGNATURE,
@ProtoEnumValue(number = 51)
INVALID_SIGNATURE_ERROR,
@ProtoEnumValue(number = 52)
REGISTER_NODE,
@ProtoEnumValue(number = 53)
REGISTER_NODE_ERROR,
@ProtoEnumValue(number = 54)
UNREGISTER_NODE,
@ProtoEnumValue(number = 55)
UNREGISTER_NODE_ERROR,
@ProtoEnumValue(number = 56)
USER_INFO_REQUEST,
@ProtoEnumValue(number = 57)
USER_INFO_REQUEST_ERROR,
@ProtoEnumValue(number = 58)
IDENTITY_PROVIDER_LINK_ACCOUNT,
@ProtoEnumValue(number = 59)
IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR,
@ProtoEnumValue(number = 60)
IDENTITY_PROVIDER_LOGIN,
@ProtoEnumValue(number = 61)
IDENTITY_PROVIDER_LOGIN_ERROR,
@ProtoEnumValue(number = 62)
IDENTITY_PROVIDER_FIRST_LOGIN,
@ProtoEnumValue(number = 63)
IDENTITY_PROVIDER_FIRST_LOGIN_ERROR,
@ProtoEnumValue(number = 64)
IDENTITY_PROVIDER_POST_LOGIN,
@ProtoEnumValue(number = 65)
IDENTITY_PROVIDER_POST_LOGIN_ERROR,
@ProtoEnumValue(number = 66)
IDENTITY_PROVIDER_RESPONSE,
@ProtoEnumValue(number = 67)
IDENTITY_PROVIDER_RESPONSE_ERROR,
@ProtoEnumValue(number = 68)
IDENTITY_PROVIDER_RETRIEVE_TOKEN,
@ProtoEnumValue(number = 69)
IDENTITY_PROVIDER_RETRIEVE_TOKEN_ERROR,
@ProtoEnumValue(number = 70)
IMPERSONATE,
@ProtoEnumValue(number = 71)
IMPERSONATE_ERROR,
@ProtoEnumValue(number = 72)
CUSTOM_REQUIRED_ACTION,
@ProtoEnumValue(number = 73)
CUSTOM_REQUIRED_ACTION_ERROR,
@ProtoEnumValue(number = 74)
EXECUTE_ACTIONS,
@ProtoEnumValue(number = 75)
EXECUTE_ACTIONS_ERROR,
@ProtoEnumValue(number = 76)
EXECUTE_ACTION_TOKEN,
@ProtoEnumValue(number = 77)
EXECUTE_ACTION_TOKEN_ERROR,
@ProtoEnumValue(number = 78)
CLIENT_INFO,
@ProtoEnumValue(number = 79)
CLIENT_INFO_ERROR,
@ProtoEnumValue(number = 80)
CLIENT_REGISTER,
@ProtoEnumValue(number = 81)
CLIENT_REGISTER_ERROR,
@ProtoEnumValue(number = 82)
CLIENT_UPDATE,
@ProtoEnumValue(number = 83)
CLIENT_UPDATE_ERROR,
@ProtoEnumValue(number = 84)
CLIENT_DELETE,
@ProtoEnumValue(number = 85)
CLIENT_DELETE_ERROR,
@ProtoEnumValue(number = 86)
CLIENT_INITIATED_ACCOUNT_LINKING,
@ProtoEnumValue(number = 87)
CLIENT_INITIATED_ACCOUNT_LINKING_ERROR,
@ProtoEnumValue(number = 88)
TOKEN_EXCHANGE,
@ProtoEnumValue(number = 89)
TOKEN_EXCHANGE_ERROR,
@ProtoEnumValue(number = 90)
OAUTH2_DEVICE_AUTH,
@ProtoEnumValue(number = 91)
OAUTH2_DEVICE_AUTH_ERROR,
@ProtoEnumValue(number = 92)
OAUTH2_DEVICE_VERIFY_USER_CODE,
@ProtoEnumValue(number = 93)
OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR,
@ProtoEnumValue(number = 94)
OAUTH2_DEVICE_CODE_TO_TOKEN,
@ProtoEnumValue(number = 95)
OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR,
@ProtoEnumValue(number = 96)
AUTHREQID_TO_TOKEN,
@ProtoEnumValue(number = 97)
AUTHREQID_TO_TOKEN_ERROR,
@ProtoEnumValue(number = 98)
PERMISSION_TOKEN,
@ProtoEnumValue(number = 99)
PERMISSION_TOKEN_ERROR,
@ProtoEnumValue(number = 100)
DELETE_ACCOUNT,
@ProtoEnumValue(number = 101)
DELETE_ACCOUNT_ERROR,
@ProtoEnumValue(number = 102)
// PAR request.
PUSHED_AUTHORIZATION_REQUEST,
@ProtoEnumValue(number = 103)
PUSHED_AUTHORIZATION_REQUEST_ERROR;
}

View file

@ -0,0 +1,31 @@
/*
* Copyright 2022 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.models.map.storage.hotRod.events;
import org.infinispan.protostream.annotations.ProtoEnumValue;
public enum HotRodOperationType {
@ProtoEnumValue(number = 0)
CREATE,
@ProtoEnumValue(number = 1)
UPDATE,
@ProtoEnumValue(number = 2)
DELETE,
@ProtoEnumValue(number = 3)
ACTION;
}

View file

@ -100,5 +100,21 @@
</indexed-entities> </indexed-entities>
</indexing> </indexing>
</distributed-cache> </distributed-cache>
<distributed-cache name="auth-events" mode="SYNC">
<encoding media-type="application/x-protostream"/>
<indexing>
<indexed-entities>
<indexed-entity>kc.HotRodAuthEventEntity</indexed-entity>
</indexed-entities>
</indexing>
</distributed-cache>
<distributed-cache name="admin-events" mode="SYNC">
<encoding media-type="application/x-protostream"/>
<indexing>
<indexed-entities>
<indexed-entity>kc.HotRodAdminEventEntity</indexed-entity>
</indexed-entities>
</indexing>
</distributed-cache>
</cache-container> </cache-container>
</infinispan> </infinispan>

View file

@ -102,5 +102,21 @@
</indexed-entities> </indexed-entities>
</indexing> </indexing>
</distributed-cache> </distributed-cache>
<distributed-cache name="auth-events" mode="SYNC">
<encoding media-type="application/x-protostream"/>
<indexing>
<indexed-entities>
<indexed-entity>kc.HotRodAuthEventEntity</indexed-entity>
</indexed-entities>
</indexing>
</distributed-cache>
<distributed-cache name="admin-events" mode="SYNC">
<encoding media-type="application/x-protostream"/>
<indexing>
<indexed-entities>
<indexed-entity>kc.HotRodAdminEventEntity</indexed-entity>
</indexed-entities>
</indexing>
</distributed-cache>
</cache-container> </cache-container>
</infinispan> </infinispan>

View file

@ -34,7 +34,7 @@ public class AdminEvent {
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);
public static final SearchableModelField<AdminEvent> AUTH_IP_ADDRESS = new SearchableModelField<>("authIpAddress", String.class); public static final SearchableModelField<AdminEvent> AUTH_IP_ADDRESS = new SearchableModelField<>("authIpAddress", String.class);
public static final SearchableModelField<AdminEvent> OPERATION_TYPE = new SearchableModelField<>("operationType", OperationType.class); public static final SearchableModelField<AdminEvent> OPERATION_TYPE = new SearchableModelField<>("operationType", OperationType.class);
public static final SearchableModelField<AdminEvent> RESOURCE_TYPE = new SearchableModelField<>("resourceType", ResourceType.class); public static final SearchableModelField<AdminEvent> RESOURCE_TYPE = new SearchableModelField<>("resourceType", String.class);
public static final SearchableModelField<AdminEvent> RESOURCE_PATH = new SearchableModelField<>("resourcePath", String.class); public static final SearchableModelField<AdminEvent> RESOURCE_PATH = new SearchableModelField<>("resourcePath", String.class);
} }

View file

@ -1506,6 +1506,7 @@
<keycloak.realm.map.storage.provider>hotrod</keycloak.realm.map.storage.provider> <keycloak.realm.map.storage.provider>hotrod</keycloak.realm.map.storage.provider>
<keycloak.userSession.map.storage.provider>hotrod</keycloak.userSession.map.storage.provider> <keycloak.userSession.map.storage.provider>hotrod</keycloak.userSession.map.storage.provider>
<keycloak.authorization.map.storage.provider>hotrod</keycloak.authorization.map.storage.provider> <keycloak.authorization.map.storage.provider>hotrod</keycloak.authorization.map.storage.provider>
<keycloak.eventStore.map.storage.provider>hotrod</keycloak.eventStore.map.storage.provider>
</systemPropertyVariables> </systemPropertyVariables>
</configuration> </configuration>
</plugin> </plugin>

View file

@ -98,5 +98,21 @@
</indexed-entities> </indexed-entities>
</indexing> </indexing>
</distributed-cache> </distributed-cache>
<distributed-cache name="auth-events" mode="SYNC">
<encoding media-type="application/x-protostream"/>
<indexing>
<indexed-entities>
<indexed-entity>kc.HotRodAuthEventEntity</indexed-entity>
</indexed-entities>
</indexing>
</distributed-cache>
<distributed-cache name="admin-events" mode="SYNC">
<encoding media-type="application/x-protostream"/>
<indexing>
<indexed-entities>
<indexed-entity>kc.HotRodAdminEventEntity</indexed-entity>
</indexed-entities>
</indexing>
</distributed-cache>
</cache-container> </cache-container>
</infinispan> </infinispan>

View file

@ -90,8 +90,8 @@ public class HotRodMapStorage extends KeycloakModelParameters {
.config("storage-client-sessions.provider", HotRodMapStorageProviderFactory.PROVIDER_ID) .config("storage-client-sessions.provider", HotRodMapStorageProviderFactory.PROVIDER_ID)
.spi(UserLoginFailureSpi.NAME).provider(MapUserLoginFailureProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) .spi(UserLoginFailureSpi.NAME).provider(MapUserLoginFailureProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID)
.spi("dblock").provider(NoLockingDBLockProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) .spi("dblock").provider(NoLockingDBLockProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID)
.spi(EventStoreSpi.NAME).provider(MapUserSessionProviderFactory.PROVIDER_ID).config("storage-admin-events.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) .spi(EventStoreSpi.NAME).provider(MapUserSessionProviderFactory.PROVIDER_ID).config("storage-admin-events.provider", HotRodMapStorageProviderFactory.PROVIDER_ID)
.config("storage-auth-events.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID); .config("storage-auth-events.provider", HotRodMapStorageProviderFactory.PROVIDER_ID);
cf.spi(MapStorageSpi.NAME) cf.spi(MapStorageSpi.NAME)
.provider(ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) .provider(ConcurrentHashMapStorageProviderFactory.PROVIDER_ID)

View file

@ -305,6 +305,7 @@
<systemProperty><key>keycloak.authorization.provider</key><value>map</value></systemProperty> <systemProperty><key>keycloak.authorization.provider</key><value>map</value></systemProperty>
<systemProperty><key>keycloak.actionToken.provider</key><value>map</value></systemProperty> <systemProperty><key>keycloak.actionToken.provider</key><value>map</value></systemProperty>
<systemProperty><key>keycloak.singleUseObject.provider</key><value>map</value></systemProperty> <systemProperty><key>keycloak.singleUseObject.provider</key><value>map</value></systemProperty>
<systemProperty><key>keycloak.eventsStore.provider</key><value>map</value></systemProperty>
<systemProperty><key>keycloak.authorizationCache.enabled</key><value>false</value></systemProperty> <systemProperty><key>keycloak.authorizationCache.enabled</key><value>false</value></systemProperty>
<systemProperty><key>keycloak.realmCache.enabled</key><value>false</value></systemProperty> <systemProperty><key>keycloak.realmCache.enabled</key><value>false</value></systemProperty>
<systemProperty><key>keycloak.userCache.enabled</key><value>false</value></systemProperty> <systemProperty><key>keycloak.userCache.enabled</key><value>false</value></systemProperty>

View file

@ -11,7 +11,15 @@
}, },
"eventsStore": { "eventsStore": {
"provider": "${keycloak.eventsStore.provider:}" "provider": "${keycloak.eventsStore.provider:jpa}",
"map": {
"storage-admin-events": {
"provider": "${keycloak.eventStore.map.storage.provider:concurrenthashmap}"
},
"storage-auth-events": {
"provider": "${keycloak.eventStore.map.storage.provider:concurrenthashmap}"
}
}
}, },
"deploymentState": { "deploymentState": {