diff --git a/server-spi/src/main/java/org/keycloak/userprofile/AttributeMetadata.java b/server-spi/src/main/java/org/keycloak/userprofile/AttributeMetadata.java index d641100548..016e0ec7f3 100644 --- a/server-spi/src/main/java/org/keycloak/userprofile/AttributeMetadata.java +++ b/server-spi/src/main/java/org/keycloak/userprofile/AttributeMetadata.java @@ -52,7 +52,7 @@ public class AttributeMetadata { private Map annotations; private int guiOrder; private boolean multivalued; - + AttributeMetadata(String attributeName, int guiOrder) { this(attributeName, guiOrder, ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE); @@ -210,7 +210,7 @@ public class AttributeMetadata { @Override public AttributeMetadata clone() { - AttributeMetadata cloned = new AttributeMetadata(attributeName, guiOrder, selector, writeAllowed, required, readAllowed); + AttributeMetadata cloned = new AttributeMetadata(attributeName, guiOrder, selector, new ArrayList<>(writeAllowed), required, new ArrayList<>(readAllowed)); // we clone validators list to allow adding or removing validators. Validators // itself are not cloned as we do not expect them to be reconfigured. if (validators != null) { @@ -227,7 +227,7 @@ public class AttributeMetadata { cloned.setMultivalued(multivalued); return cloned; } - + public String getAttributeDisplayName() { if(attributeDisplayName == null || attributeDisplayName.trim().isEmpty()) return attributeName; diff --git a/services/src/main/java/org/keycloak/userprofile/DeclarativeUserProfileProvider.java b/services/src/main/java/org/keycloak/userprofile/DeclarativeUserProfileProvider.java index f40cd81a52..d5e1a227c5 100644 --- a/services/src/main/java/org/keycloak/userprofile/DeclarativeUserProfileProvider.java +++ b/services/src/main/java/org/keycloak/userprofile/DeclarativeUserProfileProvider.java @@ -189,7 +189,7 @@ public class DeclarativeUserProfileProvider implements UserProfileProvider { component.setNote(PARSED_CONFIG_COMPONENT_KEY, metadataMap); } - return metadataMap.computeIfAbsent(context, createUserDefinedProfileDecorator(session, decoratedMetadata, component)); + return metadataMap.computeIfAbsent(context, createUserDefinedProfileDecorator(session, decoratedMetadata, component)).clone(); } @Override diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPUserProfileTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPUserProfileTest.java index dd0ecf15d8..5938be3fa4 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPUserProfileTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/ldap/LDAPUserProfileTest.java @@ -288,6 +288,11 @@ public class LDAPUserProfileTest extends AbstractLDAPTest { userResource = ApiUtil.findUserByUsernameId(testRealm(), "johnkeycloak"); userRep = userResource.toRepresentation(true); assertProfileAttributes(userRep, null, true, "username", "email", "firstName", "lastName", "postal_code"); + + // the second provider is not readonly + userResource = ApiUtil.findUserByUsernameId(testRealm(), "anotherjohn"); + userRep = userResource.toRepresentation(true); + assertProfileAttributes(userRep, null, false, "username", "email", "firstName", "lastName"); } finally { setLDAPWritable(); }