diff --git a/model/build-processor/src/main/java/org/keycloak/models/map/annotations/CollectionKey.java b/model/build-processor/src/main/java/org/keycloak/models/map/annotations/CollectionKey.java new file mode 100644 index 00000000000..18fe46ab6de --- /dev/null +++ b/model/build-processor/src/main/java/org/keycloak/models/map/annotations/CollectionKey.java @@ -0,0 +1,41 @@ +/* + * Copyright 2023 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.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Determines getter of a field which is unique across a set of the same entities within the same context. + * This field can be used as unique key in map-like access to a collection. For example, in the set of + * user consents, this can be client ID. + * + * @author hmlnarik + */ +@Retention(RetentionPolicy.CLASS) +@Target(ElementType.METHOD) +public @interface CollectionKey { + + /** + * Priority of this annotation: The higher the value, the more appropriate the annotation is. + * @return + */ + public int priority() default 0; + +} diff --git a/model/build-processor/src/main/java/org/keycloak/models/map/processor/AbstractGenerateEntityImplementationsProcessor.java b/model/build-processor/src/main/java/org/keycloak/models/map/processor/AbstractGenerateEntityImplementationsProcessor.java index 4ece1811fab..7da921dd2e2 100644 --- a/model/build-processor/src/main/java/org/keycloak/models/map/processor/AbstractGenerateEntityImplementationsProcessor.java +++ b/model/build-processor/src/main/java/org/keycloak/models/map/processor/AbstractGenerateEntityImplementationsProcessor.java @@ -17,6 +17,7 @@ package org.keycloak.models.map.processor; +import org.keycloak.models.map.annotations.CollectionKey; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.element.Element; @@ -37,6 +38,7 @@ import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -90,6 +92,39 @@ public abstract class AbstractGenerateEntityImplementationsProcessor extends Abs return true; } + public ExecutableElement getCollectionKey(TypeMirror fieldType, ExecutableElement callingMethod) { + if (! Util.isCollectionType(elements.getTypeElement(types.erasure(fieldType).toString()))) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Invalid collection type: " + fieldType, callingMethod); + return null; + } + + TypeMirror collectionType = getGenericsDeclaration(fieldType).get(0); + TypeElement collectionTypeEl = elements.getTypeElement(types.erasure(collectionType).toString()); + + Iterator it = elements.getAllMembers(collectionTypeEl).stream() + .filter(el -> el.getKind() == ElementKind.METHOD) + .filter(el -> el.getAnnotation(CollectionKey.class) != null) + .sorted(Comparator.comparing((Element el) -> el.getAnnotation(CollectionKey.class).priority()).reversed()) + .filter(ExecutableElement.class::isInstance) + .map(ExecutableElement.class::cast) + .iterator(); + + ExecutableElement res = null; + if (it.hasNext()) { + res = it.next(); + if (! res.getParameters().isEmpty() || ! "java.lang.String".equals(res.getReturnType().toString())) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Invalid getter annotated with @CollectionKey in " + res, callingMethod); + } + if (it.hasNext() && it.next().getAnnotation(CollectionKey.class).priority() == res.getAnnotation(CollectionKey.class).priority()) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Multiple getters annotated with @CollectionKey found: " + res + ", " + it.next(), callingMethod); + } + } else { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "No getters annotated with @CollectionKey in " + collectionType, callingMethod); + } + + return res; + } + protected boolean testAnnotationElement(TypeElement kind) { return true; } protected void afterAnnotationProcessing() {} protected abstract Generator[] getGenerators(); diff --git a/model/build-processor/src/main/java/org/keycloak/models/map/processor/FieldAccessorType.java b/model/build-processor/src/main/java/org/keycloak/models/map/processor/FieldAccessorType.java index fcd4070a565..7a80080f694 100644 --- a/model/build-processor/src/main/java/org/keycloak/models/map/processor/FieldAccessorType.java +++ b/model/build-processor/src/main/java/org/keycloak/models/map/processor/FieldAccessorType.java @@ -33,6 +33,9 @@ import static org.keycloak.models.map.processor.Util.pluralToSingular; * @author hmlnarik */ enum FieldAccessorType { + + // Order does matter, see {@link #getMethod} + GETTER { @Override public boolean is(ExecutableElement method, String fieldName, Types types, TypeMirror fieldType) { @@ -95,6 +98,28 @@ enum FieldAccessorType { && types.isSameType(res.get(0), method.getParameters().get(0).asType()); } }, + COLLECTION_GET_BY_ID { + @Override + public boolean is(ExecutableElement method, String fieldName, Types types, TypeMirror fieldType) { + String fieldNameSingular = pluralToSingular(fieldName); + String getFromCollection = "get" + fieldNameSingular; + List res = getGenericsDeclaration(fieldType); + return Objects.equals(getFromCollection, method.getSimpleName().toString()) + && method.getParameters().size() == 1 + && res.size() == 1 + && Objects.equals("java.lang.String", method.getParameters().get(0).asType().toString()); + } + }, + COLLECTION_DELETE_BY_ID { + @Override + public boolean is(ExecutableElement method, String fieldName, Types types, TypeMirror fieldType) { + String fieldNameSingular = pluralToSingular(fieldName); + String removeFromCollection = "remove" + fieldNameSingular; + return Objects.equals(removeFromCollection, method.getSimpleName().toString()) + && method.getParameters().size() == 1 + && Objects.equals("java.lang.String", method.getParameters().get(0).asType().toString()); + } + }, UNKNOWN /* Must be the last */ { @Override public boolean is(ExecutableElement method, String fieldName, Types types, TypeMirror fieldType) { diff --git a/model/build-processor/src/main/java/org/keycloak/models/map/processor/GenerateEntityImplementationsProcessor.java b/model/build-processor/src/main/java/org/keycloak/models/map/processor/GenerateEntityImplementationsProcessor.java index bd7b7dbad6b..47302f24740 100644 --- a/model/build-processor/src/main/java/org/keycloak/models/map/processor/GenerateEntityImplementationsProcessor.java +++ b/model/build-processor/src/main/java/org/keycloak/models/map/processor/GenerateEntityImplementationsProcessor.java @@ -225,6 +225,7 @@ public class GenerateEntityImplementationsProcessor extends AbstractGenerateEnti pw.println(" }"); return; case COLLECTION_DELETE: + { String returnType = method.getReturnType().getKind() == TypeKind.VOID ? "Void" : method.getReturnType().toString(); TypeElement fieldTypeElement = elements.getTypeElement(types.erasure(fieldType).toString()); if (Util.isMapType(fieldTypeElement)) { @@ -235,10 +236,28 @@ public class GenerateEntityImplementationsProcessor extends AbstractGenerateEnti if (method.getReturnType().getKind() == TypeKind.VOID) { pw.println(" e." + method.getSimpleName() + "((" + firstParameterType + ") p0); return null;"); } else { - pw.println(" return (" + method.getReturnType() + ") e." + method.getSimpleName() + "((" + firstParameterType + ") p0);"); + pw.println(" return e." + method.getSimpleName() + "((" + firstParameterType + ") p0);"); } pw.println(" }"); return; + } + case COLLECTION_DELETE_BY_ID: + { + String returnType = method.getReturnType().getKind() == TypeKind.VOID ? "Void" : method.getReturnType().toString(); + pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + returnType + " mapRemove(" + className + " e, K p0) {"); + if (method.getReturnType().getKind() == TypeKind.VOID) { + pw.println(" e." + method.getSimpleName() + "((String) p0); return null;"); + } else { + pw.println(" return e." + method.getSimpleName() + "((String) p0);"); + } + pw.println(" }"); + return; + } + case COLLECTION_GET_BY_ID: + pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " mapGet(" + className + " e, K key) {"); + pw.println(" return e." + method.getSimpleName() + "((" + firstParameterType + ") key);"); + pw.println(" }"); + return; case MAP_ADD: TypeMirror secondParameterType = method.getParameters().get(1).asType(); pw.println(" @SuppressWarnings(\"unchecked\") @Override public void mapPut(" + className + " e, K key, T value) {"); @@ -288,6 +307,7 @@ public class GenerateEntityImplementationsProcessor extends AbstractGenerateEnti } pw.println("import java.util.Objects;"); + pw.println("import java.util.Optional;"); pw.println("import " + FQN_DEEP_CLONER + ";"); pw.println("// DO NOT CHANGE THIS CLASS, IT IS GENERATED AUTOMATICALLY BY " + GenerateEntityImplementationsProcessor.class.getSimpleName()); generatedAnnotation(pw); @@ -454,6 +474,7 @@ public class GenerateEntityImplementationsProcessor extends AbstractGenerateEnti pw.println(" }"); return true; case COLLECTION_DELETE: + { boolean needsReturn = method.getReturnType().getKind() != TypeKind.VOID; pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method.getSimpleName() + "(" + firstParameterType + " p0) {"); pw.println(" if (" + fieldName + " == null) { return" + (needsReturn ? " false" : "") + "; }"); @@ -462,6 +483,25 @@ public class GenerateEntityImplementationsProcessor extends AbstractGenerateEnti if (needsReturn) pw.println(" return removed;"); pw.println(" }"); return true; + } + case COLLECTION_DELETE_BY_ID: + { + boolean needsReturn = method.getReturnType().getKind() != TypeKind.VOID; + pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method.getSimpleName() + "(String p0) {"); + pw.println(" boolean removed = " + fieldName + " != null && " + fieldName + ".removeIf(o -> Objects.equals(o." + getCollectionKey(fieldType, method) + ", p0));"); + pw.println(" updated |= removed;"); + if (needsReturn) pw.println(" return removed;"); + pw.println(" }"); + return true; + } + case COLLECTION_GET_BY_ID: + { + pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method.getSimpleName() + "(String p0) {"); + pw.println(" if (" + fieldName + " == null || " + fieldName + ".isEmpty()) return Optional.empty();"); + pw.println(" return " + fieldName + ".stream().filter(o -> Objects.equals(o." + getCollectionKey(fieldType, method) + ", p0)).findFirst();"); + pw.println(" }"); + return true; + } case MAP_ADD: TypeMirror secondParameterType = method.getParameters().get(1).asType(); pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method.getSimpleName() + "(" + firstParameterType + " p0, " + secondParameterType + " p1) {"); @@ -580,6 +620,7 @@ public class GenerateEntityImplementationsProcessor extends AbstractGenerateEnti pw.println(" }"); return true; case COLLECTION_DELETE: + { pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method.getSimpleName() + "(" + firstParameterType + " p0) {"); TypeElement fieldTypeElement = elements.getTypeElement(types.erasure(fieldType).toString()); String removeMethod = Util.isMapType(fieldTypeElement) ? "mapRemove" : "collectionRemove"; @@ -590,12 +631,25 @@ public class GenerateEntityImplementationsProcessor extends AbstractGenerateEnti } pw.println(" }"); return true; + } + case COLLECTION_DELETE_BY_ID: + { + pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method.getSimpleName() + "(String p0) {"); + if (method.getReturnType().getKind() == TypeKind.VOID) { + pw.println(" entityFieldDelegate.mapRemove(" + fieldName + ", p0);"); + } else { + pw.println(" return (" + method.getReturnType() + ") entityFieldDelegate.mapRemove(" + fieldName + ", p0);"); + } + pw.println(" }"); + return true; + } case MAP_ADD: TypeMirror secondParameterType = method.getParameters().get(1).asType(); pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method.getSimpleName() + "(" + firstParameterType + " p0, " + secondParameterType + " p1) {"); pw.println(" entityFieldDelegate.mapPut(" + fieldName + ", p0, p1);"); pw.println(" }"); return true; + case COLLECTION_GET_BY_ID: case MAP_GET: pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method.getSimpleName() + "(" + firstParameterType + " p0) {"); pw.println(" return (" + method.getReturnType() + ") entityFieldDelegate.mapGet(" + fieldName + ", p0);"); 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 0a168636b4f..c0d8d6b386e 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 @@ -344,6 +344,13 @@ public class GenerateHotRodEntityImplementationsProcessor extends AbstractGenera return "this." + ENTITY_VARIABLE + "." + fieldName; } + private String getFieldNameForCollectionKey(TypeMirror fieldType, ExecutableElement callingMethod) { + ExecutableElement collectionKey = getCollectionKey(fieldType, callingMethod); + char[] c = determineAttributeFromMethodName(collectionKey).toCharArray(); + c[0] = Character.toLowerCase(c[0]); + return new String(c); + } + private boolean printMethodBody(PrintWriter pw, FieldAccessorType accessorType, ExecutableElement method, String fieldName, TypeMirror fieldType, TypeMirror hotRodFieldType) { TypeMirror firstParameterType = method.getParameters().isEmpty() ? types.getNullType() @@ -393,6 +400,7 @@ public class GenerateHotRodEntityImplementationsProcessor extends AbstractGenera pw.println(" }"); return true; case COLLECTION_DELETE: + { collectionItemType = getGenericsDeclaration(hotRodFieldType).get(0); boolean needsReturn = method.getReturnType().getKind() != TypeKind.VOID; pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method.getSimpleName() + "(" + firstParameterType + " p0) {"); @@ -412,6 +420,27 @@ public class GenerateHotRodEntityImplementationsProcessor extends AbstractGenera if (needsReturn) pw.println(" return removed;"); pw.println(" }"); return true; + } + case COLLECTION_DELETE_BY_ID: + { + boolean needsReturn = method.getReturnType().getKind() != TypeKind.VOID; + pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method.getSimpleName() + "(String p0) {"); + pw.println(" boolean removed = " + hotRodEntityField(fieldName) + " != null && " + hotRodEntityField(fieldName) + ".removeIf(o -> Objects.equals(o." + getFieldNameForCollectionKey(fieldType, method) + ", p0));"); + pw.println(" " + hotRodEntityField("updated") + " |= removed;"); + if (needsReturn) pw.println(" return removed;"); + pw.println(" }"); + return true; + } + case COLLECTION_GET_BY_ID: + { + collectionItemType = getGenericsDeclaration(hotRodFieldType).get(0); + TypeMirror returnTypeGeneric = getGenericsDeclaration(method.getReturnType()).get(0); + pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method.getSimpleName() + "(String p0) {"); + pw.println(" if (" + hotRodEntityField(fieldName) + " == null || " + hotRodEntityField(fieldName) + ".isEmpty()) return Optional.empty();"); + pw.println(" return " + hotRodEntityField(fieldName) + ".stream().filter(o -> Objects.equals(o." + getFieldNameForCollectionKey(fieldType, method) + ", p0)).findFirst().map(e -> " + migrateToType(returnTypeGeneric, collectionItemType, "e") + ");"); + pw.println(" }"); + return true; + } case MAP_ADD: collectionItemType = getGenericsDeclaration(hotRodFieldType).get(0); TypeMirror secondParameterType = method.getParameters().get(1).asType(); diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authSession/HotRodRootAuthenticationSessionEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authSession/HotRodRootAuthenticationSessionEntity.java index bd0b2b19c91..e4dcd05b60a 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authSession/HotRodRootAuthenticationSessionEntity.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authSession/HotRodRootAuthenticationSessionEntity.java @@ -99,26 +99,6 @@ public class HotRodRootAuthenticationSessionEntity extends AbstractHotRodEntity entity.updated |= id != null; } - @Override - public Optional getAuthenticationSession(String tabId) { - HotRodRootAuthenticationSessionEntity rootAuthSession = getHotRodEntity(); - if (rootAuthSession.authenticationSessions == null || rootAuthSession.authenticationSessions.isEmpty()) return Optional.empty(); - - return rootAuthSession.authenticationSessions.stream() - .filter(as -> Objects.equals(as.tabId, tabId)) - .findFirst() - .map(HotRodAuthenticationSessionEntityDelegate::new); - } - - @Override - public Boolean removeAuthenticationSession(String tabId) { - HotRodRootAuthenticationSessionEntity rootAuthSession = getHotRodEntity(); - boolean removed = rootAuthSession.authenticationSessions != null && - rootAuthSession.authenticationSessions.removeIf(c -> Objects.equals(c.tabId, tabId)); - rootAuthSession.updated |= removed; - return removed; - } - @Override public boolean isUpdated() { HotRodRootAuthenticationSessionEntity rootAuthSession = getHotRodEntity(); diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/client/HotRodClientEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/client/HotRodClientEntity.java index 8fabea3f124..c2b2c56526a 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/client/HotRodClientEntity.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/client/HotRodClientEntity.java @@ -209,20 +209,6 @@ public class HotRodClientEntity extends AbstractHotRodEntity { .filter(me -> Objects.equals(me.getValue(), defaultScope)) .map(Map.Entry::getKey); } - - @Override - public Optional getProtocolMapper(String id) { - Set mappers = getProtocolMappers(); - if (mappers == null || mappers.isEmpty()) return Optional.empty(); - - return mappers.stream().filter(m -> Objects.equals(m.getId(), id)).findFirst(); - } - - @Override - public void removeProtocolMapper(String id) { - HotRodClientEntity entity = getHotRodEntity(); - entity.updated |= entity.protocolMappers != null && entity.protocolMappers.removeIf(m -> Objects.equals(m.id, id)); - } } @Override diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/clientscope/HotRodClientScopeEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/clientscope/HotRodClientScopeEntity.java index f7b7bd06b67..c8e219f5380 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/clientscope/HotRodClientScopeEntity.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/clientscope/HotRodClientScopeEntity.java @@ -109,20 +109,6 @@ public class HotRodClientScopeEntity extends AbstractHotRodEntity { entity.id = id; entity.updated |= id != null; } - - @Override - public Optional getProtocolMapper(String id) { - Set mappers = getProtocolMappers(); - if (mappers == null || mappers.isEmpty()) return Optional.empty(); - - return mappers.stream().filter(m -> Objects.equals(m.getId(), id)).findFirst(); - } - - @Override - public void removeProtocolMapper(String id) { - HotRodClientScopeEntity entity = getHotRodEntity(); - entity.updated |= entity.protocolMappers != null && entity.protocolMappers.removeIf(m -> Objects.equals(m.id, id)); - } } @Override 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 index 7253ede9fc9..5c62db94d23 100644 --- 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 @@ -323,126 +323,6 @@ public class HotRodRealmEntity extends AbstractHotRodEntity { 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(); diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/user/HotRodUserEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/user/HotRodUserEntity.java index 2952c9a9ec8..22459bd7e7a 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/user/HotRodUserEntity.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/user/HotRodUserEntity.java @@ -227,38 +227,6 @@ public class HotRodUserEntity extends AbstractHotRodEntity { Optional.ofNullable(getFederatedIdentities()).orElseGet(Collections::emptySet).forEach(UpdatableEntity::clearUpdatedFlag); } - @Override - public Optional getUserConsent(String clientId) { - Set ucs = getHotRodEntity().userConsents; - if (ucs == null || ucs.isEmpty()) return Optional.empty(); - - return ucs.stream().filter(uc -> Objects.equals(uc.clientId, clientId)).findFirst().map(HotRodUserConsentEntityDelegate::new); - } - - @Override - public Boolean removeUserConsent(String clientId) { - Set consents = getHotRodEntity().userConsents; - boolean removed = consents != null && consents.removeIf(uc -> Objects.equals(uc.clientId, clientId)); - getHotRodEntity().updated |= removed; - return removed; - } - - @Override - public Optional getCredential(String id) { - List uce = getHotRodEntity().credentials; - if (uce == null || uce.isEmpty()) return Optional.empty(); - - return uce.stream().filter(uc -> Objects.equals(uc.id, id)).findFirst().map(HotRodUserCredentialEntityDelegate::new); - } - - @Override - public Boolean removeCredential(String id) { - List credentials = getHotRodEntity().credentials; - boolean removed = credentials != null && credentials.removeIf(c -> Objects.equals(c.id, id)); - getHotRodEntity().updated |= removed; - return removed; - } - @Override public Boolean moveCredential(String credentialId, String newPreviousCredentialId) { // 1 - Get all credentials from the entity. @@ -302,22 +270,6 @@ public class HotRodUserEntity extends AbstractHotRodEntity { return true; } - @Override - public Optional getFederatedIdentity(String identityProviderId) { - Set fes = getHotRodEntity().federatedIdentities; - if (fes == null || fes.isEmpty()) return Optional.empty(); - - return fes.stream().filter(fi -> Objects.equals(fi.identityProvider, identityProviderId)).findFirst().map(HotRodUserFederatedIdentityEntityDelegate::new); - } - - @Override - public Boolean removeFederatedIdentity(String identityProviderId) { - Set federatedIdentities = getHotRodEntity().federatedIdentities; - boolean removed = federatedIdentities != null && federatedIdentities.removeIf(fi -> Objects.equals(fi.identityProvider, identityProviderId)); - getHotRodEntity().updated |= removed; - return removed; - } - } @Override diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/userSession/HotRodUserSessionEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/userSession/HotRodUserSessionEntity.java index b9f818ce67d..0db608431ae 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/userSession/HotRodUserSessionEntity.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/userSession/HotRodUserSessionEntity.java @@ -166,25 +166,6 @@ public class HotRodUserSessionEntity extends AbstractHotRodEntity { Optional.ofNullable(getAuthenticatedClientSessions()).orElseGet(Collections::emptySet).forEach(UpdatableEntity::clearUpdatedFlag); } - @Override - public Optional getAuthenticatedClientSession(String clientUUID) { - Set acss = getHotRodEntity().authenticatedClientSessions; - if (acss == null || acss.isEmpty()) return Optional.empty(); - - return acss.stream() - .filter(acs -> Objects.equals(acs.clientId, clientUUID)) - .findFirst() - .map(HotRodTypesUtils::migrateHotRodAuthenticatedClientSessionEntityReferenceToMapAuthenticatedClientSessionEntity); - } - - @Override - public Boolean removeAuthenticatedClientSession(String clientUUID) { - Set acss = getHotRodEntity().authenticatedClientSessions; - boolean removed = acss != null && acss.removeIf(uc -> Objects.equals(uc.clientId, clientUUID)); - getHotRodEntity().updated |= removed; - return removed; - } - @Override public void clearAuthenticatedClientSessions() { HotRodUserSessionEntity entity = getHotRodEntity(); diff --git a/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/client/entity/JpaClientEntity.java b/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/client/entity/JpaClientEntity.java index f8e09ae400d..f0aa228a46f 100644 --- a/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/client/entity/JpaClientEntity.java +++ b/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/client/entity/JpaClientEntity.java @@ -47,6 +47,7 @@ import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSI import org.keycloak.models.map.common.UuidValidator; import org.keycloak.models.map.storage.jpa.JpaRootVersionedEntity; import org.keycloak.models.map.storage.jpa.hibernate.jsonb.JsonbType; +import java.util.Optional; /** * There are some fields marked by {@code @Column(insertable = false, updatable = false)}. @@ -215,11 +216,21 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootVers return metadata.getProtocolMappers(); } + @Override + public Optional getProtocolMapper(String id) { + return metadata.getProtocolMapper(id); + } + @Override public void addProtocolMapper(MapProtocolMapperEntity mapping) { metadata.addProtocolMapper(mapping); } + @Override + public void removeProtocolMapper(String id) { + metadata.removeProtocolMapper(id); + } + @Override public void addRedirectUri(String redirectUri) { metadata.addRedirectUri(redirectUri); diff --git a/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/clientScope/entity/JpaClientScopeEntity.java b/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/clientScope/entity/JpaClientScopeEntity.java index 1e1217dc50d..f02b0816778 100644 --- a/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/clientScope/entity/JpaClientScopeEntity.java +++ b/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/clientScope/entity/JpaClientScopeEntity.java @@ -47,6 +47,7 @@ import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSI import org.keycloak.models.map.common.UuidValidator; import org.keycloak.models.map.storage.jpa.JpaRootVersionedEntity; import org.keycloak.models.map.storage.jpa.hibernate.jsonb.JsonbType; +import java.util.Optional; /** * There are some fields marked by {@code @Column(insertable = false, updatable = false)}. @@ -162,11 +163,21 @@ public class JpaClientScopeEntity extends AbstractClientScopeEntity implements J return metadata.getProtocolMappers(); } + @Override + public Optional getProtocolMapper(String id) { + return metadata.getProtocolMapper(id); + } + @Override public void addProtocolMapper(MapProtocolMapperEntity mapping) { metadata.addProtocolMapper(mapping); } + @Override + public void removeProtocolMapper(String id) { + metadata.removeProtocolMapper(id); + } + @Override public void addScopeMapping(String id) { metadata.addScopeMapping(id); diff --git a/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/realm/entity/JpaRealmEntity.java b/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/realm/entity/JpaRealmEntity.java index 37fdd9a269e..2490adebe02 100644 --- a/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/realm/entity/JpaRealmEntity.java +++ b/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/realm/entity/JpaRealmEntity.java @@ -902,41 +902,80 @@ public class JpaRealmEntity extends MapRealmEntity.AbstractRealmEntity implement return this.metadata.getAuthenticationFlows(); } + @Override + public Optional getAuthenticationFlow(String p0) { + return metadata.getAuthenticationFlow(p0); + } + @Override public void addAuthenticationFlow(MapAuthenticationFlowEntity authenticationFlow) { this.metadata.addAuthenticationFlow(authenticationFlow); } + @Override + public Boolean removeAuthenticationFlow(String p0) { + return metadata.removeAuthenticationFlow(p0); + } + @Override public Set getAuthenticationExecutions() { return this.metadata.getAuthenticationExecutions(); } + public Optional getAuthenticationExecution(String p0) { + return metadata.getAuthenticationExecution(p0); + } + @Override public void addAuthenticationExecution(MapAuthenticationExecutionEntity authenticationExecution) { this.metadata.addAuthenticationExecution(authenticationExecution); } + @Override + public Boolean removeAuthenticationExecution(String p0) { + return metadata.removeAuthenticationExecution(p0); + } + @Override public Set getAuthenticatorConfigs() { return this.metadata.getAuthenticatorConfigs(); } + @Override + public Optional getAuthenticatorConfig(String p0) { + return metadata.getAuthenticatorConfig(p0); + } + @Override public void addAuthenticatorConfig(MapAuthenticatorConfigEntity authenticatorConfig) { this.metadata.addAuthenticatorConfig(authenticatorConfig); } + @Override + public Boolean removeAuthenticatorConfig(String p0) { + return metadata.removeAuthenticatorConfig(p0); + } + @Override public Set getRequiredActionProviders() { return this.metadata.getRequiredActionProviders(); } + @Override + public Optional getRequiredActionProvider(String requiredActionProviderId) { + return this.metadata.getRequiredActionProvider(requiredActionProviderId); + } + @Override public void addRequiredActionProvider(MapRequiredActionProviderEntity requiredActionProvider) { this.metadata.addRequiredActionProvider(requiredActionProvider); } + @Override + public Boolean removeRequiredActionProvider(String requiredActionProviderId) { + return this.metadata.removeRequiredActionProvider(requiredActionProviderId); + } + @Override public Set getIdentityProviders() { return this.metadata.getIdentityProviders(); @@ -947,6 +986,11 @@ public class JpaRealmEntity extends MapRealmEntity.AbstractRealmEntity implement this.metadata.addIdentityProvider(identityProvider); } + @Override + public Boolean removeIdentityProvider(String p0) { + return metadata.removeIdentityProvider(p0); + } + @Override public void addIdentityProviderMapper(MapIdentityProviderMapperEntity identityProviderMapper) { this.metadata.addIdentityProviderMapper(identityProviderMapper); @@ -957,16 +1001,36 @@ public class JpaRealmEntity extends MapRealmEntity.AbstractRealmEntity implement return this.metadata.getIdentityProviderMappers(); } + @Override + public Optional getIdentityProviderMapper(String p0) { + return metadata.getIdentityProviderMapper(p0); + } + + @Override + public Boolean removeIdentityProviderMapper(String p0) { + return metadata.removeIdentityProviderMapper(p0); + } + @Override public Set getClientInitialAccesses() { return this.metadata.getClientInitialAccesses(); } + @Override + public Optional getClientInitialAccess(String p0) { + return metadata.getClientInitialAccess(p0); + } + @Override public void addClientInitialAccess(MapClientInitialAccessEntity clientInitialAccess) { this.metadata.addClientInitialAccess(clientInitialAccess); } + @Override + public Boolean removeClientInitialAccess(String p0) { + return metadata.removeClientInitialAccess(p0); + } + @Override public Map> getAttributes() { Map> result = new HashMap<>(); diff --git a/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/user/entity/JpaUserEntity.java b/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/user/entity/JpaUserEntity.java index 2142e7c0118..b270c4c9f53 100644 --- a/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/user/entity/JpaUserEntity.java +++ b/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/user/entity/JpaUserEntity.java @@ -54,6 +54,7 @@ import org.keycloak.models.map.user.MapUserEntity; import org.keycloak.models.map.user.MapUserFederatedIdentityEntity; import org.keycloak.models.utils.KeycloakModelUtils; +import java.util.Optional; import static org.keycloak.models.map.storage.jpa.JpaMapStorageProviderFactory.CLONER; /** @@ -471,6 +472,14 @@ public class JpaUserEntity extends MapUserEntity.AbstractUserEntity implements J return this.consents.stream().map(MapUserConsentEntity.class::cast).collect(Collectors.toSet()); } + @Override + public Optional getUserConsent(String clientId) { + return this.consents.stream() + .map(MapUserConsentEntity.class::cast) + .filter(muce -> Objects.equals(muce.getClientId(), clientId)) + .findAny(); + } + @Override public void setUserConsents(Set userConsents) { this.consents.clear(); @@ -489,7 +498,7 @@ public class JpaUserEntity extends MapUserEntity.AbstractUserEntity implements J @Override public Boolean removeUserConsent(MapUserConsentEntity userConsentEntity) { - return this.consents.removeIf(uc -> Objects.equals(uc.getClientId(), userConsentEntity.getClientId())); + return removeUserConsent(userConsentEntity.getClientId()); } @Override @@ -503,6 +512,11 @@ public class JpaUserEntity extends MapUserEntity.AbstractUserEntity implements J return this.metadata.getCredentials(); } + @Override + public Optional getCredential(String id) { + return metadata.getCredential(id); + } + @Override public void setCredentials(List credentials) { this.metadata.setCredentials(credentials); @@ -515,7 +529,12 @@ public class JpaUserEntity extends MapUserEntity.AbstractUserEntity implements J @Override public Boolean removeCredential(MapUserCredentialEntity credentialEntity) { - return super.removeCredential(credentialEntity.getId()); + return removeCredential(credentialEntity.getId()); + } + + @Override + public Boolean removeCredential(String id) { + return metadata.removeCredential(id); } //user federated identities @@ -524,6 +543,14 @@ public class JpaUserEntity extends MapUserEntity.AbstractUserEntity implements J return this.federatedIdentities.stream().map(MapUserFederatedIdentityEntity.class::cast).collect(Collectors.toSet()); } + @Override + public Optional getFederatedIdentity(String identityProviderId) { + return this.federatedIdentities.stream() + .map(MapUserFederatedIdentityEntity.class::cast) + .filter(muce -> Objects.equals(muce.getIdentityProvider(), identityProviderId)) + .findAny(); + } + @Override public void setFederatedIdentities(Set federatedIdentities) { this.federatedIdentities.clear(); @@ -542,7 +569,7 @@ public class JpaUserEntity extends MapUserEntity.AbstractUserEntity implements J @Override public Boolean removeFederatedIdentity(MapUserFederatedIdentityEntity federatedIdentity) { - return this.federatedIdentities.removeIf(fi -> Objects.equals(fi.getIdentityProvider(), federatedIdentity.getIdentityProvider())); + return removeFederatedIdentity(federatedIdentity.getIdentityProvider()); } @Override diff --git a/model/map/src/main/java/org/keycloak/models/map/authSession/MapAuthenticationSessionEntity.java b/model/map/src/main/java/org/keycloak/models/map/authSession/MapAuthenticationSessionEntity.java index d7b3018cae5..39b2b301f2e 100644 --- a/model/map/src/main/java/org/keycloak/models/map/authSession/MapAuthenticationSessionEntity.java +++ b/model/map/src/main/java/org/keycloak/models/map/authSession/MapAuthenticationSessionEntity.java @@ -16,6 +16,7 @@ */ package org.keycloak.models.map.authSession; +import org.keycloak.models.map.annotations.CollectionKey; import org.keycloak.models.map.annotations.GenerateEntityImplementations; import org.keycloak.models.map.common.DeepCloner; import org.keycloak.models.map.common.UpdatableEntity; @@ -31,6 +32,7 @@ import java.util.Set; @DeepCloner.Root public interface MapAuthenticationSessionEntity extends UpdatableEntity { + @CollectionKey String getTabId(); void setTabId(String tabId); diff --git a/model/map/src/main/java/org/keycloak/models/map/authSession/MapRootAuthenticationSessionEntity.java b/model/map/src/main/java/org/keycloak/models/map/authSession/MapRootAuthenticationSessionEntity.java index e953558bc7a..37c8b724595 100644 --- a/model/map/src/main/java/org/keycloak/models/map/authSession/MapRootAuthenticationSessionEntity.java +++ b/model/map/src/main/java/org/keycloak/models/map/authSession/MapRootAuthenticationSessionEntity.java @@ -53,22 +53,6 @@ public interface MapRootAuthenticationSessionEntity extends AbstractEntity, Upda this.updated |= id != null; } - @Override - public Optional getAuthenticationSession(String tabId) { - Set authenticationSessions = getAuthenticationSessions(); - if (authenticationSessions == null || authenticationSessions.isEmpty()) return Optional.empty(); - - return authenticationSessions.stream().filter(as -> Objects.equals(as.getTabId(), tabId)).findFirst(); - } - - @Override - public Boolean removeAuthenticationSession(String tabId) { - Set authenticationSessions = getAuthenticationSessions(); - boolean removed = authenticationSessions != null && authenticationSessions.removeIf(c -> Objects.equals(c.getTabId(), tabId)); - this.updated |= removed; - return removed; - } - @Override public boolean isUpdated() { return this.updated || diff --git a/model/map/src/main/java/org/keycloak/models/map/client/MapClientEntity.java b/model/map/src/main/java/org/keycloak/models/map/client/MapClientEntity.java index d4eb97613d2..e9624928a3a 100644 --- a/model/map/src/main/java/org/keycloak/models/map/client/MapClientEntity.java +++ b/model/map/src/main/java/org/keycloak/models/map/client/MapClientEntity.java @@ -75,20 +75,6 @@ public interface MapClientEntity extends AbstractEntity, UpdatableEntity, Entity .filter(me -> Objects.equals(me.getValue(), defaultScope)) .map(Entry::getKey); } - - @Override - public Optional getProtocolMapper(String id) { - Set mappers = getProtocolMappers(); - if (mappers == null || mappers.isEmpty()) return Optional.empty(); - - return mappers.stream().filter(mapper -> Objects.equals(mapper.getId(), id)).findFirst(); - } - - @Override - public void removeProtocolMapper(String id) { - Set mappers = getProtocolMappers(); - this.updated |= mappers != null && mappers.removeIf(mapper -> Objects.equals(mapper.getId(), id)); - } } Map getClientScopes(); diff --git a/model/map/src/main/java/org/keycloak/models/map/clientscope/MapClientScopeEntity.java b/model/map/src/main/java/org/keycloak/models/map/clientscope/MapClientScopeEntity.java index fd947574728..cffd48eada8 100644 --- a/model/map/src/main/java/org/keycloak/models/map/clientscope/MapClientScopeEntity.java +++ b/model/map/src/main/java/org/keycloak/models/map/clientscope/MapClientScopeEntity.java @@ -48,20 +48,6 @@ public interface MapClientScopeEntity extends AbstractEntity, UpdatableEntity, E this.id = id; this.updated |= id != null; } - - @Override - public Optional getProtocolMapper(String id) { - Set mappers = getProtocolMappers(); - if (mappers == null || mappers.isEmpty()) return Optional.empty(); - - return mappers.stream().filter(m -> Objects.equals(m.getId(), id)).findFirst(); - } - - @Override - public void removeProtocolMapper(String id) { - Set mappers = getProtocolMappers(); - this.updated |= mappers != null && mappers.removeIf(m -> Objects.equals(m.getId(), id)); - } } String getName(); diff --git a/model/map/src/main/java/org/keycloak/models/map/common/AbstractEntity.java b/model/map/src/main/java/org/keycloak/models/map/common/AbstractEntity.java index 80dd9c25027..cda50664a29 100644 --- a/model/map/src/main/java/org/keycloak/models/map/common/AbstractEntity.java +++ b/model/map/src/main/java/org/keycloak/models/map/common/AbstractEntity.java @@ -16,12 +16,15 @@ */ package org.keycloak.models.map.common; +import org.keycloak.models.map.annotations.CollectionKey; + /** * * @author hmlnarik */ public interface AbstractEntity { + @CollectionKey String getId(); void setId(String id); } diff --git a/model/map/src/main/java/org/keycloak/models/map/realm/MapRealmEntity.java b/model/map/src/main/java/org/keycloak/models/map/realm/MapRealmEntity.java index a473a9180c4..4487a081be4 100644 --- a/model/map/src/main/java/org/keycloak/models/map/realm/MapRealmEntity.java +++ b/model/map/src/main/java/org/keycloak/models/map/realm/MapRealmEntity.java @@ -100,126 +100,6 @@ public interface MapRealmEntity extends UpdatableEntity, AbstractEntity, EntityW Optional.ofNullable(getWebAuthnPolicyPasswordless()).ifPresent(UpdatableEntity::clearUpdatedFlag); } - @Override - public Optional getComponent(String componentId) { - Set cs = getComponents(); - if (cs == null || cs.isEmpty()) return Optional.empty(); - - return cs.stream().filter(c -> Objects.equals(c.getId(), componentId)).findFirst(); - } - - @Override - public Boolean removeComponent(String componentId) { - Set cs = getComponents(); - boolean removed = cs != null && cs.removeIf(c -> Objects.equals(c.getId(), componentId)); - this.updated |= removed; - return removed; - } - - @Override - public Optional getAuthenticationFlow(String flowId) { - Set afs = getAuthenticationFlows(); - if (afs == null || afs.isEmpty()) return Optional.empty(); - - return afs.stream().filter(afe -> Objects.equals(afe.getId(), flowId)).findFirst(); - } - - @Override - public Boolean removeAuthenticationFlow(String flowId) { - Set afs = getAuthenticationFlows(); - boolean removed = afs != null && afs.removeIf(af -> Objects.equals(af.getId(), flowId)); - this.updated |= removed; - return removed; - } - - @Override - public Optional getAuthenticationExecution(String executionId) { - Set aes = getAuthenticationExecutions(); - if (aes == null || aes.isEmpty()) return Optional.empty(); - - return aes.stream().filter(ae -> Objects.equals(ae.getId(), executionId)).findFirst(); - } - - @Override - public Boolean removeAuthenticationExecution(String executionId) { - Set aes = getAuthenticationExecutions(); - boolean removed = aes != null && aes.removeIf(ae -> Objects.equals(ae.getId(), executionId)); - this.updated |= removed; - return removed; - } - - @Override - public Optional getAuthenticatorConfig(String authenticatorConfigId) { - Set acs = getAuthenticatorConfigs(); - if (acs == null || acs.isEmpty()) return Optional.empty(); - - return acs.stream().filter(ac -> Objects.equals(ac.getId(), authenticatorConfigId)).findFirst(); - } - - @Override - public Boolean removeAuthenticatorConfig(String authenticatorConfigId) { - Set acs = getAuthenticatorConfigs(); - boolean removed = acs != null && acs.removeIf(ac -> Objects.equals(ac.getId(), authenticatorConfigId)); - this.updated |= removed; - return removed; - } - - @Override - public Optional getRequiredActionProvider(String requiredActionProviderId) { - Set raps = getRequiredActionProviders(); - if (raps == null || raps.isEmpty()) return Optional.empty(); - - return raps.stream().filter(ac -> Objects.equals(ac.getId(), requiredActionProviderId)).findFirst(); - } - - @Override - public Boolean removeRequiredActionProvider(String requiredActionProviderId) { - Set raps = getRequiredActionProviders(); - boolean removed = raps != null && raps.removeIf(rap -> Objects.equals(rap.getId(), requiredActionProviderId)); - this.updated |= removed; - return removed; - } - - @Override - public Boolean removeIdentityProvider(String identityProviderId) { - Set ips = getIdentityProviders(); - boolean removed = ips != null && ips.removeIf(ip -> Objects.equals(ip.getId(), identityProviderId)); - this.updated |= removed; - return removed; - } - - @Override - public Optional getIdentityProviderMapper(String identityProviderMapperId) { - Set ipms = getIdentityProviderMappers(); - if (ipms == null || ipms.isEmpty()) return Optional.empty(); - - return ipms.stream().filter(ipm -> Objects.equals(ipm.getId(), identityProviderMapperId)).findFirst(); - } - - @Override - public Boolean removeIdentityProviderMapper(String identityProviderMapperId) { - Set ipms = getIdentityProviderMappers(); - boolean removed = ipms != null && ipms.removeIf(ipm -> Objects.equals(ipm.getId(), identityProviderMapperId)); - this.updated |= removed; - return removed; - } - - @Override - public Optional getClientInitialAccess(String clientInitialAccessId) { - Set cias = getClientInitialAccesses(); - if (cias == null || cias.isEmpty()) return Optional.empty(); - - return cias.stream().filter(cia -> Objects.equals(cia.getId(), clientInitialAccessId)).findFirst(); - } - - @Override - public Boolean removeClientInitialAccess(String clientInitialAccessId) { - Set cias = getClientInitialAccesses(); - boolean removed = cias != null && cias.removeIf(cia -> Objects.equals(cia.getId(), clientInitialAccessId)); - this.updated |= removed; - return removed; - } - @Override public void removeExpiredClientInitialAccesses() { Set cias = getClientInitialAccesses(); diff --git a/model/map/src/main/java/org/keycloak/models/map/user/MapUserConsentEntity.java b/model/map/src/main/java/org/keycloak/models/map/user/MapUserConsentEntity.java index f92a0462a5c..64fb250302f 100644 --- a/model/map/src/main/java/org/keycloak/models/map/user/MapUserConsentEntity.java +++ b/model/map/src/main/java/org/keycloak/models/map/user/MapUserConsentEntity.java @@ -23,6 +23,7 @@ import org.keycloak.models.ClientScopeModel; import org.keycloak.models.ModelException; import org.keycloak.models.RealmModel; import org.keycloak.models.UserConsentModel; +import org.keycloak.models.map.annotations.CollectionKey; import org.keycloak.models.map.annotations.GenerateEntityImplementations; import org.keycloak.models.map.common.DeepCloner; import org.keycloak.models.map.common.UpdatableEntity; @@ -77,6 +78,7 @@ public interface MapUserConsentEntity extends UpdatableEntity { return model; } + @CollectionKey String getClientId(); void setClientId(String clientId); diff --git a/model/map/src/main/java/org/keycloak/models/map/user/MapUserCredentialEntity.java b/model/map/src/main/java/org/keycloak/models/map/user/MapUserCredentialEntity.java index 0036e5f1d03..d89bcce2ed4 100644 --- a/model/map/src/main/java/org/keycloak/models/map/user/MapUserCredentialEntity.java +++ b/model/map/src/main/java/org/keycloak/models/map/user/MapUserCredentialEntity.java @@ -19,6 +19,7 @@ package org.keycloak.models.map.user; import org.keycloak.credential.CredentialModel; import org.keycloak.models.map.annotations.GenerateEntityImplementations; +import org.keycloak.models.map.common.AbstractEntity; import org.keycloak.models.map.common.DeepCloner; import org.keycloak.models.map.common.UpdatableEntity; import org.keycloak.models.utils.KeycloakModelUtils; @@ -27,7 +28,7 @@ import java.util.Comparator; @GenerateEntityImplementations @DeepCloner.Root -public interface MapUserCredentialEntity extends UpdatableEntity { +public interface MapUserCredentialEntity extends AbstractEntity, UpdatableEntity { public static MapUserCredentialEntity fromModel(CredentialModel model) { MapUserCredentialEntity credentialEntity = DeepCloner.DUMB_CLONER.newInstance(MapUserCredentialEntity.class); @@ -53,9 +54,6 @@ public interface MapUserCredentialEntity extends UpdatableEntity { return model; } - String getId(); - void setId(String id); - String getType(); void setType(String type); diff --git a/model/map/src/main/java/org/keycloak/models/map/user/MapUserEntity.java b/model/map/src/main/java/org/keycloak/models/map/user/MapUserEntity.java index 11fe7699ad9..b0fe0ff9e35 100644 --- a/model/map/src/main/java/org/keycloak/models/map/user/MapUserEntity.java +++ b/model/map/src/main/java/org/keycloak/models/map/user/MapUserEntity.java @@ -80,38 +80,6 @@ public interface MapUserEntity extends UpdatableEntity, AbstractEntity, EntityWi this.setEmailConstraint(email == null || duplicateEmailsAllowed ? KeycloakModelUtils.generateId() : email); } - @Override - public Optional getUserConsent(String clientId) { - Set ucs = getUserConsents(); - if (ucs == null || ucs.isEmpty()) return Optional.empty(); - - return ucs.stream().filter(uc -> Objects.equals(uc.getClientId(), clientId)).findFirst(); - } - - @Override - public Boolean removeUserConsent(String clientId) { - Set consents = getUserConsents(); - boolean removed = consents != null && consents.removeIf(uc -> Objects.equals(uc.getClientId(), clientId)); - this.updated |= removed; - return removed; - } - - @Override - public Optional getCredential(String id) { - List uce = getCredentials(); - if (uce == null || uce.isEmpty()) return Optional.empty(); - - return uce.stream().filter(uc -> Objects.equals(uc.getId(), id)).findFirst(); - } - - @Override - public Boolean removeCredential(String id) { - List credentials = getCredentials(); - boolean removed = credentials != null && credentials.removeIf(c -> Objects.equals(c.getId(), id)); - this.updated |= removed; - return removed; - } - @Override public Boolean moveCredential(String credentialId, String newPreviousCredentialId) { // 1 - Get all credentials from the entity. @@ -154,22 +122,6 @@ public interface MapUserEntity extends UpdatableEntity, AbstractEntity, EntityWi this.updated = true; return true; } - - @Override - public Optional getFederatedIdentity(String identityProviderId) { - Set fes = getFederatedIdentities(); - if (fes == null || fes.isEmpty()) return Optional.empty(); - - return fes.stream().filter(fi -> Objects.equals(fi.getIdentityProvider(), identityProviderId)).findFirst(); - } - - @Override - public Boolean removeFederatedIdentity(String identityProviderId) { - Set federatedIdentities = getFederatedIdentities(); - boolean removed = federatedIdentities != null && federatedIdentities.removeIf(fi -> Objects.equals(fi.getIdentityProvider(), identityProviderId)); - this.updated |= removed; - return removed; - } } String getRealmId(); diff --git a/model/map/src/main/java/org/keycloak/models/map/user/MapUserFederatedIdentityEntity.java b/model/map/src/main/java/org/keycloak/models/map/user/MapUserFederatedIdentityEntity.java index 564134a546d..a906a0945ce 100644 --- a/model/map/src/main/java/org/keycloak/models/map/user/MapUserFederatedIdentityEntity.java +++ b/model/map/src/main/java/org/keycloak/models/map/user/MapUserFederatedIdentityEntity.java @@ -18,6 +18,7 @@ package org.keycloak.models.map.user; import org.keycloak.models.FederatedIdentityModel; +import org.keycloak.models.map.annotations.CollectionKey; import org.keycloak.models.map.annotations.GenerateEntityImplementations; import org.keycloak.models.map.common.DeepCloner; import org.keycloak.models.map.common.UpdatableEntity; @@ -48,6 +49,7 @@ public interface MapUserFederatedIdentityEntity extends UpdatableEntity { String getUserId(); void setUserId(String userId); + @CollectionKey String getIdentityProvider(); void setIdentityProvider(String identityProvider); diff --git a/model/map/src/main/java/org/keycloak/models/map/userSession/MapAuthenticatedClientSessionEntity.java b/model/map/src/main/java/org/keycloak/models/map/userSession/MapAuthenticatedClientSessionEntity.java index 5a855ca7ffe..1a2688ba4ba 100644 --- a/model/map/src/main/java/org/keycloak/models/map/userSession/MapAuthenticatedClientSessionEntity.java +++ b/model/map/src/main/java/org/keycloak/models/map/userSession/MapAuthenticatedClientSessionEntity.java @@ -16,6 +16,7 @@ */ package org.keycloak.models.map.userSession; +import org.keycloak.models.map.annotations.CollectionKey; import org.keycloak.models.map.annotations.GenerateEntityImplementations; import org.keycloak.models.map.common.AbstractEntity; @@ -66,6 +67,7 @@ public interface MapAuthenticatedClientSessionEntity extends AbstractEntity, Upd String getRealmId(); void setRealmId(String realmId); + @CollectionKey(priority = 1) String getClientId(); void setClientId(String clientId); diff --git a/model/map/src/main/java/org/keycloak/models/map/userSession/MapUserSessionEntity.java b/model/map/src/main/java/org/keycloak/models/map/userSession/MapUserSessionEntity.java index 918e066219e..4244102aa1e 100644 --- a/model/map/src/main/java/org/keycloak/models/map/userSession/MapUserSessionEntity.java +++ b/model/map/src/main/java/org/keycloak/models/map/userSession/MapUserSessionEntity.java @@ -69,22 +69,6 @@ public interface MapUserSessionEntity extends AbstractEntity, UpdatableEntity, E Optional.ofNullable(getAuthenticatedClientSessions()).orElseGet(Collections::emptySet).forEach(UpdatableEntity::clearUpdatedFlag); } - @Override - public Optional getAuthenticatedClientSession(String clientUUID) { - Set acss = getAuthenticatedClientSessions(); - if (acss == null || acss.isEmpty()) return Optional.empty(); - - return acss.stream().filter(acs -> Objects.equals(acs.getClientId(), clientUUID)).findFirst(); - } - - @Override - public Boolean removeAuthenticatedClientSession(String clientUUID) { - Set acss = getAuthenticatedClientSessions(); - boolean removed = acss != null && acss.removeIf(uc -> Objects.equals(uc.getClientId(), clientUUID)); - this.updated |= removed; - return removed; - } - @Override public void clearAuthenticatedClientSessions() { Set acss = getAuthenticatedClientSessions();