Update UserProfileProvider.setConfiguration. Tuning of UserProfileProvider.getConfiguration

closes #25416

Signed-off-by: mposolda <mposolda@gmail.com>
This commit is contained in:
mposolda 2023-12-13 19:21:45 +01:00 committed by Marek Posolda
parent 26342d829c
commit c81b533cf6
14 changed files with 201 additions and 145 deletions

View file

@ -19,6 +19,7 @@
package org.keycloak.representations.userprofile.config;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
@ -27,7 +28,7 @@ import java.util.Map;
* @author Vlastimil Elias <velias@redhat.com>
*
*/
public class UPAttribute {
public class UPAttribute implements Cloneable {
private String name;
private String displayName;
@ -144,4 +145,29 @@ public class UPAttribute {
public String toString() {
return "UPAttribute [name=" + name + ", displayName=" + displayName + ", permissions=" + permissions + ", selector=" + selector + ", required=" + required + ", validations=" + validations + ", annotations=" + annotations + ", group=" + group + "]";
}
@Override
protected UPAttribute clone() {
UPAttribute attr = new UPAttribute(this.name);
attr.setDisplayName(this.displayName);
Map<String, Map<String, Object>> validations;
if (this.validations == null) {
validations = null;
} else {
validations = new LinkedHashMap<>();
for (Map.Entry<String, Map<String, Object>> entry : this.validations.entrySet()) {
Map<String, Object> newVal = entry.getValue() == null ? null : new LinkedHashMap<>(entry.getValue());
validations.put(entry.getKey(), newVal);
}
}
attr.setValidations(validations);
attr.setAnnotations(this.annotations == null ? null : new HashMap<>(this.annotations));
attr.setRequired(this.required == null ? null : this.required.clone());
attr.setPermissions(this.permissions == null ? null : this.permissions.clone());
attr.setSelector(this.selector == null ? null : this.selector.clone());
attr.setGroup(this.group);
return attr;
}
}

View file

@ -19,6 +19,7 @@
package org.keycloak.representations.userprofile.config;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import com.fasterxml.jackson.annotation.JsonIgnore;
@ -28,7 +29,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
* @author Vlastimil Elias <velias@redhat.com>
*
*/
public class UPAttributePermissions {
public class UPAttributePermissions implements Cloneable {
private Set<String> view = Collections.emptySet();
private Set<String> edit = Collections.emptySet();
@ -67,4 +68,11 @@ public class UPAttributePermissions {
public boolean isEmpty() {
return getEdit().isEmpty() && getView().isEmpty();
}
@Override
protected UPAttributePermissions clone() {
Set<String> view = this.view == null ? null : new HashSet<>(this.view);
Set<String> edit = this.edit == null ? null : new HashSet<>(this.edit);
return new UPAttributePermissions(view, edit);
}
}

View file

@ -18,6 +18,7 @@
*/
package org.keycloak.representations.userprofile.config;
import java.util.HashSet;
import java.util.Set;
import com.fasterxml.jackson.annotation.JsonIgnore;
@ -28,7 +29,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
* @author Vlastimil Elias <velias@redhat.com>
*
*/
public class UPAttributeRequired {
public class UPAttributeRequired implements Cloneable {
private Set<String> roles;
private Set<String> scopes;
@ -74,4 +75,11 @@ public class UPAttributeRequired {
return "UPAttributeRequired [isAlways=" + isAlways() + ", roles=" + roles + ", scopes=" + scopes + "]";
}
@Override
protected UPAttributeRequired clone() {
Set<String> scopes = this.scopes == null ? null : new HashSet<>(this.scopes);
Set<String> roles = this.roles == null ? null : new HashSet<>(this.roles);
return new UPAttributeRequired(roles, scopes);
}
}

View file

@ -18,6 +18,7 @@
*/
package org.keycloak.representations.userprofile.config;
import java.util.HashSet;
import java.util.Set;
/**
@ -26,7 +27,7 @@ import java.util.Set;
* @author Vlastimil Elias <velias@redhat.com>
*
*/
public class UPAttributeSelector {
public class UPAttributeSelector implements Cloneable {
private Set<String> scopes;
@ -51,4 +52,8 @@ public class UPAttributeSelector {
return "UPAttributeSelector [scopes=" + scopes + "]";
}
@Override
protected UPAttributeSelector clone() {
return new UPAttributeSelector(scopes == null ? null : new HashSet<>(scopes));
}
}

View file

@ -21,6 +21,8 @@ package org.keycloak.representations.userprofile.config;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
@ -29,7 +31,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
* @author Vlastimil Elias <velias@redhat.com>
*
*/
public class UPConfig {
public class UPConfig implements Cloneable {
public enum UnmanagedAttributePolicy {
@ -120,4 +122,19 @@ public class UPConfig {
public String toString() {
return "UPConfig [attributes=" + attributes + ", groups=" + groups + "]";
}
@Override
public UPConfig clone() {
UPConfig cfg = new UPConfig();
cfg.setUnmanagedAttributePolicy(this.unmanagedAttributePolicy);
if (attributes != null) {
cfg.setAttributes(attributes.stream().map(UPAttribute::clone).collect(Collectors.toList()));
}
if (groups != null) {
cfg.setGroups(groups.stream().map(UPGroup::clone).collect(Collectors.toList()));
}
return cfg;
}
}

View file

@ -19,6 +19,7 @@
package org.keycloak.representations.userprofile.config;
import java.util.HashMap;
import java.util.Map;
/**
@ -26,7 +27,7 @@ import java.util.Map;
*
* @author <a href="joerg.matysiak@bosch.io">Jörg Matysiak</a>
*/
public class UPGroup {
public class UPGroup implements Cloneable {
private String name;
private String displayHeader;
@ -72,4 +73,13 @@ public class UPGroup {
public void setAnnotations(Map<String, Object> annotations) {
this.annotations = annotations;
}
@Override
protected UPGroup clone() {
UPGroup group = new UPGroup(this.name);
group.setDisplayHeader(displayHeader);
group.setDisplayDescription(displayDescription);
group.setAnnotations(this.annotations == null ? null : new HashMap<>(this.annotations));
return group;
}
}

View file

@ -75,15 +75,7 @@ public class UIRealmResource {
return;
}
String rawUpConfig;
try {
rawUpConfig = JsonSerialization.writeValueAsString(upConfig);
} catch (IOException e) {
throw new InternalServerErrorException("Failed to parse user profile config", e);
}
Response response = new UserProfileResource(session, auth).update(rawUpConfig);
Response response = new UserProfileResource(session, auth).update(upConfig);
if (isSuccessful(response)) {
return;

View file

@ -74,20 +74,20 @@ public interface UserProfileProvider extends Provider {
* Get current UserProfile configuration.
*
* @return current UserProfile configuration
* @see #setConfiguration(String)
* @see #setConfiguration(UPConfig)
*/
UPConfig getConfiguration();
/**
* Set new UserProfile configuration. It is persisted inside of the provider.
*
* @param configuration to be set
* @param configuration to be set. It can be null and in this case, userProfile implementation will switch to use the default configuration
* @throws RuntimeException if configuration is invalid (exact exception class
* depends on the implementation) or configuration
* can't be persisted.
* @see #getConfiguration()
*/
void setConfiguration(String configuration);
void setConfiguration(UPConfig configuration);
/**
* Returns whether the declarative provider is enabled to a realm

View file

@ -32,29 +32,20 @@ import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.extensions.Extension;
import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.keycloak.component.ComponentValidationException;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.provider.ConfiguredProvider;
import org.keycloak.representations.idm.UserProfileAttributeGroupMetadata;
import org.keycloak.representations.idm.UserProfileAttributeMetadata;
import org.keycloak.representations.idm.UserProfileMetadata;
import org.keycloak.services.ErrorResponse;
import org.keycloak.services.resources.KeycloakOpenAPI;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.userprofile.AttributeMetadata;
import org.keycloak.userprofile.AttributeValidatorMetadata;
import org.keycloak.userprofile.Attributes;
import org.keycloak.userprofile.UserProfile;
import org.keycloak.userprofile.UserProfileContext;
import org.keycloak.userprofile.UserProfileProvider;
import org.keycloak.representations.userprofile.config.UPConfig;
import org.keycloak.representations.userprofile.config.UPGroup;
import org.keycloak.validate.Validators;
/**
* @author Vlastimil Elias <velias@redhat.com>
@ -99,13 +90,12 @@ public class UserProfileResource {
@Tag(name = KeycloakOpenAPI.Admin.Tags.USERS)
@Operation(description = "Set the configuration for the user profile")
@APIResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = UPConfig.class)))
public Response update(
@RequestBody(content = @Content(schema = @Schema(implementation = UPConfig.class))) String text) {
public Response update(UPConfig config) {
auth.realm().requireManageRealm();
UserProfileProvider t = session.getProvider(UserProfileProvider.class);
try {
t.setConfiguration(text);
t.setConfiguration(config);
} catch (ComponentValidationException e) {
//show validation result containing details about error
throw ErrorResponse.error(e.getMessage(), Response.Status.BAD_REQUEST);

View file

@ -54,6 +54,7 @@ import org.keycloak.representations.userprofile.config.UPGroup;
import org.keycloak.userprofile.validator.AttributeRequiredByMetadataValidator;
import org.keycloak.userprofile.validator.BlankAttributeValidator;
import org.keycloak.userprofile.validator.ImmutableAttributeValidator;
import org.keycloak.util.JsonSerialization;
import org.keycloak.validate.AbstractSimpleValidator;
import org.keycloak.validate.ValidatorConfig;
@ -68,7 +69,8 @@ public class DeclarativeUserProfileProvider implements UserProfileProvider {
public static final String UP_COMPONENT_CONFIG_KEY = "kc.user.profile.config";
public static final String REALM_USER_PROFILE_ENABLED = "userProfileEnabled";
protected static final String PARSED_CONFIG_COMPONENT_KEY = "kc.user.profile.metadata"; // TODO:mposolda should it be here or rather on factory?
protected static final String PARSED_CONFIG_COMPONENT_KEY = "kc.user.profile.metadata";
protected static final String PARSED_UP_CONFIG_COMPONENT_KEY = "kc.parsed.up.config";
/**
* Method used for predicate which returns true if any of the configuredScopes is requested in current auth flow.
@ -95,7 +97,6 @@ public class DeclarativeUserProfileProvider implements UserProfileProvider {
private final boolean isDeclarativeConfigurationEnabled;
private final String providerId;
private final Map<UserProfileContext, UserProfileMetadata> contextualMetadataRegistry;
private final String defaultRawConfig;
protected final UPConfig parsedDefaultRawConfig;
public DeclarativeUserProfileProvider(KeycloakSession session, DeclarativeUserProfileProviderFactory factory) {
@ -103,7 +104,6 @@ public class DeclarativeUserProfileProvider implements UserProfileProvider {
this.providerId = factory.getId();
this.isDeclarativeConfigurationEnabled = factory.isDeclarativeConfigurationEnabled();
this.contextualMetadataRegistry = factory.getContextualMetadataRegistry();
this.defaultRawConfig = factory.getDefaultRawConfig();
this.parsedDefaultRawConfig = factory.getParsedDefaultRawConfig();
}
@ -214,42 +214,41 @@ public class DeclarativeUserProfileProvider implements UserProfileProvider {
RealmModel realm = session.getContext().getRealm();
if (!isEnabled(realm)) {
return getParsedConfig(defaultRawConfig);
return parsedDefaultRawConfig.clone();
}
Optional<ComponentModel> component = getComponentModel();
if (component.isPresent()) {
String cfg = getConfigJsonFromComponentModel(component.get());
if (isBlank(cfg)) {
return getParsedConfig(defaultRawConfig);
UPConfig cfg = getConfigFromComponentModel(component.get()).clone();
return cfg == null ? parsedDefaultRawConfig.clone() : cfg;
}
return getParsedConfig(cfg);
}
return getParsedConfig(defaultRawConfig);
return parsedDefaultRawConfig.clone();
}
@Override
public void setConfiguration(String configuration) {
public void setConfiguration(UPConfig configuration) {
RealmModel realm = session.getContext().getRealm();
Optional<ComponentModel> optionalComponent = realm.getComponentsStream(realm.getId(), UserProfileProvider.class.getName()).findAny();
// Avoid creating componentModel and then removing it right away
if (!optionalComponent.isPresent() && isBlank(configuration)) return;
if (!optionalComponent.isPresent() && configuration == null) return;
ComponentModel component = optionalComponent.isPresent() ? optionalComponent.get() : createComponentModel();
removeConfigJsonFromComponentModel(component);
if (isBlank(configuration)) {
if (configuration == null) {
realm.removeComponent(component);
return;
}
component.getConfig().putSingle(UP_COMPONENT_CONFIG_KEY, configuration);
try {
component.getConfig().putSingle(UP_COMPONENT_CONFIG_KEY, JsonSerialization.writeValueAsString(configuration));
} catch (IOException ioe) {
throw new RuntimeException("Cannot write component config", ioe);
}
realm.updateComponent(component);
}
@ -475,11 +474,23 @@ public class DeclarativeUserProfileProvider implements UserProfileProvider {
return new AttributeValidatorMetadata(validator, ValidatorConfig.builder().config(validatorConfig).config(AbstractSimpleValidator.IGNORE_EMPTY_VALUE, true).build());
}
private String getConfigJsonFromComponentModel(ComponentModel model) {
private UPConfig getConfigFromComponentModel(ComponentModel model) {
if (model == null)
return null;
return model.get(UP_COMPONENT_CONFIG_KEY);
UPConfig cfg = model.getNote(PARSED_UP_CONFIG_COMPONENT_KEY);
if (cfg != null) {
return cfg;
}
String rawConfig = model.get(UP_COMPONENT_CONFIG_KEY);
if (rawConfig == null) {
return null;
} else {
cfg = getParsedConfig(rawConfig);
model.setNote(PARSED_UP_CONFIG_COMPONENT_KEY, cfg);
return cfg;
}
}
private void removeConfigJsonFromComponentModel(ComponentModel model) {
@ -500,7 +511,7 @@ public class DeclarativeUserProfileProvider implements UserProfileProvider {
private Function<UserProfileContext, UserProfileMetadata> createUserDefinedProfileDecorator(KeycloakSession session, UserProfileMetadata decoratedMetadata, ComponentModel component) {
return (c) -> {
UPConfig parsedConfig = getParsedConfig(getConfigJsonFromComponentModel(component));
UPConfig parsedConfig = getConfigFromComponentModel(component);
//validate configuration to catch things like changed/removed validators etc, and warn early and clearly about this problem
List<String> errors = UPConfigUtils.validate(session, parsedConfig);

View file

@ -87,7 +87,6 @@ public class DeclarativeUserProfileProviderFactory implements UserProfileProvide
private boolean isDeclarativeConfigurationEnabled;
private String defaultRawConfig;
private UPConfig parsedDefaultRawConfig;
private final Map<UserProfileContext, UserProfileMetadata> contextualMetadataRegistry = new HashMap<>();
@ -200,12 +199,7 @@ public class DeclarativeUserProfileProviderFactory implements UserProfileProvide
@Override
public void init(Config.Scope config) {
isDeclarativeConfigurationEnabled = Profile.isFeatureEnabled(Profile.Feature.DECLARATIVE_USER_PROFILE);
defaultRawConfig = UPConfigUtils.readDefaultConfig();
try {
parsedDefaultRawConfig = UPConfigUtils.parseConfig(defaultRawConfig);
} catch (IOException cause) {
throw new RuntimeException("Failed to parse default user profile configuration", cause);
}
parsedDefaultRawConfig = UPConfigUtils.parseDefaultConfig();
// make sure registry is clear in case of re-deploy
contextualMetadataRegistry.clear();
@ -446,10 +440,6 @@ public class DeclarativeUserProfileProviderFactory implements UserProfileProvide
return isDeclarativeConfigurationEnabled;
}
protected String getDefaultRawConfig() {
return defaultRawConfig;
}
protected UPConfig getParsedDefaultRawConfig() {
return parsedDefaultRawConfig;
}

View file

@ -83,7 +83,12 @@ public abstract class AbstractUserProfileTest extends AbstractTestRealmKeycloakT
protected static void setConfiguration(KeycloakSession session, String config) {
UserProfileProvider provider = getUserProfileProvider(session);
provider.setConfiguration(config);
try {
UPConfig upConfig = config == null ? null : UPConfigUtils.parseConfig(config);
provider.setConfiguration(upConfig);
} catch (IOException ioe) {
throw new RuntimeException("Error when parsing user-profile config: " + config, ioe);
}
}
protected static UserProfileProvider getUserProfileProvider(KeycloakSession session) {

View file

@ -54,7 +54,7 @@ public class CustomUserProfileTest extends AbstractUserProfileTest {
UserProfileProvider provider = getUserProfileProvider(session);
assertEquals(CustomUserProfileProvider.class.getName(), provider.getClass().getName());
assertTrue(provider instanceof CustomUserProfileProvider);
provider.setConfiguration(UPConfigUtils.readDefaultConfig());
provider.setConfiguration(UPConfigUtils.parseDefaultConfig());
Optional<ComponentModel> component = getComponentModel(session);
assertTrue(component.isPresent());
assertEquals("custom-user-profile", component.get().getProviderId());
@ -66,12 +66,10 @@ public class CustomUserProfileTest extends AbstractUserProfileTest {
}
private static void testInvalidConfiguration(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
try {
provider.setConfiguration("{\"validateConfigAttribute\": true}");
setConfiguration(session, "{\"validateConfigAttribute\": true}");
fail("Should fail validation");
} catch (ComponentValidationException ve) {
} catch (RuntimeException ve) {
// OK
}
}

View file

@ -32,7 +32,6 @@ import static org.keycloak.userprofile.config.UPConfigUtils.ROLE_USER;
import static org.keycloak.userprofile.config.UPConfigUtils.parseDefaultConfig;
import jakarta.ws.rs.core.Response;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -79,7 +78,6 @@ import org.keycloak.userprofile.UserProfileContext;
import org.keycloak.userprofile.UserProfileProvider;
import org.keycloak.userprofile.ValidationException;
import org.keycloak.userprofile.validator.UsernameIDNHomographValidator;
import org.keycloak.util.JsonSerialization;
import org.keycloak.validate.ValidationError;
import org.keycloak.validate.validators.EmailValidator;
import org.keycloak.validate.validators.LengthValidator;
@ -138,7 +136,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
UPConfig upConfig = provider.getConfiguration();
upConfig.getAttribute("foo")
.setValidations(Map.of("length", Map.of("min", "5", "max", "15")));
provider.setConfiguration(JsonSerialization.writeValueAsString(upConfig));
provider.setConfiguration(upConfig);
Map<String, List<String>> attributes = new HashMap<>(user.getAttributes());
UserProfile profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes, user);
profile.validate();
@ -165,7 +163,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
UPAttribute changedFoo = upConfig.getAttribute("foo");
changedFoo.setPermissions(new UPAttributePermissions(Set.of(), Set.of(ROLE_USER, ROLE_ADMIN)));
changedFoo.setValidations(Map.of("length", Map.of("min", "5", "max", "15")));
provider.setConfiguration(JsonSerialization.writeValueAsString(upConfig));
provider.setConfiguration(upConfig);
Map<String, List<String>> attributes = new HashMap<>(user.getAttributes());
UserProfile profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes, user);
@ -196,7 +194,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testCustomAttributeInAnyContext);
}
private static void testCustomAttributeInAnyContext(KeycloakSession session) throws IOException {
private static void testCustomAttributeInAnyContext(KeycloakSession session) {
Map<String, Object> attributes = new HashMap<>();
attributes.put(UserModel.USERNAME, "profiled-user");
@ -207,7 +205,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
config.addOrReplaceAttribute(new UPAttribute("address", new UPAttributePermissions(Set.of(), Set.of(ROLE_USER)), new UPAttributeRequired()));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
UserProfile profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes);
@ -235,7 +233,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testResolveProfile);
}
private static void testResolveProfile(KeycloakSession session) throws IOException {
private static void testResolveProfile(KeycloakSession session) {
configureAuthenticationSession(session);
Map<String, Object> attributes = new HashMap<>();
@ -248,7 +246,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
config.addOrReplaceAttribute(new UPAttribute("business.address", new UPAttributePermissions(Set.of(), Set.of(ROLE_USER)), new UPAttributeRequired(Set.of(), Set.of("customer"))));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
UserProfile profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes);
@ -276,7 +274,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testAttributeValidation);
}
private static void failValidationWhenEmptyAttributes(KeycloakSession session) throws IOException {
private static void failValidationWhenEmptyAttributes(KeycloakSession session) {
Map<String, Object> attributes = new HashMap<>();
UserProfileProvider provider = session.getProvider(UserProfileProvider.class);
provider.setConfiguration(null);
@ -325,7 +323,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
email.setRequired(null);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
attributes.clear();
attributes.put(UserModel.USERNAME, "profile-user");
@ -367,14 +365,14 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testValidateComplianceWithUserProfile);
}
private static void testValidateComplianceWithUserProfile(KeycloakSession session) throws IOException {
private static void testValidateComplianceWithUserProfile(KeycloakSession session) {
RealmModel realm = session.getContext().getRealm();
UserModel user = session.users().addUser(realm, "profiled-user");
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
config.addOrReplaceAttribute(new UPAttribute("address", new UPAttributePermissions(Set.of(), Set.of(ROLE_USER)), new UPAttributeRequired()));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
UserProfile profile = provider.create(UserProfileContext.ACCOUNT, user);
@ -401,7 +399,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testGetProfileAttributes);
}
private static void testGetProfileAttributes(KeycloakSession session) throws IOException {
private static void testGetProfileAttributes(KeycloakSession session) {
RealmModel realm = session.getContext().getRealm();
UserModel user = session.users().addUser(realm, org.keycloak.models.utils.KeycloakModelUtils.generateId());
user.setFirstName("John");
@ -411,7 +409,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
config.addOrReplaceAttribute(new UPAttribute("address", new UPAttributePermissions(Set.of(), Set.of(ROLE_USER)), new UPAttributeRequired()));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
UserProfile profile = provider.create(UserProfileContext.ACCOUNT, user);
Attributes attributes = profile.getAttributes();
@ -448,7 +446,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testGetProfileAttributeGroups);
}
private static void testGetProfileAttributeGroups(KeycloakSession session) throws IOException {
private static void testGetProfileAttributeGroups(KeycloakSession session) {
RealmModel realm = session.getContext().getRealm();
UserModel user = session.users().addUser(realm, org.keycloak.models.utils.KeycloakModelUtils.generateId());
UserProfileProvider provider = getUserProfileProvider(session);
@ -462,7 +460,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
groupWithAnnotation.setAnnotations(Map.of("anno1", "value1", "anno2", "value2"));
config.addGroup(groupWithAnnotation);
config.addOrReplaceAttribute(new UPAttribute("second", groupWithAnnotation));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
UserProfile profile = provider.create(UserProfileContext.ACCOUNT, user);
Attributes attributes = profile.getAttributes();
@ -492,13 +490,13 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testCreateAndUpdateUser);
}
private static void testCreateAndUpdateUser(KeycloakSession session) throws IOException {
private static void testCreateAndUpdateUser(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = provider.getConfiguration();
config.addOrReplaceAttribute(new UPAttribute("address", new UPAttributePermissions(Set.of(), Set.of(ROLE_ADMIN, ROLE_USER))));
config.addOrReplaceAttribute(new UPAttribute("business.address", new UPAttributePermissions(Set.of(), Set.of(ROLE_ADMIN, ROLE_USER))));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
Map<String, Object> attributes = new HashMap<>();
String userName = org.keycloak.models.utils.KeycloakModelUtils.generateId();
@ -558,7 +556,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testReadonlyUpdates);
}
private static void testReadonlyUpdates(KeycloakSession session) throws IOException {
private static void testReadonlyUpdates(KeycloakSession session) {
Map<String, Object> attributes = new HashMap<>();
attributes.put(UserModel.USERNAME, org.keycloak.models.utils.KeycloakModelUtils.generateId());
@ -571,7 +569,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
config.addOrReplaceAttribute(new UPAttribute("department", new UPAttributePermissions(Set.of(), Set.of(ROLE_ADMIN))));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
UserProfile profile = provider.create(UserProfileContext.ACCOUNT, attributes);
UserModel user = profile.create();
@ -612,7 +610,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testReadonlyEmailCannotBeUpdated);
}
private static void testReadonlyEmailCannotBeUpdated(KeycloakSession session) throws IOException {
private static void testReadonlyEmailCannotBeUpdated(KeycloakSession session) {
Map<String, Object> attributes = new HashMap<>();
attributes.put(UserModel.USERNAME, org.keycloak.models.utils.KeycloakModelUtils.generateId());
@ -625,7 +623,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
config.addOrReplaceAttribute(new UPAttribute("email", new UPAttributePermissions(Set.of(), Set.of(ROLE_ADMIN))));
// configure email r/o for user
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
UserProfile profile = provider.create(UserProfileContext.ACCOUNT, attributes);
UserModel user = profile.create();
@ -661,7 +659,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testUpdateEmail);
}
private static void testUpdateEmail(KeycloakSession session) throws IOException {
private static void testUpdateEmail(KeycloakSession session) {
Map<String, Object> attributes = new HashMap<>();
attributes.put(UserModel.USERNAME, org.keycloak.models.utils.KeycloakModelUtils.generateId());
@ -675,7 +673,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
config.getAttribute("email").getPermissions().setEdit(Set.of(ROLE_USER, ROLE_ADMIN));
// configure email r/w for user
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
UserProfile profile = provider.create(UserProfileContext.ACCOUNT, attributes);
UserModel user = profile.create();
@ -703,7 +701,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testDoNotUpdateUndefinedAttributes);
}
private static void testDoNotUpdateUndefinedAttributes(KeycloakSession session) throws IOException {
private static void testDoNotUpdateUndefinedAttributes(KeycloakSession session) {
Map<String, Object> attributes = new HashMap<>();
attributes.put(UserModel.USERNAME, org.keycloak.models.utils.KeycloakModelUtils.generateId());
@ -719,7 +717,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
config.addOrReplaceAttribute(new UPAttribute("department", new UPAttributePermissions(Set.of(), Set.of(ROLE_ADMIN))));
config.addOrReplaceAttribute(new UPAttribute("phone", new UPAttributePermissions(Set.of(), Set.of(ROLE_ADMIN))));
config.addOrReplaceAttribute(new UPAttribute("address", new UPAttributePermissions(Set.of(), Set.of(ROLE_ADMIN))));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
UserProfile profile = provider.create(UserProfileContext.ACCOUNT, attributes);
UserModel user = profile.create();
@ -735,7 +733,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
assertThat(attributesUpdated, containsInAnyOrder("department", "address", "phone"));
config.removeAttribute("address");
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
attributesUpdated.clear();
attributes.remove("address");
attributes.put("department", "foo");
@ -746,7 +744,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
assertTrue(user.getAttributes().containsKey("address"));
config.addOrReplaceAttribute(new UPAttribute("address", new UPAttributePermissions(Set.of(), Set.of(ROLE_ADMIN))));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
attributes.put("department", "foo");
attributes.put("phone", "foo");
attributes.put("address", "bar");
@ -794,12 +792,10 @@ public class UserProfileTest extends AbstractUserProfileTest {
}
private static void testInvalidConfiguration(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
try {
provider.setConfiguration("{\"validateConfigAttribute\": true}");
setConfiguration(session, "{\"validateConfigAttribute\": true}");
fail("Should fail validation");
} catch (ComponentValidationException ve) {
} catch (RuntimeException ve) {
// OK
}
@ -810,7 +806,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testResetConfiguration);
}
private static void testResetConfiguration(KeycloakSession session) throws IOException {
private static void testResetConfiguration(KeycloakSession session) {
setConfiguration(session, null);
assertFalse(getComponentModel(session).isPresent());
}
@ -870,7 +866,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testCustomValidationForUsername);
}
private static void testCustomValidationForUsername(KeycloakSession session) throws IOException {
private static void testCustomValidationForUsername(KeycloakSession session) {
UPConfig config = parseDefaultConfig();
UPAttribute attribute = new UPAttribute(UserModel.USERNAME);
@ -883,7 +879,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
config.addOrReplaceAttribute(attribute);
UserProfileProvider provider = getUserProfileProvider(session);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
Map<String, Object> attributes = new HashMap<>();
@ -925,7 +921,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testRemoveDefaultValidationFromUsername);
}
private static void testRemoveDefaultValidationFromUsername(KeycloakSession session) throws IOException {
private static void testRemoveDefaultValidationFromUsername(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
// reset configuration to default
@ -956,7 +952,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
}
}
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes);
@ -968,7 +964,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testOptionalAttributes);
}
private static void testOptionalAttributes(KeycloakSession session) throws IOException {
private static void testOptionalAttributes(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
UPAttribute attribute = new UPAttribute();
@ -983,7 +979,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
attribute.addValidation(LengthValidator.ID, validatorConfig);
config.addOrReplaceAttribute(attribute);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
Map<String, Object> attributes = new HashMap<>();
@ -1026,7 +1022,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testCustomAttributeRequired);
}
private static void testCustomAttributeRequired(KeycloakSession session) throws IOException {
private static void testCustomAttributeRequired(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
UPAttribute attribute = new UPAttribute();
@ -1049,7 +1045,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
config.addOrReplaceAttribute(attribute);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
Map<String, Object> attributes = new HashMap<>();
@ -1092,7 +1088,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testCustomAttributeOptional);
}
private static void testCustomAttributeOptional(KeycloakSession session) throws IOException {
private static void testCustomAttributeOptional(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
UPAttribute attribute = new UPAttribute();
@ -1105,7 +1101,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
config.addOrReplaceAttribute(attribute);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
Map<String, Object> attributes = new HashMap<>();
attributes.put(UserModel.USERNAME, "user");
@ -1144,11 +1140,11 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testRequiredIfUser);
}
private static void testRequiredIfUser(KeycloakSession session) throws IOException {
private static void testRequiredIfUser(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
config.addOrReplaceAttribute(new UPAttribute(ATT_ADDRESS, new UPAttributePermissions(Set.of(), Set.of(ROLE_USER)), new UPAttributeRequired(Set.of(ROLE_USER), Set.of())));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
Map<String, Object> attributes = new HashMap<>();
@ -1192,11 +1188,11 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testRequiredIfAdmin);
}
private static void testRequiredIfAdmin(KeycloakSession session) throws IOException {
private static void testRequiredIfAdmin(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
config.addOrReplaceAttribute(new UPAttribute(ATT_ADDRESS, new UPAttributePermissions(Set.of(), Set.of(ROLE_ADMIN)), new UPAttributeRequired(Set.of(ROLE_ADMIN), Set.of())));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
Map<String, Object> attributes = new HashMap<>();
@ -1231,11 +1227,11 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testNoValidationsIfUserReadOnly);
}
private static void testNoValidationsIfUserReadOnly(KeycloakSession session) throws IOException {
private static void testNoValidationsIfUserReadOnly(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
config.addOrReplaceAttribute(new UPAttribute(ATT_ADDRESS, new UPAttributePermissions(Set.of(), Set.of(ROLE_ADMIN)), new UPAttributeRequired()));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
Map<String, Object> attributes = new HashMap<>();
@ -1264,11 +1260,11 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testNoValidationsIfAdminReadOnly);
}
private static void testNoValidationsIfAdminReadOnly(KeycloakSession session) throws IOException {
private static void testNoValidationsIfAdminReadOnly(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
config.addOrReplaceAttribute(new UPAttribute(ATT_ADDRESS, new UPAttributePermissions(Set.of(), Set.of(ROLE_USER)), new UPAttributeRequired()));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
Map<String, Object> attributes = new HashMap<>();
@ -1293,12 +1289,12 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testIgnoreReadOnlyAttribute);
}
private static void testIgnoreReadOnlyAttribute(KeycloakSession session) throws IOException {
private static void testIgnoreReadOnlyAttribute(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
config.addOrReplaceAttribute(new UPAttribute(ATT_ADDRESS, new UPAttributePermissions(Set.of(ROLE_ADMIN), Set.of(ROLE_USER)), new UPAttributeRequired(Set.of(ROLE_USER), Set.of())));
config.addOrReplaceAttribute(new UPAttribute(UserModel.FIRST_NAME, new UPAttributePermissions(Set.of(ROLE_ADMIN), Set.of(ROLE_USER)), new UPAttributeRequired(Set.of(ROLE_USER), Set.of())));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
Map<String, Object> attributes = new HashMap<>();
@ -1343,7 +1339,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testReadOnlyInternalAttributeValidation);
}
private static void testReadOnlyInternalAttributeValidation(KeycloakSession session) throws IOException {
private static void testReadOnlyInternalAttributeValidation(KeycloakSession session) {
RealmModel realm = session.getContext().getRealm();
UserModel maria = session.users().addUser(realm, "maria");
@ -1369,11 +1365,11 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testRequiredByClientScope);
}
private static void testRequiredByClientScope(KeycloakSession session) throws IOException {
private static void testRequiredByClientScope(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
config.addOrReplaceAttribute(new UPAttribute(ATT_ADDRESS, new UPAttributePermissions(Set.of(), Set.of(ROLE_USER)), new UPAttributeRequired(Set.of(), Set.of("client-a"))));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
Map<String, Object> attributes = new HashMap<>();
@ -1438,14 +1434,14 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testConfigurationInvalidScope);
}
private static void testConfigurationInvalidScope(KeycloakSession session) throws IOException {
private static void testConfigurationInvalidScope(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
config.addOrReplaceAttribute(new UPAttribute(ATT_ADDRESS, new UPAttributePermissions(Set.of(), Set.of(ROLE_USER)),
new UPAttributeRequired(Set.of(), Set.of("invalid")), new UPAttributeSelector(Set.of("invalid"))));
try {
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
Assert.fail("Expected to fail due to invalid client scope");
} catch (ComponentValidationException cve) {
//ignore
@ -1457,7 +1453,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testUsernameAndEmailPermissionNotSetIfEmpty);
}
private static void testUsernameAndEmailPermissionNotSetIfEmpty(KeycloakSession session) throws IOException {
private static void testUsernameAndEmailPermissionNotSetIfEmpty(KeycloakSession session){
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = provider.getConfiguration();
@ -1467,7 +1463,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
}
}
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
RealmModel realm = session.getContext().getRealm();
String username = "profiled-user-profile";
@ -1491,7 +1487,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testDoNotRemoveAttributes);
}
private static void testDoNotRemoveAttributes(KeycloakSession session) throws IOException {
private static void testDoNotRemoveAttributes(KeycloakSession session) {
Map<String, Object> attributes = new HashMap<>();
attributes.put(UserModel.USERNAME, org.keycloak.models.utils.KeycloakModelUtils.generateId());
@ -1507,7 +1503,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
config.addOrReplaceAttribute(new UPAttribute("foo", new UPAttributePermissions(Set.of(), Set.of(ROLE_USER, ROLE_ADMIN))));
config.addOrReplaceAttribute(new UPAttribute("email", new UPAttributePermissions(Set.of(), Set.of(ROLE_USER, ROLE_ADMIN))));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
UserProfile profile = provider.create(UserProfileContext.USER_API, attributes);
UserModel user = profile.create();
@ -1546,7 +1542,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
assertNull(userAttributes.getFirst("foo"));
config.addOrReplaceAttribute(new UPAttribute("test-attribute", new UPAttributePermissions(Set.of(), Set.of(ROLE_USER))));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
attributes.remove("test-attribute");
profile = provider.create(UserProfileContext.USER_API, attributes, user);
profile.update(true);
@ -1557,7 +1553,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
assertEquals("Test Value", userAttributes.getFirst("test-attribute"));
config.addOrReplaceAttribute(new UPAttribute("test-attribute", new UPAttributePermissions(Set.of(), Set.of(ROLE_USER, ROLE_ADMIN))));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
attributes.remove("test-attribute");
profile = provider.create(UserProfileContext.USER_API, attributes, user);
profile.update(true);
@ -1573,7 +1569,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testRemoveEmptyRootAttribute);
}
private static void testRemoveEmptyRootAttribute(KeycloakSession session) throws IOException {
private static void testRemoveEmptyRootAttribute(KeycloakSession session) {
Map<String, List<String>> attributes = new HashMap<>();
attributes.put(UserModel.USERNAME, List.of(org.keycloak.models.utils.KeycloakModelUtils.generateId()));
@ -1587,7 +1583,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
config.addOrReplaceAttribute(new UPAttribute(UserModel.FIRST_NAME, new UPAttributePermissions(Set.of(), Set.of(ROLE_ADMIN, ROLE_USER))));
config.addOrReplaceAttribute(new UPAttribute(UserModel.LAST_NAME, new UPAttributePermissions(Set.of(), Set.of(ROLE_ADMIN, ROLE_USER))));
config.addOrReplaceAttribute(new UPAttribute(UserModel.EMAIL, new UPAttributePermissions(Set.of(), Set.of(ROLE_ADMIN, ROLE_USER))));
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
UserProfile profile = provider.create(UserProfileContext.USER_API, attributes);
UserModel user = profile.create();
@ -1620,14 +1616,14 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testRemoveOptionalAttributesFromDefaultConfigIfNotSet);
}
private static void testRemoveOptionalAttributesFromDefaultConfigIfNotSet(KeycloakSession session) throws IOException {
private static void testRemoveOptionalAttributesFromDefaultConfigIfNotSet(KeycloakSession session) {
UPConfig config = parseDefaultConfig();
config.addOrReplaceAttribute(new UPAttribute("foo"));
config.removeAttribute(UserModel.FIRST_NAME);
config.removeAttribute(UserModel.LAST_NAME);
UserProfileProvider provider = getUserProfileProvider(session);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
Map<String, Object> attributes = new HashMap<>();
@ -1647,7 +1643,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
UPAttribute lastName = new UPAttribute();
lastName.setName(UserModel.LAST_NAME);
config.addOrReplaceAttribute(lastName);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes, user);
assertTrue(profile.getAttributes().contains(UserModel.FIRST_NAME));
assertTrue(profile.getAttributes().contains(UserModel.LAST_NAME));
@ -1658,11 +1654,11 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testUnmanagedPolicy);
}
private static void testUnmanagedPolicy(KeycloakSession session) throws IOException {
private static void testUnmanagedPolicy(KeycloakSession session) {
UPConfig config = parseDefaultConfig();
config.addOrReplaceAttribute(new UPAttribute("bar", new UPAttributePermissions(Set.of(), Set.of(ROLE_USER, ROLE_ADMIN))));
UserProfileProvider provider = getUserProfileProvider(session);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
// can't create attribute if policy is disabled
Map<String, Object> attributes = new HashMap<>();
@ -1678,27 +1674,27 @@ public class UserProfileTest extends AbstractUserProfileTest {
profile = provider.create(UserProfileContext.USER_API, attributes, user);
assertFalse(profile.getAttributes().contains("foo"));
config.setUnmanagedAttributePolicy(UnmanagedAttributePolicy.ADMIN_EDIT);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
profile = provider.create(UserProfileContext.USER_API, attributes, user);
assertTrue(profile.getAttributes().contains("foo"));
assertFalse(profile.getAttributes().isReadOnly("foo"));
// user already set with an unmanaged attribute, and it should be visible if policy is adminView but read-only
config.setUnmanagedAttributePolicy(UnmanagedAttributePolicy.ADMIN_VIEW);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
profile = provider.create(UserProfileContext.USER_API, attributes, user);
assertTrue(profile.getAttributes().contains("foo"));
assertTrue(profile.getAttributes().isReadOnly("foo"));
// user already set with an unmanaged attribute, but it is not available to user-facing contexts
config.setUnmanagedAttributePolicy(UnmanagedAttributePolicy.ADMIN_VIEW);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes, user);
assertFalse(profile.getAttributes().contains("foo"));
// user already set with an unmanaged attribute, and it is available to all contexts
config.setUnmanagedAttributePolicy(UnmanagedAttributePolicy.ENABLED);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes, user);
assertTrue(profile.getAttributes().contains("foo"));
assertFalse(profile.getAttributes().isReadOnly("foo"));
@ -1712,10 +1708,10 @@ public class UserProfileTest extends AbstractUserProfileTest {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testOptionalRootAttributesAsUnmanagedAttribute);
}
private static void testOptionalRootAttributesAsUnmanagedAttribute(KeycloakSession session) throws IOException {
private static void testOptionalRootAttributesAsUnmanagedAttribute(KeycloakSession session) {
UPConfig config = parseDefaultConfig();
UserProfileProvider provider = getUserProfileProvider(session);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
Map<String, String> rawAttributes = new HashMap<>();
rawAttributes.put(UserModel.USERNAME, org.keycloak.models.utils.KeycloakModelUtils.generateId() + "@keycloak.org");
rawAttributes.put(UserModel.EMAIL, org.keycloak.models.utils.KeycloakModelUtils.generateId() + "@keycloak.org");
@ -1732,7 +1728,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
config.removeAttribute(UserModel.FIRST_NAME);
config.removeAttribute(UserModel.LAST_NAME);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
profile = provider.create(UserProfileContext.USER_API, user);
Attributes attributes = profile.getAttributes();
assertNull(attributes.getFirst(UserModel.FIRST_NAME));
@ -1745,7 +1741,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
rawAttributes.put(UserModel.FIRST_NAME, "firstName");
rawAttributes.put(UserModel.LAST_NAME, "lastName");
config.setUnmanagedAttributePolicy(UnmanagedAttributePolicy.ADMIN_EDIT);
provider.setConfiguration(JsonSerialization.writeValueAsString(config));
provider.setConfiguration(config);
profile = provider.create(UserProfileContext.USER_API, user);
attributes = profile.getAttributes();
assertEquals(rawAttributes.get(UserModel.FIRST_NAME), attributes.getFirst(UserModel.FIRST_NAME));