Add HotRod no downtime store for Realms

Closes #9670
This commit is contained in:
Michal Hajas 2022-03-17 12:35:23 +01:00 committed by Hynek Mlnařík
parent 3bb4081bd1
commit 1f2ebf4cba
30 changed files with 1120 additions and 12 deletions

View file

@ -36,6 +36,7 @@ import javax.tools.Diagnostic;
import javax.tools.JavaFileObject; import javax.tools.JavaFileObject;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -327,7 +328,7 @@ public class GenerateHotRodEntityImplementationsProcessor extends AbstractGenera
switch (accessorType) { switch (accessorType) {
case GETTER: case GETTER:
pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method + " {"); pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method + " {");
pw.println(" return " + migrateToType(method.getReturnType(), hotRodFieldType, hotRodEntityField(fieldName)) + ";"); pw.println(" return " + hotRodEntityField(fieldName) + " == null ? null : " + migrateToType(method.getReturnType(), hotRodFieldType, hotRodEntityField(fieldName)) + ";");
pw.println(" }"); pw.println(" }");
return true; return true;
case SETTER: case SETTER:
@ -336,9 +337,12 @@ public class GenerateHotRodEntityImplementationsProcessor extends AbstractGenera
pw.println(" p0 = " + deepClone(firstParameterType, "p0") + ";"); pw.println(" p0 = " + deepClone(firstParameterType, "p0") + ";");
} }
if (isCollection(firstParameterType)) { if (isCollection(firstParameterType)) {
pw.println(" if (p0 != null) " + removeUndefined(firstParameterType, "p0") + ";"); pw.println(" if (p0 != null) {");
pw.println(" " + removeUndefined(firstParameterType, "p0") + ";");
pw.println(" if (" + isUndefined("p0") + ") p0 = null;");
pw.println(" }");
} }
pw.println(" " + hotRodFieldType.toString() + " migrated = " + migrateToType(hotRodFieldType, firstParameterType, "p0") + ";"); pw.println(" " + hotRodFieldType.toString() + " migrated = p0 == null ? null : " + migrateToType(hotRodFieldType, firstParameterType, "p0") + ";");
pw.println(" " + hotRodEntityField("updated") + " |= ! Objects.equals(" + hotRodEntityField(fieldName) + ", migrated);"); pw.println(" " + hotRodEntityField("updated") + " |= ! Objects.equals(" + hotRodEntityField(fieldName) + ", migrated);");
pw.println(" " + hotRodEntityField(fieldName) + " = migrated;"); pw.println(" " + hotRodEntityField(fieldName) + " = migrated;");
pw.println(" }"); pw.println(" }");
@ -387,7 +391,6 @@ public class GenerateHotRodEntityImplementationsProcessor extends AbstractGenera
collectionItemType = getGenericsDeclaration(hotRodFieldType).get(0); collectionItemType = getGenericsDeclaration(hotRodFieldType).get(0);
TypeMirror secondParameterType = method.getParameters().get(1).asType(); TypeMirror secondParameterType = method.getParameters().get(1).asType();
pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method.getSimpleName() + "(" + firstParameterType + " p0, " + secondParameterType + " p1) {"); pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method.getSimpleName() + "(" + firstParameterType + " p0, " + secondParameterType + " p1) {");
pw.println(" if (" + hotRodEntityField(fieldName) + " == null) { " + hotRodEntityField(fieldName) + " = " + interfaceToImplementation((TypeElement) types.asElement(types.erasure(hotRodFieldType)), "") + "; }");
if (! isImmutableFinalType(secondParameterType)) { if (! isImmutableFinalType(secondParameterType)) {
pw.println(" p1 = " + deepClone(secondParameterType, "p1") + ";"); pw.println(" p1 = " + deepClone(secondParameterType, "p1") + ";");
} }
@ -395,6 +398,7 @@ public class GenerateHotRodEntityImplementationsProcessor extends AbstractGenera
pw.println(" if (p1 != null) " + removeUndefined(secondParameterType, "p1") + ";"); pw.println(" if (p1 != null) " + removeUndefined(secondParameterType, "p1") + ";");
} }
pw.println(" boolean valueUndefined = " + isUndefined("p1") + ";"); pw.println(" boolean valueUndefined = " + isUndefined("p1") + ";");
pw.println(" if (" + hotRodEntityField(fieldName) + " == null && !valueUndefined) { " + hotRodEntityField(fieldName) + " = " + interfaceToImplementation((TypeElement) types.asElement(types.erasure(hotRodFieldType)), "") + "; }");
pw.println(" " + hotRodEntityField("updated") + " |= " + hotRodUtils.getQualifiedName().toString() + ".removeFromSetByMapKey(" pw.println(" " + hotRodEntityField("updated") + " |= " + hotRodUtils.getQualifiedName().toString() + ".removeFromSetByMapKey("
+ hotRodEntityField(fieldName) + ", " + hotRodEntityField(fieldName) + ", "
+ "p0, " + "p0, "
@ -522,8 +526,7 @@ public class GenerateHotRodEntityImplementationsProcessor extends AbstractGenera
return "new " + fromType[anotherHotRodEntityIndex.getAsInt()] + "Delegate(" + String.join(", ", fieldNames) + ")"; return "new " + fromType[anotherHotRodEntityIndex.getAsInt()] + "Delegate(" + String.join(", ", fieldNames) + ")";
} }
int last = fromType.length -1 ; return hotRodUtils.getQualifiedName().toString() + ".migrate" + Arrays.stream(fromType).map(this::toSimpleName).collect(Collectors.joining("")) + "To" + toSimpleName(toType) + "(" + String.join(", ", fieldNames) + ")";
return hotRodUtils.getQualifiedName().toString() + ".migrate" + toSimpleName(fromType[last]) + "To" + toSimpleName(toType) + "(" + fieldNames[last] + ")";
} }
private Optional<ExecutableElement> findSuitableConstructor(TypeMirror desiredType, TypeMirror[] parameters) { private Optional<ExecutableElement> findSuitableConstructor(TypeMirror desiredType, TypeMirror[] parameters) {

View file

@ -18,6 +18,13 @@
<groupId>org.keycloak</groupId> <groupId>org.keycloak</groupId>
<artifactId>keycloak-model-map</artifactId> <artifactId>keycloak-model-map</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-map</artifactId>
<version>${project.version}</version>
<scope>test</scope>
<type>test-jar</type>
</dependency>
<dependency> <dependency>
<groupId>org.infinispan</groupId> <groupId>org.infinispan</groupId>
<artifactId>infinispan-client-hotrod</artifactId> <artifactId>infinispan-client-hotrod</artifactId>

View file

@ -26,6 +26,7 @@ import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.GroupModel; import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel; import org.keycloak.models.RoleModel;
import org.keycloak.models.UserLoginFailureModel; import org.keycloak.models.UserLoginFailureModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
@ -34,6 +35,18 @@ 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.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.entity.MapAuthenticationExecutionEntity;
import org.keycloak.models.map.realm.entity.MapAuthenticationFlowEntity;
import org.keycloak.models.map.realm.entity.MapAuthenticatorConfigEntity;
import org.keycloak.models.map.realm.entity.MapClientInitialAccessEntity;
import org.keycloak.models.map.realm.entity.MapComponentEntity;
import org.keycloak.models.map.realm.entity.MapIdentityProviderEntity;
import org.keycloak.models.map.realm.entity.MapIdentityProviderMapperEntity;
import org.keycloak.models.map.realm.entity.MapOTPPolicyEntity;
import org.keycloak.models.map.realm.entity.MapRequiredActionProviderEntity;
import org.keycloak.models.map.realm.entity.MapRequiredCredentialEntity;
import org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntity;
import org.keycloak.models.map.role.MapRoleEntity; import org.keycloak.models.map.role.MapRoleEntity;
import org.keycloak.models.map.storage.hotRod.authSession.HotRodAuthenticationSessionEntityDelegate; import org.keycloak.models.map.storage.hotRod.authSession.HotRodAuthenticationSessionEntityDelegate;
import org.keycloak.models.map.storage.hotRod.authSession.HotRodRootAuthenticationSessionEntity; import org.keycloak.models.map.storage.hotRod.authSession.HotRodRootAuthenticationSessionEntity;
@ -56,6 +69,19 @@ import org.keycloak.models.map.storage.MapStorageProvider;
import org.keycloak.models.map.storage.MapStorageProviderFactory; import org.keycloak.models.map.storage.MapStorageProviderFactory;
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.group.HotRodGroupEntityDelegate; import org.keycloak.models.map.storage.hotRod.group.HotRodGroupEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.HotRodRealmEntity;
import org.keycloak.models.map.storage.hotRod.realm.HotRodRealmEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodAuthenticationExecutionEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodAuthenticationFlowEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodAuthenticatorConfigEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodClientInitialAccessEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodComponentEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodIdentityProviderEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodIdentityProviderMapperEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodOTPPolicyEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodRequiredActionProviderEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodRequiredCredentialEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodWebAuthnPolicyEntityDelegate;
import org.keycloak.models.map.storage.hotRod.user.HotRodUserConsentEntityDelegate; import org.keycloak.models.map.storage.hotRod.user.HotRodUserConsentEntityDelegate;
import org.keycloak.models.map.storage.hotRod.user.HotRodUserCredentialEntityDelegate; import org.keycloak.models.map.storage.hotRod.user.HotRodUserCredentialEntityDelegate;
import org.keycloak.models.map.storage.hotRod.user.HotRodUserEntity; import org.keycloak.models.map.storage.hotRod.user.HotRodUserEntity;
@ -89,6 +115,20 @@ public class HotRodMapStorageProviderFactory implements AmphibianProviderFactory
.constructor(MapUserFederatedIdentityEntity.class, HotRodUserFederatedIdentityEntityDelegate::new) .constructor(MapUserFederatedIdentityEntity.class, HotRodUserFederatedIdentityEntityDelegate::new)
.constructor(MapUserConsentEntity.class, HotRodUserConsentEntityDelegate::new) .constructor(MapUserConsentEntity.class, HotRodUserConsentEntityDelegate::new)
.constructor(MapUserLoginFailureEntity.class, HotRodUserLoginFailureEntityDelegate::new) .constructor(MapUserLoginFailureEntity.class, HotRodUserLoginFailureEntityDelegate::new)
.constructor(MapRealmEntity.class, HotRodRealmEntityDelegate::new)
.constructor(MapAuthenticationExecutionEntity.class, HotRodAuthenticationExecutionEntityDelegate::new)
.constructor(MapAuthenticationFlowEntity.class, HotRodAuthenticationFlowEntityDelegate::new)
.constructor(MapAuthenticatorConfigEntity.class, HotRodAuthenticatorConfigEntityDelegate::new)
.constructor(MapClientInitialAccessEntity.class, HotRodClientInitialAccessEntityDelegate::new)
.constructor(MapComponentEntity.class, HotRodComponentEntityDelegate::new)
.constructor(MapIdentityProviderEntity.class, HotRodIdentityProviderEntityDelegate::new)
.constructor(MapIdentityProviderMapperEntity.class, HotRodIdentityProviderMapperEntityDelegate::new)
.constructor(MapOTPPolicyEntity.class, HotRodOTPPolicyEntityDelegate::new)
.constructor(MapRequiredActionProviderEntity.class, HotRodRequiredActionProviderEntityDelegate::new)
.constructor(MapRequiredCredentialEntity.class, HotRodRequiredCredentialEntityDelegate::new)
.constructor(MapWebAuthnPolicyEntity.class, HotRodWebAuthnPolicyEntityDelegate::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<>();
@ -133,6 +173,12 @@ public class HotRodMapStorageProviderFactory implements AmphibianProviderFactory
new HotRodEntityDescriptor<>(UserLoginFailureModel.class, new HotRodEntityDescriptor<>(UserLoginFailureModel.class,
HotRodUserLoginFailureEntity.class, HotRodUserLoginFailureEntity.class,
HotRodUserLoginFailureEntityDelegate::new)); HotRodUserLoginFailureEntityDelegate::new));
// Realm descriptor
ENTITY_DESCRIPTOR_MAP.put(RealmModel.class,
new HotRodEntityDescriptor<>(RealmModel.class,
HotRodRealmEntity.class,
HotRodRealmEntityDelegate::new));
} }
@Override @Override

View file

@ -19,6 +19,7 @@ package org.keycloak.models.map.storage.hotRod;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.GroupModel; import org.keycloak.models.GroupModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel; import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.models.map.storage.ModelCriteriaBuilder; import org.keycloak.models.map.storage.ModelCriteriaBuilder;
@ -68,6 +69,9 @@ public class IckleQueryMapModelCriteriaBuilder<E extends AbstractHotRodEntity, M
INFINISPAN_NAME_OVERRIDES.put(UserModel.SearchableFields.ASSIGNED_GROUP, "groupsMembership"); INFINISPAN_NAME_OVERRIDES.put(UserModel.SearchableFields.ASSIGNED_GROUP, "groupsMembership");
INFINISPAN_NAME_OVERRIDES.put(UserModel.SearchableFields.ATTRIBUTE, "attributes"); INFINISPAN_NAME_OVERRIDES.put(UserModel.SearchableFields.ATTRIBUTE, "attributes");
INFINISPAN_NAME_OVERRIDES.put(UserModel.SearchableFields.IDP_AND_USER, "federatedIdentities"); INFINISPAN_NAME_OVERRIDES.put(UserModel.SearchableFields.IDP_AND_USER, "federatedIdentities");
INFINISPAN_NAME_OVERRIDES.put(RealmModel.SearchableFields.CLIENT_INITIAL_ACCESS, "clientInitialAccesses");
INFINISPAN_NAME_OVERRIDES.put(RealmModel.SearchableFields.COMPONENT_PROVIDER_TYPE, "components.providerType");
} }
static { static {

View file

@ -32,14 +32,14 @@ public class HotRodAttributeEntity {
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)") @ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 2) @ProtoField(number = 2)
public List<String> values = new LinkedList<>(); public List<String> values;
public HotRodAttributeEntity() { public HotRodAttributeEntity() {
} }
public HotRodAttributeEntity(String name, List<String> values) { public HotRodAttributeEntity(String name, List<String> values) {
this.name = name; this.name = name;
this.values.addAll(values); this.values = values;
} }
public String getName() { public String getName() {

View file

@ -30,14 +30,14 @@ public class HotRodAttributeEntityNonIndexed {
public String name; public String name;
@ProtoField(number = 2) @ProtoField(number = 2)
public List<String> values = new LinkedList<>(); public List<String> values;
public HotRodAttributeEntityNonIndexed() { public HotRodAttributeEntityNonIndexed() {
} }
public HotRodAttributeEntityNonIndexed(String name, List<String> values) { public HotRodAttributeEntityNonIndexed(String name, List<String> values) {
this.name = name; this.name = name;
this.values.addAll(values); this.values = values;
} }
public String getName() { public String getName() {

View file

@ -17,8 +17,11 @@
package org.keycloak.models.map.storage.hotRod.common; package org.keycloak.models.map.storage.hotRod.common;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.map.common.AbstractEntity; import org.keycloak.models.map.common.AbstractEntity;
import org.keycloak.models.map.storage.hotRod.authSession.HotRodAuthenticationSessionEntity; import org.keycloak.models.map.storage.hotRod.authSession.HotRodAuthenticationSessionEntity;
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.user.HotRodUserConsentEntity; import org.keycloak.models.map.storage.hotRod.user.HotRodUserConsentEntity;
import org.keycloak.models.map.storage.hotRod.user.HotRodUserFederatedIdentityEntity; import org.keycloak.models.map.storage.hotRod.user.HotRodUserFederatedIdentityEntity;
@ -115,4 +118,29 @@ public class HotRodTypesUtils {
public static String getKey(HotRodAuthenticationSessionEntity hotRodAuthenticationSessionEntity) { public static String getKey(HotRodAuthenticationSessionEntity hotRodAuthenticationSessionEntity) {
return hotRodAuthenticationSessionEntity.tabId; return hotRodAuthenticationSessionEntity.tabId;
} }
public static AuthenticationExecutionModel.Requirement migrateHotRodRequirementToRequirement(HotRodRequirement p0) {
return p0 == null ? null : AuthenticationExecutionModel.Requirement.values()[p0.ordinal()];
}
public static HotRodRequirement migrateRequirementToHotRodRequirement(AuthenticationExecutionModel.Requirement p0) {
return p0 == null ? null : HotRodRequirement.values()[p0.ordinal()];
}
public static String getKey(HotRodLocalizationTexts hotRodLocalizationTexts) {
return hotRodLocalizationTexts.getLocale();
}
public static Map<String, String> getValue(HotRodLocalizationTexts hotRodLocalizationTexts) {
Set<HotRodPair<String, String>> values = hotRodLocalizationTexts.getValues();
return values == null ? null : values.stream().collect(Collectors.toMap(HotRodPair::getKey, HotRodPair::getValue));
}
public static HotRodLocalizationTexts migrateStringMapToHotRodLocalizationTexts(String p0, Map<String, String> p1) {
HotRodLocalizationTexts hotRodLocalizationTexts = new HotRodLocalizationTexts();
hotRodLocalizationTexts.setLocale(p0);
hotRodLocalizationTexts.setValues(migrateMapToSet(p1, HotRodTypesUtils::createHotRodPairFromMapEntry));
return hotRodLocalizationTexts;
}
} }

View file

@ -27,6 +27,20 @@ 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.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.entity.HotRodAuthenticationExecutionEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodAuthenticationFlowEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodAuthenticatorConfigEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodClientInitialAccessEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodComponentEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodIdentityProviderEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodIdentityProviderMapperEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodLocalizationTexts;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodOTPPolicyEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodRequiredActionProviderEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodRequiredCredentialEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodRequirement;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodWebAuthnPolicyEntity;
import org.keycloak.models.map.storage.hotRod.role.HotRodRoleEntity; import org.keycloak.models.map.storage.hotRod.role.HotRodRoleEntity;
import org.keycloak.models.map.storage.hotRod.user.HotRodUserConsentEntity; import org.keycloak.models.map.storage.hotRod.user.HotRodUserConsentEntity;
import org.keycloak.models.map.storage.hotRod.user.HotRodUserCredentialEntity; import org.keycloak.models.map.storage.hotRod.user.HotRodUserCredentialEntity;
@ -65,6 +79,22 @@ import org.keycloak.models.map.storage.hotRod.user.HotRodUserFederatedIdentityEn
// Login Failures // Login Failures
HotRodUserLoginFailureEntity.class, HotRodUserLoginFailureEntity.class,
// Realms
HotRodAuthenticationExecutionEntity.class,
HotRodAuthenticationFlowEntity.class,
HotRodAuthenticatorConfigEntity.class,
HotRodClientInitialAccessEntity.class,
HotRodComponentEntity.class,
HotRodIdentityProviderEntity.class,
HotRodIdentityProviderMapperEntity.class,
HotRodLocalizationTexts.class,
HotRodOTPPolicyEntity.class,
HotRodRequiredActionProviderEntity.class,
HotRodRequiredCredentialEntity.class,
HotRodRequirement.class,
HotRodWebAuthnPolicyEntity.class,
HotRodRealmEntity.class,
// Common // Common
HotRodPair.class, HotRodPair.class,
HotRodAttributeEntity.class, HotRodAttributeEntity.class,

View file

@ -0,0 +1,438 @@
/*
* 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.realm;
import org.infinispan.protostream.annotations.ProtoDoc;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.common.util.Time;
import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation;
import org.keycloak.models.map.common.UpdatableEntity;
import org.keycloak.models.map.realm.MapRealmEntity;
import org.keycloak.models.map.realm.entity.MapAuthenticationExecutionEntity;
import org.keycloak.models.map.realm.entity.MapAuthenticationFlowEntity;
import org.keycloak.models.map.realm.entity.MapAuthenticatorConfigEntity;
import org.keycloak.models.map.realm.entity.MapClientInitialAccessEntity;
import org.keycloak.models.map.realm.entity.MapComponentEntity;
import org.keycloak.models.map.realm.entity.MapIdentityProviderEntity;
import org.keycloak.models.map.realm.entity.MapIdentityProviderMapperEntity;
import org.keycloak.models.map.realm.entity.MapOTPPolicyEntity;
import org.keycloak.models.map.realm.entity.MapRequiredActionProviderEntity;
import org.keycloak.models.map.realm.entity.MapRequiredCredentialEntity;
import org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntity;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
import org.keycloak.models.map.storage.hotRod.common.HotRodAttributeEntityNonIndexed;
import org.keycloak.models.map.storage.hotRod.common.HotRodPair;
import org.keycloak.models.map.storage.hotRod.common.UpdatableHotRodEntityDelegateImpl;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodAuthenticationExecutionEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodAuthenticationExecutionEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodAuthenticationFlowEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodAuthenticationFlowEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodAuthenticatorConfigEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodAuthenticatorConfigEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodClientInitialAccessEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodClientInitialAccessEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodComponentEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodComponentEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodIdentityProviderEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodIdentityProviderMapperEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodIdentityProviderMapperEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodLocalizationTexts;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodOTPPolicyEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodRequiredActionProviderEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodRequiredActionProviderEntityDelegate;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodRequiredCredentialEntity;
import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodWebAuthnPolicyEntity;
import java.util.Collections;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@GenerateHotRodEntityImplementation(
implementInterface = "org.keycloak.models.map.realm.MapRealmEntity",
inherits = "org.keycloak.models.map.storage.hotRod.realm.HotRodRealmEntity.AbstractHotRodRealmEntityDelegate"
)
@ProtoDoc("@Indexed")
public class HotRodRealmEntity extends AbstractHotRodEntity {
@ProtoField(number = 1, required = true)
public int entityVersion = 1;
@ProtoField(number = 2)
public String id;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 3)
public String name;
@ProtoField(number = 4)
public Boolean adminEventsDetailsEnabled;
@ProtoField(number = 5)
public Boolean adminEventsEnabled;
@ProtoField(number = 6)
public Boolean allowUserManagedAccess;
@ProtoField(number = 7)
public Boolean duplicateEmailsAllowed;
@ProtoField(number = 8)
public Boolean editUsernameAllowed;
@ProtoField(number = 9)
public Boolean enabled;
@ProtoField(number = 10)
public Boolean eventsEnabled;
@ProtoField(number = 11)
public Boolean internationalizationEnabled;
@ProtoField(number = 12)
public Boolean loginWithEmailAllowed;
@ProtoField(number = 13)
public Boolean offlineSessionMaxLifespanEnabled;
@ProtoField(number = 14)
public Boolean registrationAllowed;
@ProtoField(number = 15)
public Boolean registrationEmailAsUsername;
@ProtoField(number = 16)
public Boolean rememberMe;
@ProtoField(number = 17)
public Boolean resetPasswordAllowed;
@ProtoField(number = 18)
public Boolean revokeRefreshToken;
@ProtoField(number = 19)
public Boolean verifyEmail;
@ProtoField(number = 20)
public Integer accessCodeLifespan;
@ProtoField(number = 21)
public Integer accessCodeLifespanLogin;
@ProtoField(number = 22)
public Integer accessCodeLifespanUserAction;
@ProtoField(number = 23)
public Integer accessTokenLifespan;
@ProtoField(number = 24)
public Integer accessTokenLifespanForImplicitFlow;
@ProtoField(number = 25)
public Integer actionTokenGeneratedByAdminLifespan;
@ProtoField(number = 26)
public Integer clientOfflineSessionIdleTimeout;
@ProtoField(number = 27)
public Integer clientOfflineSessionMaxLifespan;
@ProtoField(number = 28)
public Integer clientSessionIdleTimeout;
@ProtoField(number = 29)
public Integer clientSessionMaxLifespan;
@ProtoField(number = 30)
public Integer notBefore;
@ProtoField(number = 31)
public Integer offlineSessionIdleTimeout;
@ProtoField(number = 32)
public Integer offlineSessionMaxLifespan;
@ProtoField(number = 33)
public Integer refreshTokenMaxReuse;
@ProtoField(number = 34)
public Integer ssoSessionIdleTimeout;
@ProtoField(number = 35)
public Integer ssoSessionIdleTimeoutRememberMe;
@ProtoField(number = 36)
public Integer ssoSessionMaxLifespan;
@ProtoField(number = 37)
public Integer ssoSessionMaxLifespanRememberMe;
@ProtoField(number = 38)
public Long eventsExpiration;
@ProtoField(number = 39)
public HotRodOTPPolicyEntity oTPPolicy;
@ProtoField(number = 40)
public HotRodWebAuthnPolicyEntity webAuthnPolicy;
@ProtoField(number = 41)
public HotRodWebAuthnPolicyEntity webAuthnPolicyPasswordless;
@ProtoField(number = 42)
public String accountTheme;
@ProtoField(number = 43)
public String adminTheme;
@ProtoField(number = 44)
public String browserFlow;
@ProtoField(number = 45)
public String clientAuthenticationFlow;
@ProtoField(number = 46)
public String defaultLocale;
@ProtoField(number = 47)
public String defaultRoleId;
@ProtoField(number = 48)
public String directGrantFlow;
@ProtoField(number = 49)
public String displayName;
@ProtoField(number = 50)
public String displayNameHtml;
@ProtoField(number = 51)
public String dockerAuthenticationFlow;
@ProtoField(number = 52)
public String emailTheme;
@ProtoField(number = 53)
public String loginTheme;
@ProtoField(number = 54)
public String masterAdminClient;
@ProtoField(number = 55)
public String passwordPolicy;
@ProtoField(number = 56)
public String registrationFlow;
@ProtoField(number = 57)
public String resetCredentialsFlow;
@ProtoField(number = 58)
public String sslRequired;
@ProtoField(number = 59)
public Set<HotRodAttributeEntityNonIndexed> attributes;
@ProtoField(number = 60)
public Set<HotRodLocalizationTexts> localizationTexts;
@ProtoField(number = 61)
public Set<HotRodPair<String, String>> browserSecurityHeaders;
@ProtoField(number = 62)
public Set<HotRodPair<String, String>> smtpConfig;
@ProtoField(number = 63)
public Set<HotRodAuthenticationExecutionEntity> authenticationExecutions;
@ProtoField(number = 64)
public Set<HotRodAuthenticationFlowEntity> authenticationFlows;
@ProtoField(number = 65)
public Set<HotRodAuthenticatorConfigEntity> authenticatorConfigs;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 66)
public Set<HotRodClientInitialAccessEntity> clientInitialAccesses;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 67)
public Set<HotRodComponentEntity> components;
@ProtoField(number = 68)
public Set<HotRodIdentityProviderEntity> identityProviders;
@ProtoField(number = 69)
public Set<HotRodIdentityProviderMapperEntity> identityProviderMappers;
@ProtoField(number = 70)
public Set<HotRodRequiredActionProviderEntity> requiredActionProviders;
@ProtoField(number = 71)
public Set<HotRodRequiredCredentialEntity> requiredCredentials;
@ProtoField(number = 72)
public Set<String> defaultClientScopeIds;
@ProtoField(number = 73)
public Set<String> defaultGroupIds;
@ProtoField(number = 74)
public Set<String> enabledEventTypes;
@ProtoField(number = 75)
public Set<String> eventsListeners;
@ProtoField(number = 76)
public Set<String> optionalClientScopeIds;
@ProtoField(number = 77)
public Set<String> supportedLocales;
public static abstract class AbstractHotRodRealmEntityDelegate extends UpdatableHotRodEntityDelegateImpl<HotRodRealmEntity> implements MapRealmEntity {
@Override
public String getId() {
return getHotRodEntity().id;
}
@Override
public void setId(String id) {
HotRodRealmEntity entity = getHotRodEntity();
if (entity.id != null) throw new IllegalStateException("Id cannot be changed");
entity.id = id;
entity.updated |= id != null;
}
@Override
public boolean isUpdated() {
return getHotRodEntity().updated
|| Optional.ofNullable(getAuthenticationExecutions()).orElseGet(Collections::emptySet).stream().anyMatch(MapAuthenticationExecutionEntity::isUpdated)
|| Optional.ofNullable(getAuthenticationFlows()).orElseGet(Collections::emptySet).stream().anyMatch(MapAuthenticationFlowEntity::isUpdated)
|| Optional.ofNullable(getAuthenticatorConfigs()).orElseGet(Collections::emptySet).stream().anyMatch(MapAuthenticatorConfigEntity::isUpdated)
|| Optional.ofNullable(getClientInitialAccesses()).orElseGet(Collections::emptySet).stream().anyMatch(MapClientInitialAccessEntity::isUpdated)
|| Optional.ofNullable(getComponents()).orElseGet(Collections::emptySet).stream().anyMatch(MapComponentEntity::isUpdated)
|| Optional.ofNullable(getIdentityProviders()).orElseGet(Collections::emptySet).stream().anyMatch(MapIdentityProviderEntity::isUpdated)
|| Optional.ofNullable(getIdentityProviderMappers()).orElseGet(Collections::emptySet).stream().anyMatch(MapIdentityProviderMapperEntity::isUpdated)
|| Optional.ofNullable(getRequiredActionProviders()).orElseGet(Collections::emptySet).stream().anyMatch(MapRequiredActionProviderEntity::isUpdated)
|| Optional.ofNullable(getRequiredCredentials()).orElseGet(Collections::emptySet).stream().anyMatch(MapRequiredCredentialEntity::isUpdated)
|| Optional.ofNullable(getOTPPolicy()).map(MapOTPPolicyEntity::isUpdated).orElse(false)
|| Optional.ofNullable(getWebAuthnPolicy()).map(MapWebAuthnPolicyEntity::isUpdated).orElse(false)
|| Optional.ofNullable(getWebAuthnPolicyPasswordless()).map(MapWebAuthnPolicyEntity::isUpdated).orElse(false);
}
@Override
public void clearUpdatedFlag() {
getHotRodEntity().updated = false;
Optional.ofNullable(getAuthenticationExecutions()).orElseGet(Collections::emptySet).forEach(UpdatableEntity::clearUpdatedFlag);
Optional.ofNullable(getAuthenticationFlows()).orElseGet(Collections::emptySet).forEach(UpdatableEntity::clearUpdatedFlag);
Optional.ofNullable(getAuthenticatorConfigs()).orElseGet(Collections::emptySet).forEach(UpdatableEntity::clearUpdatedFlag);
Optional.ofNullable(getClientInitialAccesses()).orElseGet(Collections::emptySet).forEach(UpdatableEntity::clearUpdatedFlag);
Optional.ofNullable(getComponents()).orElseGet(Collections::emptySet).forEach(UpdatableEntity::clearUpdatedFlag);
Optional.ofNullable(getIdentityProviders()).orElseGet(Collections::emptySet).forEach(UpdatableEntity::clearUpdatedFlag);
Optional.ofNullable(getIdentityProviderMappers()).orElseGet(Collections::emptySet).forEach(UpdatableEntity::clearUpdatedFlag);
Optional.ofNullable(getRequiredActionProviders()).orElseGet(Collections::emptySet).forEach(UpdatableEntity::clearUpdatedFlag);
Optional.ofNullable(getRequiredCredentials()).orElseGet(Collections::emptySet).forEach(UpdatableEntity::clearUpdatedFlag);
Optional.ofNullable(getOTPPolicy()).ifPresent(UpdatableEntity::clearUpdatedFlag);
Optional.ofNullable(getWebAuthnPolicy()).ifPresent(UpdatableEntity::clearUpdatedFlag);
Optional.ofNullable(getWebAuthnPolicyPasswordless()).ifPresent(UpdatableEntity::clearUpdatedFlag);
}
@Override
public Optional<MapComponentEntity> getComponent(String id) {
Set<HotRodComponentEntity> set = getHotRodEntity().components;
if (set == null || set.isEmpty()) return Optional.empty();
return set.stream().filter(ob -> Objects.equals(ob.id, id)).findFirst().map(HotRodComponentEntityDelegate::new);
}
@Override
public Boolean removeComponent(String componentId) {
Set<HotRodComponentEntity> set = getHotRodEntity().components;
boolean removed = set != null && set.removeIf(ob -> Objects.equals(ob.id, componentId));
getHotRodEntity().updated |= removed;
return removed;
}
@Override
public Optional<MapAuthenticationExecutionEntity> getAuthenticationExecution(String id) {
Set<HotRodAuthenticationExecutionEntity> set = getHotRodEntity().authenticationExecutions;
if (set == null || set.isEmpty()) return Optional.empty();
return set.stream().filter(ob -> Objects.equals(ob.id, id)).findFirst().map(HotRodAuthenticationExecutionEntityDelegate::new);
}
@Override
public Boolean removeAuthenticationExecution(String executionId) {
Set<HotRodAuthenticationExecutionEntity> set = getHotRodEntity().authenticationExecutions;
boolean removed = set != null && set.removeIf(ob -> Objects.equals(ob.id, executionId));
getHotRodEntity().updated |= removed;
return removed;
}
@Override
public Optional<MapAuthenticationFlowEntity> getAuthenticationFlow(String flowId) {
Set<HotRodAuthenticationFlowEntity> set = getHotRodEntity().authenticationFlows;
if (set == null || set.isEmpty()) return Optional.empty();
return set.stream().filter(ob -> Objects.equals(ob.id, flowId)).findFirst().map(HotRodAuthenticationFlowEntityDelegate::new);
}
@Override
public Boolean removeAuthenticationFlow(String flowId) {
Set<HotRodAuthenticationFlowEntity> set = getHotRodEntity().authenticationFlows;
boolean removed = set != null && set.removeIf(ob -> Objects.equals(ob.id, flowId));
getHotRodEntity().updated |= removed;
return removed;
}
@Override
public Boolean removeAuthenticatorConfig(String authenticatorConfigId) {
Set<HotRodAuthenticatorConfigEntity> set = getHotRodEntity().authenticatorConfigs;
boolean removed = set != null && set.removeIf(ob -> Objects.equals(ob.id, authenticatorConfigId));
getHotRodEntity().updated |= removed;
return removed;
}
@Override
public Optional<MapAuthenticatorConfigEntity> getAuthenticatorConfig(String authenticatorConfigId) {
Set<HotRodAuthenticatorConfigEntity> set = getHotRodEntity().authenticatorConfigs;
if (set == null || set.isEmpty()) return Optional.empty();
return set.stream().filter(ob -> Objects.equals(ob.id, authenticatorConfigId)).findFirst().map(HotRodAuthenticatorConfigEntityDelegate::new);
}
@Override
public Boolean removeIdentityProviderMapper(String identityProviderMapperId) {
Set<HotRodIdentityProviderMapperEntity> set = getHotRodEntity().identityProviderMappers;
boolean removed = set != null && set.removeIf(ob -> Objects.equals(ob.id, identityProviderMapperId));
getHotRodEntity().updated |= removed;
return removed;
}
@Override
public Optional<MapIdentityProviderMapperEntity> getIdentityProviderMapper(String identityProviderMapperId) {
Set<HotRodIdentityProviderMapperEntity> set = getHotRodEntity().identityProviderMappers;
if (set == null || set.isEmpty()) return Optional.empty();
return set.stream().filter(ob -> Objects.equals(ob.id, identityProviderMapperId)).findFirst().map(HotRodIdentityProviderMapperEntityDelegate::new);
}
@Override
public Boolean removeIdentityProvider(String identityProviderId) {
Set<HotRodIdentityProviderEntity> set = getHotRodEntity().identityProviders;
boolean removed = set != null && set.removeIf(ob -> Objects.equals(ob.id, identityProviderId));
getHotRodEntity().updated |= removed;
return removed;
}
@Override
public Optional<MapClientInitialAccessEntity> getClientInitialAccess(String clientInitialAccessId) {
Set<HotRodClientInitialAccessEntity> set = getHotRodEntity().clientInitialAccesses;
if (set == null || set.isEmpty()) return Optional.empty();
return set.stream().filter(ob -> Objects.equals(ob.id, clientInitialAccessId)).findFirst().map(HotRodClientInitialAccessEntityDelegate::new);
}
@Override
public Boolean removeClientInitialAccess(String clientInitialAccessId) {
Set<HotRodClientInitialAccessEntity> set = getHotRodEntity().clientInitialAccesses;
boolean removed = set != null && set.removeIf(ob -> Objects.equals(ob.id, clientInitialAccessId));
getHotRodEntity().updated |= removed;
return removed;
}
@Override
public Optional<MapRequiredActionProviderEntity> getRequiredActionProvider(String requiredActionProviderId) {
Set<HotRodRequiredActionProviderEntity> set = getHotRodEntity().requiredActionProviders;
if (set == null || set.isEmpty()) return Optional.empty();
return set.stream().filter(ob -> Objects.equals(ob.id, requiredActionProviderId)).findFirst().map(HotRodRequiredActionProviderEntityDelegate::new);
}
@Override
public Boolean removeRequiredActionProvider(String requiredActionProviderId) {
Set<HotRodRequiredActionProviderEntity> set = getHotRodEntity().requiredActionProviders;
boolean removed = set != null && set.removeIf(ob -> Objects.equals(ob.id, requiredActionProviderId));
getHotRodEntity().updated |= removed;
return removed;
}
@Override
public boolean hasClientInitialAccess() {
Set<MapClientInitialAccessEntity> cias = getClientInitialAccesses();
return cias != null && !cias.isEmpty();
}
@Override
public void removeExpiredClientInitialAccesses() {
Set<MapClientInitialAccessEntity> cias = getClientInitialAccesses();
if (cias != null)
cias.stream()
.filter(this::checkIfExpired)
.map(MapClientInitialAccessEntity::getId)
.collect(Collectors.toSet())
.forEach(this::removeClientInitialAccess);
}
private boolean checkIfExpired(MapClientInitialAccessEntity cia) {
return cia.getRemainingCount() < 1 ||
(cia.getExpiration() > 0 && (cia.getTimestamp() + cia.getExpiration()) < Time.currentTime());
}
}
@Override
public boolean equals(Object o) {
return HotRodRealmEntityDelegate.entityEquals(this, o);
}
@Override
public int hashCode() {
return HotRodRealmEntityDelegate.entityHashCode(this);
}
}

View file

@ -0,0 +1,36 @@
package org.keycloak.models.map.storage.hotRod.realm.entity;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
@GenerateHotRodEntityImplementation(
implementInterface = "org.keycloak.models.map.realm.entity.MapAuthenticationExecutionEntity"
)
public class HotRodAuthenticationExecutionEntity extends AbstractHotRodEntity {
@ProtoField(number = 1)
public String id;
@ProtoField(number = 2)
public Boolean autheticatorFlow;
@ProtoField(number = 3)
public Integer priority;
@ProtoField(number = 4)
public HotRodRequirement requirement;
@ProtoField(number = 5)
public String authenticator;
@ProtoField(number = 6)
public String authenticatorConfig;
@ProtoField(number = 7)
public String flowId;
@ProtoField(number = 8)
public String parentFlowId;
@Override
public boolean equals(Object o) {
return HotRodAuthenticationExecutionEntityDelegate.entityEquals(this, o);
}
@Override
public int hashCode() {
return HotRodAuthenticationExecutionEntityDelegate.entityHashCode(this);
}
}

View file

@ -0,0 +1,32 @@
package org.keycloak.models.map.storage.hotRod.realm.entity;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
@GenerateHotRodEntityImplementation(
implementInterface = "org.keycloak.models.map.realm.entity.MapAuthenticationFlowEntity"
)
public class HotRodAuthenticationFlowEntity extends AbstractHotRodEntity {
@ProtoField(number = 1)
public String id;
@ProtoField(number = 2)
public Boolean builtIn;
@ProtoField(number = 3)
public Boolean topLevel;
@ProtoField(number = 4)
public String alias;
@ProtoField(number = 5)
public String description;
@ProtoField(number = 6)
public String providerId;
@Override
public boolean equals(Object o) {
return HotRodAuthenticationFlowEntityDelegate.entityEquals(this, o);
}
@Override
public int hashCode() {
return HotRodAuthenticationFlowEntityDelegate.entityHashCode(this);
}
}

View file

@ -0,0 +1,29 @@
package org.keycloak.models.map.storage.hotRod.realm.entity;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
import org.keycloak.models.map.storage.hotRod.common.HotRodPair;
import java.util.Set;
@GenerateHotRodEntityImplementation(
implementInterface = "org.keycloak.models.map.realm.entity.MapAuthenticatorConfigEntity"
)
public class HotRodAuthenticatorConfigEntity extends AbstractHotRodEntity {
@ProtoField(number = 1)
public String id;
@ProtoField(number = 2)
public String alias;
@ProtoField(number = 3)
public Set<HotRodPair<String, String>> config;
@Override
public boolean equals(Object o) {
return HotRodAuthenticatorConfigEntityDelegate.entityEquals(this, o);
}
@Override
public int hashCode() {
return HotRodAuthenticatorConfigEntityDelegate.entityHashCode(this);
}
}

View file

@ -0,0 +1,30 @@
package org.keycloak.models.map.storage.hotRod.realm.entity;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
@GenerateHotRodEntityImplementation(
implementInterface = "org.keycloak.models.map.realm.entity.MapClientInitialAccessEntity"
)
public class HotRodClientInitialAccessEntity extends AbstractHotRodEntity {
@ProtoField(number = 1)
public String id;
@ProtoField(number = 2)
public Integer count;
@ProtoField(number = 3)
public Integer expiration;
@ProtoField(number = 4)
public Integer remainingCount;
@ProtoField(number = 5)
public Integer timestamp;
@Override
public boolean equals(Object o) {
return HotRodClientInitialAccessEntityDelegate.entityEquals(this, o);
}
@Override
public int hashCode() {
return HotRodClientInitialAccessEntityDelegate.entityHashCode(this);
}
}

View file

@ -0,0 +1,42 @@
package org.keycloak.models.map.storage.hotRod.realm.entity;
import org.infinispan.protostream.annotations.ProtoDoc;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
import org.keycloak.models.map.storage.hotRod.common.HotRodAttributeEntityNonIndexed;
import java.util.Set;
@GenerateHotRodEntityImplementation(
implementInterface = "org.keycloak.models.map.realm.entity.MapComponentEntity"
)
@ProtoDoc("@Indexed")
public class HotRodComponentEntity extends AbstractHotRodEntity {
@ProtoField(number = 1)
public String id;
@ProtoField(number = 2)
public String name;
@ProtoField(number = 3)
public String parentId;
@ProtoField(number = 4)
public String providerId;
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
@ProtoField(number = 5)
public String providerType;
@ProtoField(number = 6)
public String subType;
@ProtoField(number = 7)
public Set<HotRodAttributeEntityNonIndexed> config;
@Override
public boolean equals(Object o) {
return HotRodComponentEntityDelegate.entityEquals(this, o);
}
@Override
public int hashCode() {
return HotRodComponentEntityDelegate.entityHashCode(this);
}
}

View file

@ -0,0 +1,49 @@
package org.keycloak.models.map.storage.hotRod.realm.entity;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
import org.keycloak.models.map.storage.hotRod.common.HotRodPair;
import java.util.Set;
@GenerateHotRodEntityImplementation(
implementInterface = "org.keycloak.models.map.realm.entity.MapIdentityProviderEntity"
)
public class HotRodIdentityProviderEntity extends AbstractHotRodEntity {
@ProtoField(number = 1)
public String id;
@ProtoField(number = 2)
public Boolean addReadTokenRoleOnCreate;
@ProtoField(number = 3)
public Boolean authenticateByDefault;
@ProtoField(number = 4)
public Boolean enabled;
@ProtoField(number = 5)
public Boolean linkOnly;
@ProtoField(number = 6)
public Boolean storeToken;
@ProtoField(number = 7)
public Boolean trustEmail;
@ProtoField(number = 8)
public String alias;
@ProtoField(number = 9)
public String displayName;
@ProtoField(number = 10)
public String firstBrokerLoginFlowId;
@ProtoField(number = 11)
public String postBrokerLoginFlowId;
@ProtoField(number = 12)
public String providerId;
@ProtoField(number = 13)
public Set<HotRodPair<String, String>> config;
@Override
public boolean equals(Object o) {
return HotRodIdentityProviderEntityDelegate.entityEquals(this, o);
}
@Override
public int hashCode() {
return HotRodIdentityProviderEntityDelegate.entityHashCode(this);
}
}

View file

@ -0,0 +1,33 @@
package org.keycloak.models.map.storage.hotRod.realm.entity;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
import org.keycloak.models.map.storage.hotRod.common.HotRodPair;
import java.util.Set;
@GenerateHotRodEntityImplementation(
implementInterface = "org.keycloak.models.map.realm.entity.MapIdentityProviderMapperEntity"
)
public class HotRodIdentityProviderMapperEntity extends AbstractHotRodEntity {
@ProtoField(number = 1)
public String id;
@ProtoField(number = 2)
public String name;
@ProtoField(number = 3)
public String identityProviderAlias;
@ProtoField(number = 4)
public String identityProviderMapper;
@ProtoField(number = 5)
public Set<HotRodPair<String, String>> config;
@Override
public boolean equals(Object o) {
return HotRodIdentityProviderMapperEntityDelegate.entityEquals(this, o);
}
@Override
public int hashCode() {
return HotRodIdentityProviderMapperEntityDelegate.entityHashCode(this);
}
}

View file

@ -0,0 +1,61 @@
/*
* 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.realm.entity;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.models.map.storage.hotRod.common.HotRodPair;
import java.util.Objects;
import java.util.Set;
public class HotRodLocalizationTexts {
@ProtoField(number = 1)
public String locale;
@ProtoField(number = 2)
public Set<HotRodPair<String, String>> values;
public String getLocale() {
return locale;
}
public void setLocale(String locale) {
this.locale = locale;
}
public Set<HotRodPair<String, String>> getValues() {
return values;
}
public void setValues(Set<HotRodPair<String, String>> values) {
this.values = values;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
HotRodLocalizationTexts that = (HotRodLocalizationTexts) o;
return Objects.equals(locale, that.locale) && Objects.equals(values, that.values);
}
@Override
public int hashCode() {
return Objects.hash(locale, values);
}
}

View file

@ -0,0 +1,32 @@
package org.keycloak.models.map.storage.hotRod.realm.entity;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
@GenerateHotRodEntityImplementation(
implementInterface = "org.keycloak.models.map.realm.entity.MapOTPPolicyEntity"
)
public class HotRodOTPPolicyEntity extends AbstractHotRodEntity {
@ProtoField(number = 1)
public Integer otpPolicyDigits;
@ProtoField(number = 2)
public Integer otpPolicyInitialCounter;
@ProtoField(number = 3)
public Integer otpPolicyLookAheadWindow;
@ProtoField(number = 4)
public Integer otpPolicyPeriod;
@ProtoField(number = 5)
public String otpPolicyAlgorithm;
@ProtoField(number = 6)
public String otpPolicyType;
@Override
public boolean equals(Object o) {
return HotRodOTPPolicyEntityDelegate.entityEquals(this, o);
}
@Override
public int hashCode() {
return HotRodOTPPolicyEntityDelegate.entityHashCode(this);
}
}

View file

@ -0,0 +1,39 @@
package org.keycloak.models.map.storage.hotRod.realm.entity;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
import org.keycloak.models.map.storage.hotRod.common.HotRodPair;
import java.util.Set;
@GenerateHotRodEntityImplementation(
implementInterface = "org.keycloak.models.map.realm.entity.MapRequiredActionProviderEntity"
)
public class HotRodRequiredActionProviderEntity extends AbstractHotRodEntity {
@ProtoField(number = 1)
public String id;
@ProtoField(number = 2)
public String name;
@ProtoField(number = 3)
public Boolean defaultAction;
@ProtoField(number = 4)
public Boolean enabled;
@ProtoField(number = 5)
public Integer priority;
@ProtoField(number = 6)
public String alias;
@ProtoField(number = 7)
public String providerId;
@ProtoField(number = 8)
public Set<HotRodPair<String, String>> config;
@Override
public boolean equals(Object o) {
return HotRodRequiredActionProviderEntityDelegate.entityEquals(this, o);
}
@Override
public int hashCode() {
return HotRodRequiredActionProviderEntityDelegate.entityHashCode(this);
}
}

View file

@ -0,0 +1,28 @@
package org.keycloak.models.map.storage.hotRod.realm.entity;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
@GenerateHotRodEntityImplementation(
implementInterface = "org.keycloak.models.map.realm.entity.MapRequiredCredentialEntity"
)
public class HotRodRequiredCredentialEntity extends AbstractHotRodEntity {
@ProtoField(number = 1)
public Boolean input;
@ProtoField(number = 2)
public Boolean secret;
@ProtoField(number = 3)
public String formLabel;
@ProtoField(number = 4)
public String type;
@Override
public boolean equals(Object o) {
return HotRodRequiredCredentialEntityDelegate.entityEquals(this, o);
}
@Override
public int hashCode() {
return HotRodRequiredCredentialEntityDelegate.entityHashCode(this);
}
}

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.realm.entity;
import org.infinispan.protostream.annotations.ProtoEnumValue;
public enum HotRodRequirement {
@ProtoEnumValue(number = 0)
REQUIRED,
@ProtoEnumValue(number = 1)
CONDITIONAL,
@ProtoEnumValue(number = 2)
ALTERNATIVE,
@ProtoEnumValue(number = 3, name = "EXECUTION_DISABLED")
DISABLED
}

View file

@ -0,0 +1,42 @@
package org.keycloak.models.map.storage.hotRod.realm.entity;
import org.infinispan.protostream.annotations.ProtoField;
import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation;
import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity;
import java.util.List;
@GenerateHotRodEntityImplementation(
implementInterface = "org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntity"
)
public class HotRodWebAuthnPolicyEntity extends AbstractHotRodEntity {
@ProtoField(number = 1)
public Boolean avoidSameAuthenticatorRegister;
@ProtoField(number = 2)
public Integer createTimeout;
@ProtoField(number = 3)
public String attestationConveyancePreference;
@ProtoField(number = 4)
public String authenticatorAttachment;
@ProtoField(number = 5)
public String requireResidentKey;
@ProtoField(number = 6)
public String rpEntityName;
@ProtoField(number = 7)
public String rpId;
@ProtoField(number = 8)
public String userVerificationRequirement;
@ProtoField(number = 9)
public List<String> acceptableAaguids;
@ProtoField(number = 10)
public List<String> signatureAlgorithms;
@Override
public boolean equals(Object o) {
return HotRodWebAuthnPolicyEntityDelegate.entityEquals(this, o);
}
@Override
public int hashCode() {
return HotRodWebAuthnPolicyEntityDelegate.entityHashCode(this);
}
}

View file

@ -62,5 +62,14 @@
</indexing> </indexing>
<encoding media-type="application/x-protostream"/> <encoding media-type="application/x-protostream"/>
</distributed-cache> </distributed-cache>
<distributed-cache name="realms" mode="SYNC">
<indexing>
<indexed-entities>
<indexed-entity>kc.HotRodRealmEntity</indexed-entity>
<indexed-entity>kc.HotRodComponentEntity</indexed-entity>
</indexed-entities>
</indexing>
<encoding media-type="application/x-protostream"/>
</distributed-cache>
</cache-container> </cache-container>
</infinispan> </infinispan>

View file

@ -64,5 +64,14 @@
</indexing> </indexing>
<encoding media-type="application/x-protostream"/> <encoding media-type="application/x-protostream"/>
</distributed-cache> </distributed-cache>
<distributed-cache name="realms" mode="SYNC">
<indexing>
<indexed-entities>
<indexed-entity>kc.HotRodRealmEntity</indexed-entity>
<indexed-entity>kc.HotRodComponentEntity</indexed-entity>
</indexed-entities>
</indexing>
<encoding media-type="application/x-protostream"/>
</distributed-cache>
</cache-container> </cache-container>
</infinispan> </infinispan>

View file

@ -0,0 +1,29 @@
/*
* 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;
import org.keycloak.models.map.realm.MapRealmEntity;
import org.keycloak.models.map.realm.RealmEntityUndefinedValuesTest;
import org.keycloak.models.map.storage.hotRod.realm.HotRodRealmEntityDelegate;
public class HotRodUndefinedValuesTest extends RealmEntityUndefinedValuesTest {
@Override
public MapRealmEntity newMapRealmEntity() {
return new HotRodRealmEntityDelegate();
}
}

View file

@ -29,6 +29,17 @@
</annotationProcessors> </annotationProcessors>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>

View file

@ -266,7 +266,7 @@
"username": "${keycloak.connectionsHotRod.username:myuser}", "username": "${keycloak.connectionsHotRod.username:myuser}",
"password": "${keycloak.connectionsHotRod.password:qwer1234!}", "password": "${keycloak.connectionsHotRod.password:qwer1234!}",
"enableSecurity": "${keycloak.connectionsHotRod.enableSecurity:true}", "enableSecurity": "${keycloak.connectionsHotRod.enableSecurity:true}",
"reindexCaches": "${keycloak.connectionsHotRod.reindexCaches:auth-sessions,clients,client-scopes,groups,users,user-login-failures,roles}" "reindexCaches": "${keycloak.connectionsHotRod.reindexCaches:auth-sessions,clients,client-scopes,groups,users,user-login-failures,roles,realms}"
} }
}, },

View file

@ -1503,6 +1503,7 @@
<keycloak.role.map.storage.provider>hotrod</keycloak.role.map.storage.provider> <keycloak.role.map.storage.provider>hotrod</keycloak.role.map.storage.provider>
<keycloak.user.map.storage.provider>hotrod</keycloak.user.map.storage.provider> <keycloak.user.map.storage.provider>hotrod</keycloak.user.map.storage.provider>
<keycloak.loginFailure.map.storage.provider>hotrod</keycloak.loginFailure.map.storage.provider> <keycloak.loginFailure.map.storage.provider>hotrod</keycloak.loginFailure.map.storage.provider>
<keycloak.realm.map.storage.provider>hotrod</keycloak.realm.map.storage.provider>
</systemPropertyVariables> </systemPropertyVariables>
</configuration> </configuration>
</plugin> </plugin>

View file

@ -60,5 +60,14 @@
</indexing> </indexing>
<encoding media-type="application/x-protostream"/> <encoding media-type="application/x-protostream"/>
</distributed-cache> </distributed-cache>
<distributed-cache name="realms" mode="SYNC">
<indexing>
<indexed-entities>
<indexed-entity>kc.HotRodRealmEntity</indexed-entity>
<indexed-entity>kc.HotRodComponentEntity</indexed-entity>
</indexed-entities>
</indexing>
<encoding media-type="application/x-protostream"/>
</distributed-cache>
</cache-container> </cache-container>
</infinispan> </infinispan>

View file

@ -76,7 +76,7 @@ public class HotRodMapStorage extends KeycloakModelParameters {
.spi("client").provider(MapClientProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) .spi("client").provider(MapClientProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID)
.spi("clientScope").provider(MapClientScopeProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) .spi("clientScope").provider(MapClientScopeProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID)
.spi("group").provider(MapGroupProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) .spi("group").provider(MapGroupProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID)
.spi("realm").provider(MapRealmProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) .spi("realm").provider(MapRealmProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID)
.spi("role").provider(MapRoleProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) .spi("role").provider(MapRoleProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID)
.spi(DeploymentStateSpi.NAME).provider(MapDeploymentStateProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) .spi(DeploymentStateSpi.NAME).provider(MapDeploymentStateProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID)
.spi(StoreFactorySpi.NAME).provider(MapAuthorizationStoreFactory.PROVIDER_ID).config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) .spi(StoreFactorySpi.NAME).provider(MapAuthorizationStoreFactory.PROVIDER_ID).config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID)