From 3ec516d14cb48663f2dee613500cb9b860e5f3db Mon Sep 17 00:00:00 2001 From: Thomas Darimont Date: Mon, 4 Jan 2016 22:23:14 +0100 Subject: [PATCH 1/2] KEYCLOAK-2253 - Add support for ConfiguredProvider based UserFederationProviderFactory. UserFederationProvidersResource is now aware of ConfiguredProvider and allows sophisticated configuration of configuration properties via ProviderConfigProperty definitions. See DummyUserFederationProviderFactory. getConfigProperties() for example. Previously UserFederationProvidersResource did only support simple key-value pairs for expressing configurable options. Tested this by launching a standalone KeycloakServer and creating a new Dummy UserFederationProvider. The default values, labels and help messages are correctly displayed and the values are stored correctly. --- .../admin/resources/js/controllers/users.js | 10 +++ .../resources/partials/federated-generic.html | 3 + .../UserFederationProvidersResource.java | 76 ++++++++++++++++++- .../DummyUserFederationProviderFactory.java | 33 +++++++- 4 files changed, 116 insertions(+), 6 deletions(-) diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js index e72c8eca3d9..56c5b21421b 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js @@ -644,6 +644,16 @@ module.controller('GenericUserFederationCtrl', function($scope, $location, Notif instance.config.updateProfileFirstLogin = true; instance.config.allowKerberosAuthentication = true; } + + if (providerFactory.properties) { + + for (var i = 0; i < providerFactory.properties.length; i++) { + var configProperty = providerFactory.properties[i]; + var configValue = configProperty.type == "boolean" ? (configProperty.defaultValue === true ? 'true' : 'false') : configProperty.defaultValue; + instance.config[configProperty.name] = configValue; + } + } + } else { $scope.fullSyncEnabled = (instance.fullSyncPeriod && instance.fullSyncPeriod > 0); $scope.changedSyncEnabled = (instance.changedSyncPeriod && instance.changedSyncPeriod > 0); diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-generic.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-generic.html index b74a9abc08a..df34f728c5a 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-generic.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-generic.html @@ -37,6 +37,9 @@ + + +
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProvidersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProvidersResource.java index e0cbe730b44..1c390ad5ac1 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProvidersResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProvidersResource.java @@ -13,7 +13,10 @@ import org.keycloak.models.UserFederationProviderFactory; import org.keycloak.models.UserFederationProviderModel; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.models.utils.ModelToRepresentation; +import org.keycloak.provider.ConfiguredProvider; +import org.keycloak.provider.ProviderConfigProperty; import org.keycloak.provider.ProviderFactory; +import org.keycloak.representations.idm.ConfigPropertyRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation; import org.keycloak.representations.idm.UserFederationProviderRepresentation; @@ -32,6 +35,7 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -119,10 +123,22 @@ public class UserFederationProvidersResource { if (!factory.getId().equals(id)) { continue; } + + if (factory instanceof ConfiguredProvider) { + + UserFederationProviderFactoryDescription rep = new UserFederationProviderFactoryDescription(); + rep.setId(factory.getId()); + + ConfiguredProvider cp = (ConfiguredProvider) factory; + rep.setHelpText(cp.getHelpText()); + rep.setProperties(toConfigPropertyRepresentationList(cp.getConfigProperties())); + + return rep; + } + UserFederationProviderFactoryRepresentation rep = new UserFederationProviderFactoryRepresentation(); rep.setId(factory.getId()); - rep.setOptions(((UserFederationProviderFactory)factory).getConfigurationOptions()); - + rep.setOptions(((UserFederationProviderFactory) factory).getConfigurationOptions()); return rep; } @@ -191,4 +207,60 @@ public class UserFederationProvidersResource { return instanceResource; } + + private ConfigPropertyRepresentation toConfigPropertyRepresentation(ProviderConfigProperty prop) { + + ConfigPropertyRepresentation propRep = new ConfigPropertyRepresentation(); + propRep.setName(prop.getName()); + propRep.setLabel(prop.getLabel()); + propRep.setType(prop.getType()); + propRep.setDefaultValue(prop.getDefaultValue()); + propRep.setHelpText(prop.getHelpText()); + + return propRep; + } + + private List toConfigPropertyRepresentationList(List props) { + + List reps = new ArrayList<>(props.size()); + for(ProviderConfigProperty prop : props){ + reps.add(toConfigPropertyRepresentation(prop)); + } + + return reps; + } + + + public static class UserFederationProviderFactoryDescription extends UserFederationProviderFactoryRepresentation { + + protected String name; + + protected String helpText; + + protected List properties; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getHelpText() { + return helpText; + } + + public void setHelpText(String helpText) { + this.helpText = helpText; + } + + public List getProperties() { + return properties; + } + + public void setProperties(List properties) { + this.properties = properties; + } + } } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProviderFactory.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProviderFactory.java index 9825f5b19a6..82715c912ad 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProviderFactory.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProviderFactory.java @@ -8,17 +8,17 @@ import org.keycloak.models.UserFederationProvider; import org.keycloak.models.UserFederationProviderFactory; import org.keycloak.models.UserFederationProviderModel; import org.keycloak.models.UserFederationSyncResult; +import org.keycloak.provider.ConfiguredProvider; +import org.keycloak.provider.ProviderConfigProperty; -import java.util.Date; -import java.util.HashSet; -import java.util.Set; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; /** * @author Bill Burke * @version $Revision: 1 $ */ -public class DummyUserFederationProviderFactory implements UserFederationProviderFactory { +public class DummyUserFederationProviderFactory implements UserFederationProviderFactory, ConfiguredProvider { private static final Logger logger = Logger.getLogger(DummyUserFederationProviderFactory.class); public static final String PROVIDER_NAME = "dummy"; @@ -84,4 +84,29 @@ public class DummyUserFederationProviderFactory implements UserFederationProvide public int getChangedSyncCounter() { return changedSyncCounter.get(); } + + @Override + public String getHelpText() { + return "Dummy User Federation Provider Help Text"; + } + + @Override + public List getConfigProperties() { + + ProviderConfigProperty prop1 = new ProviderConfigProperty(); + prop1.setName("prop1"); + prop1.setLabel("Prop1"); + prop1.setDefaultValue("prop1Default"); + prop1.setHelpText("Prop1 HelpText"); + prop1.setType(ProviderConfigProperty.STRING_TYPE); + + ProviderConfigProperty prop2 = new ProviderConfigProperty(); + prop2.setName("prop2"); + prop2.setLabel("Prop2"); + prop2.setDefaultValue(true); + prop2.setHelpText("Prop2 HelpText"); + prop2.setType(ProviderConfigProperty.BOOLEAN_TYPE); + + return Arrays.asList(prop1, prop2); + } } From edcc39d906407b4f894d878c6470b36bf5cafe1d Mon Sep 17 00:00:00 2001 From: Thomas Darimont Date: Mon, 4 Jan 2016 23:07:08 +0100 Subject: [PATCH 2/2] KEYCLOAK-2253 - Use string representation for boolean properties in GenericUserFederationCtrl. Adapted due to code review. --- .../theme/base/admin/resources/js/controllers/users.js | 3 +-- .../keycloak/testsuite/DummyUserFederationProviderFactory.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js index 56c5b21421b..2f3dc48a417 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js @@ -649,8 +649,7 @@ module.controller('GenericUserFederationCtrl', function($scope, $location, Notif for (var i = 0; i < providerFactory.properties.length; i++) { var configProperty = providerFactory.properties[i]; - var configValue = configProperty.type == "boolean" ? (configProperty.defaultValue === true ? 'true' : 'false') : configProperty.defaultValue; - instance.config[configProperty.name] = configValue; + instance.config[configProperty.name] = configProperty.defaultValue; } } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProviderFactory.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProviderFactory.java index 82715c912ad..fc8b8d6227c 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProviderFactory.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/DummyUserFederationProviderFactory.java @@ -103,7 +103,7 @@ public class DummyUserFederationProviderFactory implements UserFederationProvide ProviderConfigProperty prop2 = new ProviderConfigProperty(); prop2.setName("prop2"); prop2.setLabel("Prop2"); - prop2.setDefaultValue(true); + prop2.setDefaultValue("true"); prop2.setHelpText("Prop2 HelpText"); prop2.setType(ProviderConfigProperty.BOOLEAN_TYPE);