8000 Allow setting a default user profile configuration by pedroigor · Pull Request #26911 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
import org.keycloak.url.DefaultHostnameProviderFactory;
import org.keycloak.url.FixedHostnameProviderFactory;
import org.keycloak.url.RequestHostnameProviderFactory;
import org.keycloak.userprofile.DeclarativeUserProfileProviderFactory;
import org.keycloak.userprofile.config.UPConfigUtils;
import org.keycloak.util.JsonSerialization;
import org.keycloak.vault.FilesKeystoreVaultProviderFactory;
import org.keycloak.vault.FilesPlainTextVaultProviderFactory;
Expand Down Expand Up @@ -272,7 +272,7 @@ void checkJdbcDriver(BuildProducer<JdbcDriverBuildItem> ignore) {
@BuildStep
@Produce(UserProfileBuildItem.class)
UserProfileBuildItem parseDefaultUserProfileConfig() {
final UPConfig defaultConfig = DeclarativeUserProfileProviderFactory.parseDefaultConfig();
UPConfig defaultConfig = UPConfigUtils.parseSystemDefaultConfig();
logger.debug("Parsing default configuration for the User Profile provider");
return new UserProfileBuildItem(defaultConfig);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,19 @@
package org.keycloak.userprofile;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.keycloak.Config;
import org.keycloak.Config.Scope;
import org.keycloak.authentication.requiredactions.TermsAndConditions;
import org.keycloak.common.Profile;
import org.keycloak.component.AmphibianProviderFactory;
Expand Down Expand Up @@ -91,7 +94,9 @@ public class DeclarativeUserProfileProviderFactory implements UserProfileProvide
private final Map<UserProfileContext, UserProfileMetadata> contextualMetadataRegistry = new HashMap<>();

public static void setDefaultConfig(UPConfig defaultConfig) {
PARSED_DEFAULT_RAW_CONFIG = defaultConfig;
if (PARSED_DEFAULT_RAW_CONFIG == null) {
PARSED_DEFAULT_RAW_CONFIG = defaultConfig;
}
}

private static boolean editUsernameCondition(AttributeContext c) {
Expand Down Expand Up @@ -206,15 +211,9 @@ public static Pattern getRegexPatternString(String[] builtinReadOnlyAttributes)
return null;
}

public static UPConfig parseDefaultConfig() {
return UPConfigUtils.parseDefaultConfig();
}

@Override
public void init(Config.Scope config) {
if (PARSED_DEFAULT_RAW_CONFIG == null) {
setDefaultConfig(parseDefaultConfig());
}
initDefaultConfiguration(config);

// make sure registry is clear in case of re-deploy
contextualMetadataRegistry.clear();
Expand Down Expand Up @@ -485,4 +484,21 @@ protected Map<UserProfileContext, UserProfileMetadata> getContextualMetadataRegi
return contextualMetadataRegistry;
}

private void initDefaultConfiguration(Scope config) {
// The user-defined configuration is always parsed during init and should be avoided as much as possible
// If no user-defined configuration is set, the system default configuration must have been set
// In Quarkus, the system default configuration is set at build time for optimization purposes
UPConfig defaultConfig = Optional.ofNullable(config.get("configFile"))
.map(Paths::get)
.map(UPConfigUtils::parseConfig)
.orElse(PARSED_DEFAULT_RAW_CONFIG);

if (defaultConfig == null) {
// as a fallback parse the system default config
defaultConfig = UPConfigUtils.parseSystemDefaultConfig();
}

PARSED_DEFAULT_RAW_CONFIG = null;
setDefaultConfig(defaultConfig);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
import static org.keycloak.common.util.ObjectUtil.isBlank;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -293,19 +295,39 @@ public static String capitalizeFirstLetter(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}

public static String readDefaultConfig() {
try (InputStream is = UPConfigUtils.class.getResourceAsStream(SYSTEM_DEFAULT_CONFIG_RESOURCE)) {
public static String readSystemDefaultConfig() {
try (InputStream is = getSystemDefaultConfig()) {
return StreamUtil.readString(is, Charset.defaultCharset());
} catch (IOException cause) {
throw new RuntimeException("Failed to load default user profile config file", cause);
}
}

public static UPConfig parseDefaultConfig() {
public static UPConfig parseSystemDefaultConfig() {
return parseConfig(getSystemDefaultConfig());
}

public static UPConfig parseConfig(Path configPath) {
if (configPath == null) {
throw new IllegalArgumentException("Null configPath");
}

try (InputStream is = new FileInputStream(configPath.toFile())) {
return parseConfig(is);
} catch (IOException ioe) {
throw new RuntimeException("Failed to reaad default user profile configuration: " + configPath, ioe);
}
}

private static UPConfig parseConfig(InputStream is) {
try {
return JsonSerialization.readValue(readDefaultConfig(), UPConfig.class);
return JsonSerialization.readValue(is, UPConfig.class);
} catch (IOException e) {
throw new RuntimeException("Failed to parse default user profile configuration", e);
throw new RuntimeException("Failed to parse default user profile configuration stream", e);
}
}

private static InputStream getSystemDefaultConfig() {
return UPConfigUtils.class.getResourceAsStream(SYSTEM_DEFAULT_CONFIG_RESOURCE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.keycloak.userprofile.config.UPConfigUtils.readDefaultConfig;
import static org.keycloak.userprofile.config.UPConfigUtils.readSystemDefaultConfig;

import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -53,12 +53,12 @@ public void configureTestRealm(RealmRepresentation testRealm) {

@Test
public void testDefaultConfigIfNoneSet() {
JsonTestUtils.assertJsonEquals(readDefaultConfig(), testRealm().users().userProfile().getConfiguration());
JsonTestUtils.assertJsonEquals(readSystemDefaultConfig(), testRealm().users().userProfile().getConfiguration());
}

@Test
public void testSetDefaultConfig() {
UPConfig config = UPConfigUtils.parseDefaultConfig().addOrReplaceAttribute(new UPAttribute("test"));
UPConfig config = UPConfigUtils.parseSystemDefaultConfig().addOrReplaceAttribute(new UPAttribute("test"));
UserProfileResource userProfile = testRealm().users().userProfile();
userProfile.update(config);
getCleanup().addCleanup(() -> testRealm().users().userProfile().update(null));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ protected static Optional<ComponentModel> getComponentModel(KeycloakSession sess
}

protected static void setDefaultConfiguration(KeycloakSession session) {
setConfiguration(session, UPConfigUtils.readDefaultConfig());
setConfiguration(session, UPConfigUtils.readSystemDefaultConfig());
}

protected static void setConfiguration(KeycloakSession session, String config) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@

import org.junit.Test;
import org.keycloak.component.ComponentModel;
import org.keycloak.component.ComponentValidationException;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.UserModel;
import org.keycloak.testsuite.arquillian.annotation.SetDefaultProvider;
Expand Down Expand Up @@ -54,7 +53,7 @@ private static void testCustomUserProfileProviderIsActive(KeycloakSession sessio
UserProfileProvider provider = getUserProfileProvider(session);
assertEquals(CustomUserProfileProvider.class.getName(), provider.getClass().getName());
assertTrue(provider instanceof CustomUserProfileProvider);
provider.setConfiguration(UPConfigUtils.parseDefaultConfig());
provider.setConfiguration(UPConfigUtils.parseSystemDefaultConfig());
Optional<ComponentModel> component = getComponentModel(session);
assertTrue(component.isPresent());
assertEquals("custom-user-profile", component.get().getProviderId());
Expand Down
Loading
0