diff --git a/model/build-processor/src/main/java/org/keycloak/models/map/processor/GenerateHotRodEntityImplementationsProcessor.java b/model/build-processor/src/main/java/org/keycloak/models/map/processor/GenerateHotRodEntityImplementationsProcessor.java index 7decf2ca76..a327662928 100644 --- a/model/build-processor/src/main/java/org/keycloak/models/map/processor/GenerateHotRodEntityImplementationsProcessor.java +++ b/model/build-processor/src/main/java/org/keycloak/models/map/processor/GenerateHotRodEntityImplementationsProcessor.java @@ -36,6 +36,7 @@ import javax.tools.Diagnostic; import javax.tools.JavaFileObject; import java.io.IOException; import java.io.PrintWriter; +import java.util.Arrays; import java.util.Comparator; import java.util.HashSet; import java.util.List; @@ -327,7 +328,7 @@ public class GenerateHotRodEntityImplementationsProcessor extends AbstractGenera switch (accessorType) { case GETTER: 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(" }"); return true; case SETTER: @@ -336,9 +337,12 @@ public class GenerateHotRodEntityImplementationsProcessor extends AbstractGenera pw.println(" p0 = " + deepClone(firstParameterType, "p0") + ";"); } 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(fieldName) + " = migrated;"); pw.println(" }"); @@ -387,7 +391,6 @@ public class GenerateHotRodEntityImplementationsProcessor extends AbstractGenera collectionItemType = getGenericsDeclaration(hotRodFieldType).get(0); TypeMirror secondParameterType = method.getParameters().get(1).asType(); 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)) { 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(" 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(" + hotRodEntityField(fieldName) + ", " + "p0, " @@ -522,8 +526,7 @@ public class GenerateHotRodEntityImplementationsProcessor extends AbstractGenera return "new " + fromType[anotherHotRodEntityIndex.getAsInt()] + "Delegate(" + String.join(", ", fieldNames) + ")"; } - int last = fromType.length -1 ; - return hotRodUtils.getQualifiedName().toString() + ".migrate" + toSimpleName(fromType[last]) + "To" + toSimpleName(toType) + "(" + fieldNames[last] + ")"; + return hotRodUtils.getQualifiedName().toString() + ".migrate" + Arrays.stream(fromType).map(this::toSimpleName).collect(Collectors.joining("")) + "To" + toSimpleName(toType) + "(" + String.join(", ", fieldNames) + ")"; } private Optional findSuitableConstructor(TypeMirror desiredType, TypeMirror[] parameters) { diff --git a/model/map-hot-rod/pom.xml b/model/map-hot-rod/pom.xml index 155fe15dc3..b3eb398994 100644 --- a/model/map-hot-rod/pom.xml +++ b/model/map-hot-rod/pom.xml @@ -18,6 +18,13 @@ org.keycloak keycloak-model-map + + org.keycloak + keycloak-model-map + ${project.version} + test + test-jar + org.infinispan infinispan-client-hotrod diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/HotRodMapStorageProviderFactory.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/HotRodMapStorageProviderFactory.java index 5d70654d98..7cac981ab6 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/HotRodMapStorageProviderFactory.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/HotRodMapStorageProviderFactory.java @@ -26,6 +26,7 @@ import org.keycloak.models.ClientScopeModel; import org.keycloak.models.GroupModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserLoginFailureModel; 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.group.MapGroupEntity; 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.storage.hotRod.authSession.HotRodAuthenticationSessionEntityDelegate; 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.hotRod.group.HotRodGroupEntity; 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.HotRodUserCredentialEntityDelegate; import org.keycloak.models.map.storage.hotRod.user.HotRodUserEntity; @@ -89,6 +115,20 @@ public class HotRodMapStorageProviderFactory implements AmphibianProviderFactory .constructor(MapUserFederatedIdentityEntity.class, HotRodUserFederatedIdentityEntityDelegate::new) .constructor(MapUserConsentEntity.class, HotRodUserConsentEntityDelegate::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(); public static final Map, HotRodEntityDescriptor> ENTITY_DESCRIPTOR_MAP = new HashMap<>(); @@ -133,6 +173,12 @@ public class HotRodMapStorageProviderFactory implements AmphibianProviderFactory new HotRodEntityDescriptor<>(UserLoginFailureModel.class, HotRodUserLoginFailureEntity.class, HotRodUserLoginFailureEntityDelegate::new)); + + // Realm descriptor + ENTITY_DESCRIPTOR_MAP.put(RealmModel.class, + new HotRodEntityDescriptor<>(RealmModel.class, + HotRodRealmEntity.class, + HotRodRealmEntityDelegate::new)); } @Override diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/IckleQueryMapModelCriteriaBuilder.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/IckleQueryMapModelCriteriaBuilder.java index 1798bc6fb1..232f3c0509 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/IckleQueryMapModelCriteriaBuilder.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/IckleQueryMapModelCriteriaBuilder.java @@ -19,6 +19,7 @@ package org.keycloak.models.map.storage.hotRod; import org.keycloak.models.ClientModel; import org.keycloak.models.GroupModel; +import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserModel; import org.keycloak.models.map.storage.ModelCriteriaBuilder; @@ -68,6 +69,9 @@ public class IckleQueryMapModelCriteriaBuilder values = new LinkedList<>(); + public List values; public HotRodAttributeEntity() { } public HotRodAttributeEntity(String name, List values) { this.name = name; - this.values.addAll(values); + this.values = values; } public String getName() { diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodAttributeEntityNonIndexed.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodAttributeEntityNonIndexed.java index 746ab20dda..b14ea600bc 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodAttributeEntityNonIndexed.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodAttributeEntityNonIndexed.java @@ -30,14 +30,14 @@ public class HotRodAttributeEntityNonIndexed { public String name; @ProtoField(number = 2) - public List values = new LinkedList<>(); + public List values; public HotRodAttributeEntityNonIndexed() { } public HotRodAttributeEntityNonIndexed(String name, List values) { this.name = name; - this.values.addAll(values); + this.values = values; } public String getName() { diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodTypesUtils.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodTypesUtils.java index 939ba9269d..0c9ee38314 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodTypesUtils.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodTypesUtils.java @@ -17,8 +17,11 @@ 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.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.HotRodUserFederatedIdentityEntity; @@ -115,4 +118,29 @@ public class HotRodTypesUtils { public static String getKey(HotRodAuthenticationSessionEntity hotRodAuthenticationSessionEntity) { 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 getValue(HotRodLocalizationTexts hotRodLocalizationTexts) { + Set> values = hotRodLocalizationTexts.getValues(); + return values == null ? null : values.stream().collect(Collectors.toMap(HotRodPair::getKey, HotRodPair::getValue)); + } + + public static HotRodLocalizationTexts migrateStringMapToHotRodLocalizationTexts(String p0, Map p1) { + HotRodLocalizationTexts hotRodLocalizationTexts = new HotRodLocalizationTexts(); + hotRodLocalizationTexts.setLocale(p0); + hotRodLocalizationTexts.setValues(migrateMapToSet(p1, HotRodTypesUtils::createHotRodPairFromMapEntry)); + + return hotRodLocalizationTexts; + } } diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/ProtoSchemaInitializer.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/ProtoSchemaInitializer.java index 5b87a2c870..092f1e9604 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/ProtoSchemaInitializer.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/ProtoSchemaInitializer.java @@ -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.group.HotRodGroupEntity; 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.user.HotRodUserConsentEntity; import org.keycloak.models.map.storage.hotRod.user.HotRodUserCredentialEntity; @@ -65,6 +79,22 @@ import org.keycloak.models.map.storage.hotRod.user.HotRodUserFederatedIdentityEn // Login Failures 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 HotRodPair.class, HotRodAttributeEntity.class, diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/HotRodRealmEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/HotRodRealmEntity.java new file mode 100644 index 0000000000..571809fa8b --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/HotRodRealmEntity.java @@ -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 attributes; + @ProtoField(number = 60) + public Set localizationTexts; + @ProtoField(number = 61) + public Set> browserSecurityHeaders; + @ProtoField(number = 62) + public Set> smtpConfig; + @ProtoField(number = 63) + public Set authenticationExecutions; + @ProtoField(number = 64) + public Set authenticationFlows; + @ProtoField(number = 65) + public Set authenticatorConfigs; + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 66) + public Set clientInitialAccesses; + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 67) + public Set components; + + @ProtoField(number = 68) + public Set identityProviders; + @ProtoField(number = 69) + public Set identityProviderMappers; + @ProtoField(number = 70) + public Set requiredActionProviders; + @ProtoField(number = 71) + public Set requiredCredentials; + @ProtoField(number = 72) + public Set defaultClientScopeIds; + @ProtoField(number = 73) + public Set defaultGroupIds; + @ProtoField(number = 74) + public Set enabledEventTypes; + @ProtoField(number = 75) + public Set eventsListeners; + @ProtoField(number = 76) + public Set optionalClientScopeIds; + @ProtoField(number = 77) + public Set supportedLocales; + + + public static abstract class AbstractHotRodRealmEntityDelegate extends UpdatableHotRodEntityDelegateImpl 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 getComponent(String id) { + Set 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 set = getHotRodEntity().components; + boolean removed = set != null && set.removeIf(ob -> Objects.equals(ob.id, componentId)); + getHotRodEntity().updated |= removed; + return removed; + } + + @Override + public Optional getAuthenticationExecution(String id) { + Set 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 set = getHotRodEntity().authenticationExecutions; + boolean removed = set != null && set.removeIf(ob -> Objects.equals(ob.id, executionId)); + getHotRodEntity().updated |= removed; + return removed; + } + + @Override + public Optional getAuthenticationFlow(String flowId) { + Set 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 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 set = getHotRodEntity().authenticatorConfigs; + boolean removed = set != null && set.removeIf(ob -> Objects.equals(ob.id, authenticatorConfigId)); + getHotRodEntity().updated |= removed; + return removed; + } + + @Override + public Optional getAuthenticatorConfig(String authenticatorConfigId) { + Set 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 set = getHotRodEntity().identityProviderMappers; + boolean removed = set != null && set.removeIf(ob -> Objects.equals(ob.id, identityProviderMapperId)); + getHotRodEntity().updated |= removed; + return removed; + } + + @Override + public Optional getIdentityProviderMapper(String identityProviderMapperId) { + Set 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 set = getHotRodEntity().identityProviders; + boolean removed = set != null && set.removeIf(ob -> Objects.equals(ob.id, identityProviderId)); + getHotRodEntity().updated |= removed; + return removed; + } + + @Override + public Optional getClientInitialAccess(String clientInitialAccessId) { + Set 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 set = getHotRodEntity().clientInitialAccesses; + boolean removed = set != null && set.removeIf(ob -> Objects.equals(ob.id, clientInitialAccessId)); + getHotRodEntity().updated |= removed; + return removed; + } + + @Override + public Optional getRequiredActionProvider(String requiredActionProviderId) { + Set 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 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 cias = getClientInitialAccesses(); + return cias != null && !cias.isEmpty(); + } + + @Override + public void removeExpiredClientInitialAccesses() { + Set 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); + } +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodAuthenticationExecutionEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodAuthenticationExecutionEntity.java new file mode 100644 index 0000000000..25b31c97c4 --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodAuthenticationExecutionEntity.java @@ -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); + } +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodAuthenticationFlowEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodAuthenticationFlowEntity.java new file mode 100644 index 0000000000..72be72c913 --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodAuthenticationFlowEntity.java @@ -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); + } +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodAuthenticatorConfigEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodAuthenticatorConfigEntity.java new file mode 100644 index 0000000000..edca356220 --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodAuthenticatorConfigEntity.java @@ -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> config; + @Override + public boolean equals(Object o) { + return HotRodAuthenticatorConfigEntityDelegate.entityEquals(this, o); + } + + @Override + public int hashCode() { + return HotRodAuthenticatorConfigEntityDelegate.entityHashCode(this); + } +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodClientInitialAccessEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodClientInitialAccessEntity.java new file mode 100644 index 0000000000..e0bc4d63b5 --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodClientInitialAccessEntity.java @@ -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); + } +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodComponentEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodComponentEntity.java new file mode 100644 index 0000000000..dfb1f62701 --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodComponentEntity.java @@ -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 config; + @Override + public boolean equals(Object o) { + return HotRodComponentEntityDelegate.entityEquals(this, o); + } + + @Override + public int hashCode() { + return HotRodComponentEntityDelegate.entityHashCode(this); + } +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodIdentityProviderEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodIdentityProviderEntity.java new file mode 100644 index 0000000000..e219cc315c --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodIdentityProviderEntity.java @@ -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> config; + @Override + public boolean equals(Object o) { + return HotRodIdentityProviderEntityDelegate.entityEquals(this, o); + } + + @Override + public int hashCode() { + return HotRodIdentityProviderEntityDelegate.entityHashCode(this); + } +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodIdentityProviderMapperEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodIdentityProviderMapperEntity.java new file mode 100644 index 0000000000..39a240fefe --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodIdentityProviderMapperEntity.java @@ -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> config; + @Override + public boolean equals(Object o) { + return HotRodIdentityProviderMapperEntityDelegate.entityEquals(this, o); + } + + @Override + public int hashCode() { + return HotRodIdentityProviderMapperEntityDelegate.entityHashCode(this); + } +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodLocalizationTexts.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodLocalizationTexts.java new file mode 100644 index 0000000000..b8814bae7f --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodLocalizationTexts.java @@ -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> values; + + public String getLocale() { + return locale; + } + + public void setLocale(String locale) { + this.locale = locale; + } + + public Set> getValues() { + return values; + } + + public void setValues(Set> 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); + } +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodOTPPolicyEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodOTPPolicyEntity.java new file mode 100644 index 0000000000..793b2a6084 --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodOTPPolicyEntity.java @@ -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); + } +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodRequiredActionProviderEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodRequiredActionProviderEntity.java new file mode 100644 index 0000000000..f8c9b42799 --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodRequiredActionProviderEntity.java @@ -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> config; + @Override + public boolean equals(Object o) { + return HotRodRequiredActionProviderEntityDelegate.entityEquals(this, o); + } + + @Override + public int hashCode() { + return HotRodRequiredActionProviderEntityDelegate.entityHashCode(this); + } +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodRequiredCredentialEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodRequiredCredentialEntity.java new file mode 100644 index 0000000000..9dadc36e14 --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodRequiredCredentialEntity.java @@ -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); + } +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodRequirement.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodRequirement.java new file mode 100644 index 0000000000..d834a21d93 --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodRequirement.java @@ -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 +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodWebAuthnPolicyEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodWebAuthnPolicyEntity.java new file mode 100644 index 0000000000..40e5d9f502 --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/realm/entity/HotRodWebAuthnPolicyEntity.java @@ -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 acceptableAaguids; + @ProtoField(number = 10) + public List signatureAlgorithms; + @Override + public boolean equals(Object o) { + return HotRodWebAuthnPolicyEntityDelegate.entityEquals(this, o); + } + + @Override + public int hashCode() { + return HotRodWebAuthnPolicyEntityDelegate.entityHashCode(this); + } +} diff --git a/model/map-hot-rod/src/main/resources/config/cacheConfig.xml b/model/map-hot-rod/src/main/resources/config/cacheConfig.xml index 7668cb5325..2d4f2f7f35 100644 --- a/model/map-hot-rod/src/main/resources/config/cacheConfig.xml +++ b/model/map-hot-rod/src/main/resources/config/cacheConfig.xml @@ -62,5 +62,14 @@ + + + + kc.HotRodRealmEntity + kc.HotRodComponentEntity + + + + diff --git a/model/map-hot-rod/src/main/resources/config/infinispan.xml b/model/map-hot-rod/src/main/resources/config/infinispan.xml index c1eb5778f4..0aa3a0716f 100644 --- a/model/map-hot-rod/src/main/resources/config/infinispan.xml +++ b/model/map-hot-rod/src/main/resources/config/infinispan.xml @@ -64,5 +64,14 @@ + + + + kc.HotRodRealmEntity + kc.HotRodComponentEntity + + + + diff --git a/model/map-hot-rod/src/test/java/org/keycloak/models/map/storage/hotRod/HotRodUndefinedValuesTest.java b/model/map-hot-rod/src/test/java/org/keycloak/models/map/storage/hotRod/HotRodUndefinedValuesTest.java new file mode 100644 index 0000000000..206149cb8e --- /dev/null +++ b/model/map-hot-rod/src/test/java/org/keycloak/models/map/storage/hotRod/HotRodUndefinedValuesTest.java @@ -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(); + } +} diff --git a/model/map/pom.xml b/model/map/pom.xml index 68fc71205a..8d3fd8aa69 100644 --- a/model/map/pom.xml +++ b/model/map/pom.xml @@ -29,6 +29,17 @@ + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json b/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json index cef6ea712c..552ba24b60 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json @@ -266,7 +266,7 @@ "username": "${keycloak.connectionsHotRod.username:myuser}", "password": "${keycloak.connectionsHotRod.password:qwer1234!}", "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}" } }, diff --git a/testsuite/integration-arquillian/tests/pom.xml b/testsuite/integration-arquillian/tests/pom.xml index 6f4cc71cc1..99463efc38 100755 --- a/testsuite/integration-arquillian/tests/pom.xml +++ b/testsuite/integration-arquillian/tests/pom.xml @@ -1503,6 +1503,7 @@ hotrod hotrod hotrod + hotrod diff --git a/testsuite/model/src/main/resources/hotrod/infinispan.xml b/testsuite/model/src/main/resources/hotrod/infinispan.xml index fe9ecbd66b..017c975c09 100644 --- a/testsuite/model/src/main/resources/hotrod/infinispan.xml +++ b/testsuite/model/src/main/resources/hotrod/infinispan.xml @@ -60,5 +60,14 @@ + + + + kc.HotRodRealmEntity + kc.HotRodComponentEntity + + + + diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java index 92519e5609..75101872c2 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java @@ -76,7 +76,7 @@ public class HotRodMapStorage extends KeycloakModelParameters { .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("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(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)