From c71ce8cd2e2525e3d9420e0e743a09b1de1bbb14 Mon Sep 17 00:00:00 2001 From: Markus Till Date: Fri, 2 Oct 2020 23:18:57 +0200 Subject: [PATCH] refactoring add UserProfileAttributes --- .../org/keycloak/userprofile/UserProfile.java | 15 +------ .../userprofile/UserProfileAttributes.java | 45 +++++++------------ .../userprofile/UserProfileProvider.java | 1 - .../broker/IdpReviewProfileAuthenticator.java | 4 +- .../forms/RegistrationProfile.java | 4 +- .../forms/RegistrationUserCreation.java | 10 ++--- .../requiredactions/UpdateProfile.java | 4 +- .../resources/AttributeFormDataProcessor.java | 4 +- .../resources/account/AccountFormService.java | 4 +- .../AttributeUserProfile.java | 24 +++++----- .../profile/DefaultUserProfileContext.java | 1 + .../AccountUserRepresentationUserProfile.java | 6 ++- .../representations/IdpUserProfile.java | 18 ++------ .../representations/UserModelUserProfile.java | 26 +++-------- .../UserRepresentationUserProfile.java | 6 ++- .../userprofile/utils/UserUpdateHelper.java | 17 ++++--- .../validation/StaticValidators.java | 4 +- .../validation/ValidationChain.java | 6 ++- 18 files changed, 79 insertions(+), 120 deletions(-) rename services/src/main/java/org/keycloak/userprofile/profile/AbstractUserProfile.java => server-spi-private/src/main/java/org/keycloak/userprofile/UserProfileAttributes.java (51%) rename services/src/main/java/org/keycloak/userprofile/profile/{representations => }/AttributeUserProfile.java (69%) diff --git a/server-spi-private/src/main/java/org/keycloak/userprofile/UserProfile.java b/server-spi-private/src/main/java/org/keycloak/userprofile/UserProfile.java index 125a96366ff5..a73ed45e15b6 100644 --- a/server-spi-private/src/main/java/org/keycloak/userprofile/UserProfile.java +++ b/server-spi-private/src/main/java/org/keycloak/userprofile/UserProfile.java @@ -17,9 +17,6 @@ package org.keycloak.userprofile; -import java.util.List; -import java.util.Map; - /** * Abstraction, which allows to update the user in various contexts (Required action of already existing user, or first identity provider * login when user doesn't yet exists in Keycloak DB) @@ -30,16 +27,6 @@ public interface UserProfile { String getId(); - Map> getAttributes(); - - String getFirstAttribute(String key); - - List getAttribute(String key); - - void setSingleAttribute(String key, String value); - - void setAttribute(String key, List value); - - void removeAttribute(String attr); + UserProfileAttributes getAttributes(); } diff --git a/services/src/main/java/org/keycloak/userprofile/profile/AbstractUserProfile.java b/server-spi-private/src/main/java/org/keycloak/userprofile/UserProfileAttributes.java similarity index 51% rename from services/src/main/java/org/keycloak/userprofile/profile/AbstractUserProfile.java rename to server-spi-private/src/main/java/org/keycloak/userprofile/UserProfileAttributes.java index a4f95f53e3c3..e8be91aa45b1 100644 --- a/services/src/main/java/org/keycloak/userprofile/profile/AbstractUserProfile.java +++ b/server-spi-private/src/main/java/org/keycloak/userprofile/UserProfileAttributes.java @@ -15,53 +15,38 @@ * limitations under the License. */ -package org.keycloak.userprofile.profile; - -import org.keycloak.userprofile.UserProfile; +package org.keycloak.userprofile; import java.util.Collections; -import java.util.List; +import java.util.HashMap; import java.util.Map; +import java.util.List; -/** - * @author Markus Till - */ -public abstract class AbstractUserProfile implements UserProfile { - - - /* - The user attributes handling is different in each user representation so we have to use the setAttributes and getAttributes from the original object - */ - - @Override - public abstract Map> getAttributes(); +//TODO: extend immutable map and list +//TODO: create a immutable copy of all items on create +public class UserProfileAttributes extends HashMap> { - @Override - public abstract void setAttribute(String key, List value); + public UserProfileAttributes(Map> attribtues){ + this.putAll(attribtues); + } - /* - The user id is different in each user representation - */ - @Override - public abstract String getId(); + public void setAttribute(String key, List value){ + this.put(key,value); + } - @Override public void setSingleAttribute(String key, String value) { this.setAttribute(key, Collections.singletonList(value)); } - @Override public String getFirstAttribute(String key) { - return this.getAttributes() == null ? null : this.getAttributes().get(key) == null ? null : this.getAttributes().get(key).isEmpty()? null : this.getAttributes().get(key).get(0); + return this.get(key) == null ? null : this.get(key).isEmpty()? null : this.get(key).get(0); } - @Override public List getAttribute(String key) { - return getAttributes().get(key); + return this.get(key); } - @Override public void removeAttribute(String attr) { - getAttributes().remove(attr); + this.remove(attr); } } diff --git a/server-spi-private/src/main/java/org/keycloak/userprofile/UserProfileProvider.java b/server-spi-private/src/main/java/org/keycloak/userprofile/UserProfileProvider.java index 608f2e737c9d..d5e95eb2e681 100644 --- a/server-spi-private/src/main/java/org/keycloak/userprofile/UserProfileProvider.java +++ b/server-spi-private/src/main/java/org/keycloak/userprofile/UserProfileProvider.java @@ -26,5 +26,4 @@ public interface UserProfileProvider extends Provider { UserProfileValidationResult validate(UserProfileContext updateContext, UserProfile updatedProfile); - } diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java index 38cee59b400b..5c57a50e3f16 100755 --- a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java +++ b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java @@ -38,7 +38,7 @@ import org.keycloak.userprofile.LegacyUserProfileProviderFactory; import org.keycloak.userprofile.UserProfileProvider; import org.keycloak.userprofile.profile.DefaultUserProfileContext; -import org.keycloak.userprofile.profile.representations.AttributeUserProfile; +import org.keycloak.userprofile.profile.AttributeUserProfile; import org.keycloak.userprofile.utils.UserUpdateHelper; import org.keycloak.userprofile.validation.UserProfileValidationResult; @@ -108,7 +108,7 @@ protected void actionImpl(AuthenticationFlowContext context, SerializedBrokeredI AttributeUserProfile updatedProfile = AttributeFormDataProcessor.toUserProfile(formData); String oldEmail = userCtx.getEmail(); - String newEmail = updatedProfile.getFirstAttribute(UserModel.EMAIL); + String newEmail = updatedProfile.getAttributes().getFirstAttribute(UserModel.EMAIL); UserProfileValidationResult result = profileProvider.validate(DefaultUserProfileContext.forIdpReview(userCtx), updatedProfile); List errors = Validation.getFormErrorsFromValidation(result); diff --git a/services/src/main/java/org/keycloak/authentication/forms/RegistrationProfile.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationProfile.java index cab2cf97dedb..7325a0f017b6 100755 --- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationProfile.java +++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationProfile.java @@ -37,7 +37,7 @@ import org.keycloak.userprofile.LegacyUserProfileProviderFactory; import org.keycloak.userprofile.UserProfile; import org.keycloak.userprofile.UserProfileProvider; -import org.keycloak.userprofile.profile.representations.AttributeUserProfile; +import org.keycloak.userprofile.profile.AttributeUserProfile; import org.keycloak.userprofile.utils.UserUpdateHelper; import org.keycloak.userprofile.profile.DefaultUserProfileContext; import org.keycloak.userprofile.validation.UserProfileValidationResult; @@ -76,7 +76,7 @@ public void validate(org.keycloak.authentication.ValidationContext context) { if (errors.size() > 0) { if (result.hasFailureOfErrorType(Messages.EMAIL_EXISTS, Messages.INVALID_EMAIL)) - context.getEvent().detail(Details.EMAIL, updatedProfile.getFirstAttribute(UserModel.EMAIL)); + context.getEvent().detail(Details.EMAIL, updatedProfile.getAttributes().getFirstAttribute(UserModel.EMAIL)); if (result.hasFailureOfErrorType(Messages.EMAIL_EXISTS)) { context.error(Errors.EMAIL_IN_USE); diff --git a/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java index 10e7277f65c3..af5fc33e151d 100755 --- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java +++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java @@ -40,7 +40,7 @@ import org.keycloak.userprofile.LegacyUserProfileProviderFactory; import org.keycloak.userprofile.UserProfile; import org.keycloak.userprofile.UserProfileProvider; -import org.keycloak.userprofile.profile.representations.AttributeUserProfile; +import org.keycloak.userprofile.profile.AttributeUserProfile; import org.keycloak.userprofile.utils.UserUpdateHelper; import org.keycloak.userprofile.profile.DefaultUserProfileContext; import org.keycloak.userprofile.validation.UserProfileValidationResult; @@ -72,8 +72,8 @@ public void validate(ValidationContext context) { context.getEvent().detail(Details.REGISTER_METHOD, "form"); UserProfile newProfile = AttributeFormDataProcessor.toUserProfile(context.getHttpRequest().getDecodedFormParameters()); - String email = newProfile.getFirstAttribute(UserModel.EMAIL); - String username = newProfile.getFirstAttribute(UserModel.USERNAME); + String email = newProfile.getAttributes().getFirstAttribute(UserModel.EMAIL); + String username = newProfile.getAttributes().getFirstAttribute(UserModel.USERNAME); context.getEvent().detail(Details.EMAIL, email); context.getEvent().detail(Details.USERNAME, username); @@ -114,8 +114,8 @@ public void buildPage(FormContext context, LoginFormsProvider form) { public void success(FormContext context) { AttributeUserProfile updatedProfile = AttributeFormDataProcessor.toUserProfile(context.getHttpRequest().getDecodedFormParameters()); - String email = updatedProfile.getFirstAttribute(UserModel.EMAIL); - String username = updatedProfile.getFirstAttribute(UserModel.USERNAME); + String email = updatedProfile.getAttributes().getFirstAttribute(UserModel.EMAIL); + String username = updatedProfile.getAttributes().getFirstAttribute(UserModel.USERNAME); if (context.getRealm().isRegistrationEmailAsUsername()) { username = email; } diff --git a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateProfile.java b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateProfile.java index 895a7f2659c2..3f89a738d852 100644 --- a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateProfile.java +++ b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateProfile.java @@ -35,7 +35,7 @@ import org.keycloak.services.validation.Validation; import org.keycloak.userprofile.LegacyUserProfileProviderFactory; import org.keycloak.userprofile.UserProfileProvider; -import org.keycloak.userprofile.profile.representations.AttributeUserProfile; +import org.keycloak.userprofile.profile.AttributeUserProfile; import org.keycloak.userprofile.utils.UserUpdateHelper; import org.keycloak.userprofile.profile.DefaultUserProfileContext; import org.keycloak.userprofile.validation.UserProfileValidationResult; @@ -75,7 +75,7 @@ public void processAction(RequiredActionContext context) { AttributeUserProfile updatedProfile = AttributeFormDataProcessor.toUserProfile(formData); String oldEmail = user.getEmail(); - String newEmail = updatedProfile.getFirstAttribute(UserModel.EMAIL); + String newEmail = updatedProfile.getAttributes().getFirstAttribute(UserModel.EMAIL); UserProfileProvider userProfile = context.getSession().getProvider(UserProfileProvider.class, LegacyUserProfileProviderFactory.PROVIDER_ID); UserProfileValidationResult result = userProfile.validate(DefaultUserProfileContext.forUpdateProfile(user),updatedProfile); diff --git a/services/src/main/java/org/keycloak/services/resources/AttributeFormDataProcessor.java b/services/src/main/java/org/keycloak/services/resources/AttributeFormDataProcessor.java index 15bfaafc63b4..78d1bb45e12e 100755 --- a/services/src/main/java/org/keycloak/services/resources/AttributeFormDataProcessor.java +++ b/services/src/main/java/org/keycloak/services/resources/AttributeFormDataProcessor.java @@ -19,7 +19,7 @@ import org.keycloak.models.Constants; import org.keycloak.models.UserModel; -import org.keycloak.userprofile.profile.representations.AttributeUserProfile; +import org.keycloak.userprofile.profile.AttributeUserProfile; import javax.ws.rs.core.MultivaluedMap; import java.util.ArrayList; @@ -68,7 +68,7 @@ public static AttributeUserProfile toUserProfile(MultivaluedMap private static void copyAttribute(String key, MultivaluedMap formData, AttributeUserProfile rep) { if (formData.getFirst(key) != null) - rep.setSingleAttribute(key, formData.getFirst(key)); + rep.getAttributes().setSingleAttribute(key, formData.getFirst(key)); } diff --git a/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java b/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java index 91295fd93c4b..972f46e4843f 100755 --- a/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java +++ b/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java @@ -75,7 +75,7 @@ import org.keycloak.storage.ReadOnlyException; import org.keycloak.userprofile.LegacyUserProfileProviderFactory; import org.keycloak.userprofile.UserProfileProvider; -import org.keycloak.userprofile.profile.representations.AttributeUserProfile; +import org.keycloak.userprofile.profile.AttributeUserProfile; import org.keycloak.userprofile.utils.UserUpdateHelper; import org.keycloak.userprofile.profile.DefaultUserProfileContext; import org.keycloak.userprofile.validation.UserProfileValidationResult; @@ -362,7 +362,7 @@ public Response processAccountUpdate(final MultivaluedMap formDa UserModel user = auth.getUser(); AttributeUserProfile updatedProfile = AttributeFormDataProcessor.toUserProfile(formData); String oldEmail = user.getEmail(); - String newEmail = updatedProfile.getFirstAttribute(UserModel.EMAIL); + String newEmail = updatedProfile.getAttributes().getFirstAttribute(UserModel.EMAIL); event.event(EventType.UPDATE_PROFILE).client(auth.getClient()).user(auth.getUser()); diff --git a/services/src/main/java/org/keycloak/userprofile/profile/representations/AttributeUserProfile.java b/services/src/main/java/org/keycloak/userprofile/profile/AttributeUserProfile.java similarity index 69% rename from services/src/main/java/org/keycloak/userprofile/profile/representations/AttributeUserProfile.java rename to services/src/main/java/org/keycloak/userprofile/profile/AttributeUserProfile.java index fa1168c609ab..e6c3269a95a0 100644 --- a/services/src/main/java/org/keycloak/userprofile/profile/representations/AttributeUserProfile.java +++ b/services/src/main/java/org/keycloak/userprofile/profile/AttributeUserProfile.java @@ -15,37 +15,41 @@ * limitations under the License. */ -package org.keycloak.userprofile.profile.representations; +package org.keycloak.userprofile.profile; -import org.keycloak.userprofile.profile.AbstractUserProfile; +import org.keycloak.userprofile.UserProfile; +import org.keycloak.userprofile.UserProfileAttributes; import javax.ws.rs.NotSupportedException; +import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author Markus Till */ -public class AttributeUserProfile extends AbstractUserProfile { - private final Map> attributes; +public class AttributeUserProfile implements UserProfile { + + private final UserProfileAttributes attributes; public AttributeUserProfile(Map> attributes) { - this.attributes = attributes; + this.attributes = new UserProfileAttributes(attributes); } @Override - public Map> getAttributes() { + public UserProfileAttributes getAttributes() { return this.attributes; } - @Override - public void setAttribute(String key, List value) { - this.getAttributes().put(key, value); - } + + /* + The user id is different in each user representation + */ @Override public String getId() { throw new NotSupportedException("No ID support"); } + } diff --git a/services/src/main/java/org/keycloak/userprofile/profile/DefaultUserProfileContext.java b/services/src/main/java/org/keycloak/userprofile/profile/DefaultUserProfileContext.java index 19176ab842a0..9b687ac2308e 100644 --- a/services/src/main/java/org/keycloak/userprofile/profile/DefaultUserProfileContext.java +++ b/services/src/main/java/org/keycloak/userprofile/profile/DefaultUserProfileContext.java @@ -21,6 +21,7 @@ import org.keycloak.models.UserModel; import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.userprofile.UserProfile; +import org.keycloak.userprofile.UserProfileAttributes; import org.keycloak.userprofile.UserProfileContext; import org.keycloak.userprofile.profile.representations.IdpUserProfile; import org.keycloak.userprofile.profile.representations.UserModelUserProfile; diff --git a/services/src/main/java/org/keycloak/userprofile/profile/representations/AccountUserRepresentationUserProfile.java b/services/src/main/java/org/keycloak/userprofile/profile/representations/AccountUserRepresentationUserProfile.java index 25830fed95e2..c59a23dd8f1a 100644 --- a/services/src/main/java/org/keycloak/userprofile/profile/representations/AccountUserRepresentationUserProfile.java +++ b/services/src/main/java/org/keycloak/userprofile/profile/representations/AccountUserRepresentationUserProfile.java @@ -20,6 +20,8 @@ import org.keycloak.models.UserModel; import org.keycloak.representations.account.UserRepresentation; +import org.keycloak.userprofile.UserProfileAttributes; +import org.keycloak.userprofile.profile.AttributeUserProfile; import java.util.Collections; import java.util.HashMap; @@ -35,7 +37,7 @@ public AccountUserRepresentationUserProfile(UserRepresentation user) { super(flattenUserRepresentation(user)); } - private static Map> flattenUserRepresentation(UserRepresentation user) { + private static UserProfileAttributes flattenUserRepresentation(UserRepresentation user) { Map> attrs = new HashMap<>(); if (user.getAttributes() != null) attrs.putAll(user.getAttributes()); @@ -57,7 +59,7 @@ private static Map> flattenUserRepresentation(UserRepresent attrs.put(UserModel.FIRST_NAME, Collections.singletonList(user.getFirstName())); - return attrs; + return (UserProfileAttributes)attrs; } } diff --git a/services/src/main/java/org/keycloak/userprofile/profile/representations/IdpUserProfile.java b/services/src/main/java/org/keycloak/userprofile/profile/representations/IdpUserProfile.java index a6a065d02bd4..baf07b5f0a4f 100644 --- a/services/src/main/java/org/keycloak/userprofile/profile/representations/IdpUserProfile.java +++ b/services/src/main/java/org/keycloak/userprofile/profile/representations/IdpUserProfile.java @@ -18,19 +18,18 @@ package org.keycloak.userprofile.profile.representations; import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext; -import org.keycloak.userprofile.profile.AbstractUserProfile; +import org.keycloak.userprofile.profile.AttributeUserProfile; -import java.util.List; -import java.util.Map; /** * @author Markus Till */ -public class IdpUserProfile extends AbstractUserProfile { +public class IdpUserProfile extends AttributeUserProfile { private final SerializedBrokeredIdentityContext user; public IdpUserProfile(SerializedBrokeredIdentityContext user) { + super(user.getAttributes()); this.user = user; } @@ -39,15 +38,4 @@ public String getId() { return user.getId(); } - - @Override - public Map> getAttributes() { - return user.getAttributes(); - } - - @Override - public void setAttribute(String key, List value) { - user.setAttribute(key, value); - } - } diff --git a/services/src/main/java/org/keycloak/userprofile/profile/representations/UserModelUserProfile.java b/services/src/main/java/org/keycloak/userprofile/profile/representations/UserModelUserProfile.java index ebbc5bec3f01..fa3c13f55525 100644 --- a/services/src/main/java/org/keycloak/userprofile/profile/representations/UserModelUserProfile.java +++ b/services/src/main/java/org/keycloak/userprofile/profile/representations/UserModelUserProfile.java @@ -18,40 +18,24 @@ package org.keycloak.userprofile.profile.representations; import org.keycloak.models.UserModel; -import org.keycloak.userprofile.profile.AbstractUserProfile; - -import java.util.List; -import java.util.Map; +import org.keycloak.userprofile.profile.AttributeUserProfile; /** * @author Markus Till */ -public class UserModelUserProfile extends AbstractUserProfile { +public class UserModelUserProfile extends AttributeUserProfile { - private final UserModel user; public UserModelUserProfile(UserModel user) { + super(user.getAttributes()); this.user = user; } + private final UserModel user; + @Override public String getId() { return user.getId(); } - @Override - public Map> getAttributes() { - return user.getAttributes(); - } - - @Override - public void setAttribute(String key, List value) { - user.setAttribute(key, value); - } - - @Override - public void removeAttribute(String attr) { - // Due to the fact that the user attribute list is a copy and not a reference in the user adapter we have to access the remove function directly - user.removeAttribute(attr); - } } diff --git a/services/src/main/java/org/keycloak/userprofile/profile/representations/UserRepresentationUserProfile.java b/services/src/main/java/org/keycloak/userprofile/profile/representations/UserRepresentationUserProfile.java index c2370e69f0dc..a4e55deef2bb 100644 --- a/services/src/main/java/org/keycloak/userprofile/profile/representations/UserRepresentationUserProfile.java +++ b/services/src/main/java/org/keycloak/userprofile/profile/representations/UserRepresentationUserProfile.java @@ -19,6 +19,8 @@ import org.keycloak.models.UserModel; import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.userprofile.UserProfileAttributes; +import org.keycloak.userprofile.profile.AttributeUserProfile; import java.util.Collections; import java.util.HashMap; @@ -35,7 +37,7 @@ public UserRepresentationUserProfile(UserRepresentation user) { super(flattenUserRepresentation(user)); } - private static Map> flattenUserRepresentation(UserRepresentation user) { + private static UserProfileAttributes flattenUserRepresentation(UserRepresentation user) { Map> attrs = new HashMap<>(); if (user.getAttributes() != null) attrs.putAll(user.getAttributes()); @@ -62,7 +64,7 @@ private static Map> flattenUserRepresentation(UserRepresent if (user.getEmail() != null) attrs.put(UserModel.EMAIL, Collections.singletonList(user.getEmail())); - return attrs; + return new UserProfileAttributes(attrs); } } \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/userprofile/utils/UserUpdateHelper.java b/services/src/main/java/org/keycloak/userprofile/utils/UserUpdateHelper.java index b57c37a3d1e3..188b09b7f902 100644 --- a/services/src/main/java/org/keycloak/userprofile/utils/UserUpdateHelper.java +++ b/services/src/main/java/org/keycloak/userprofile/utils/UserUpdateHelper.java @@ -21,6 +21,7 @@ import org.keycloak.models.UserModel; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.userprofile.UserProfile; +import org.keycloak.userprofile.UserProfileAttributes; import org.keycloak.userprofile.validation.UserUpdateEvent; import java.util.Collections; @@ -67,7 +68,7 @@ public static void updateUserResource(RealmModel realm, UserModel user, UserProf * @param updatedUser */ private static void update(UserUpdateEvent userUpdateEvent, RealmModel realm, UserModel currentUser, UserProfile updatedUser) { - update(userUpdateEvent, realm, currentUser, updatedUser, true); + update(userUpdateEvent, realm, currentUser, updatedUser.getAttributes(), true); } /** @@ -78,14 +79,20 @@ private static void update(UserUpdateEvent userUpdateEvent, RealmModel realm, Us * @param updatedUser */ private static void register(UserUpdateEvent userUpdateEvent, RealmModel realm, UserModel currentUser, UserProfile updatedUser) { - update(userUpdateEvent, realm, currentUser, updatedUser, false); + update(userUpdateEvent, realm, currentUser, updatedUser.getAttributes(), false); } - private static void update(UserUpdateEvent userUpdateEvent, RealmModel realm, UserModel currentUser, UserProfile updatedUser, boolean removeMissingAttributes) { + private static void update(UserUpdateEvent userUpdateEvent, RealmModel realm, UserModel currentUser, UserProfileAttributes updatedUser, boolean removeMissingAttributes) { - if (updatedUser.getAttributes() == null || updatedUser.getAttributes().size() == 0) + if (updatedUser == null || updatedUser.size() == 0) return; + filterAttributes(userUpdateEvent, realm, updatedUser); + + updateAttributes(currentUser, updatedUser, removeMissingAttributes); + } + + private static void filterAttributes(UserUpdateEvent userUpdateEvent, RealmModel realm, UserProfileAttributes updatedUser) { //The Idp review does not respect "isEditUserNameAllowed" therefore we have to miss the check here if (!userUpdateEvent.equals(UserUpdateEvent.IdpReview)) { //This step has to be done before email is assigned to the username if isRegistrationEmailAsUsername is set @@ -104,8 +111,6 @@ private static void update(UserUpdateEvent userUpdateEvent, RealmModel realm, Us updatedUser.removeAttribute(UserModel.USERNAME); updatedUser.setAttribute(UserModel.USERNAME, Collections.singletonList(updatedUser.getFirstAttribute(UserModel.EMAIL))); } - - updateAttributes(currentUser, updatedUser.getAttributes(), removeMissingAttributes); } private static void updateAttributes(UserModel currentUser, Map> updatedUser, boolean removeMissingAttributes) { diff --git a/services/src/main/java/org/keycloak/userprofile/validation/StaticValidators.java b/services/src/main/java/org/keycloak/userprofile/validation/StaticValidators.java index c5636b195199..ff75d9e93f68 100644 --- a/services/src/main/java/org/keycloak/userprofile/validation/StaticValidators.java +++ b/services/src/main/java/org/keycloak/userprofile/validation/StaticValidators.java @@ -42,7 +42,7 @@ public static BiFunction isEmailValid() { public static BiFunction userNameExists(KeycloakSession session) { return (value, context) -> !(context.getCurrentProfile() != null - && !value.equals(context.getCurrentProfile().getFirstAttribute(UserModel.USERNAME)) + && !value.equals(context.getCurrentProfile().getAttributes().getFirstAttribute(UserModel.USERNAME)) && session.users().getUserByUsername(value, session.getContext().getRealm()) != null); } @@ -50,7 +50,7 @@ public static BiFunction isUserMutable(Real return (value, context) -> !(!realm.isEditUsernameAllowed() && context.getCurrentProfile() != null - && !value.equals(context.getCurrentProfile().getFirstAttribute(UserModel.USERNAME)) + && !value.equals(context.getCurrentProfile().getAttributes().getFirstAttribute(UserModel.USERNAME)) ); } diff --git a/services/src/main/java/org/keycloak/userprofile/validation/ValidationChain.java b/services/src/main/java/org/keycloak/userprofile/validation/ValidationChain.java index 15875bfb1532..c1a592b2b8dd 100644 --- a/services/src/main/java/org/keycloak/userprofile/validation/ValidationChain.java +++ b/services/src/main/java/org/keycloak/userprofile/validation/ValidationChain.java @@ -18,6 +18,7 @@ package org.keycloak.userprofile.validation; import org.keycloak.userprofile.UserProfile; +import org.keycloak.userprofile.UserProfileAttributes; import org.keycloak.userprofile.UserProfileContext; import java.util.ArrayList; @@ -39,11 +40,12 @@ public List validate(UserProfileContext updateContext List validationResults = new ArrayList<>(); String attributeKey = attribute.attributeKey; - String attributeValue = updatedProfile.getFirstAttribute(attributeKey); + String attributeValue = updatedProfile.getAttributes().getFirstAttribute(attributeKey); boolean attributeChanged = false; if (attributeValue != null) { - attributeChanged = updateContext.getCurrentProfile() != null && !attributeValue.equals(updateContext.getCurrentProfile().getFirstAttribute(attributeKey)); + attributeChanged = updateContext.getCurrentProfile() != null + && !attributeValue.equals(updateContext.getCurrentProfile().getAttributes().getFirstAttribute(attributeKey)); for (Validator validator : attribute.validators) { validationResults.add(new ValidationResult(validator.function.apply(attributeValue, updateContext), validator.errorType)); }