diff --git a/core/src/main/java/org/keycloak/representations/idm/UserFederationProviderFactoryRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserFederationProviderFactoryRepresentation.java index 1a6fec856e..bbf5741e88 100755 --- a/core/src/main/java/org/keycloak/representations/idm/UserFederationProviderFactoryRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/UserFederationProviderFactoryRepresentation.java @@ -17,6 +17,7 @@ package org.keycloak.representations.idm; +import java.util.List; import java.util.Set; /** @@ -25,7 +26,9 @@ import java.util.Set; public class UserFederationProviderFactoryRepresentation { private String id; - private Set options; + private Set options; // TODO:Remove as configurable providers are more flexible? + private String helpText; // Used for configurable providers + private List properties; // Used for configurable providers public String getId() { return id; @@ -43,6 +46,22 @@ public class UserFederationProviderFactoryRepresentation { this.options = options; } + 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; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/core/src/main/java/org/keycloak/representations/idm/UserFederationSyncResultRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserFederationSyncResultRepresentation.java new file mode 100644 index 0000000000..08509efd50 --- /dev/null +++ b/core/src/main/java/org/keycloak/representations/idm/UserFederationSyncResultRepresentation.java @@ -0,0 +1,82 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.representations.idm; + +/** + * @author Marek Posolda + */ +public class UserFederationSyncResultRepresentation { + + private boolean ignored; + + private int added; + private int updated; + private int removed; + private int failed; + + private String status; + + public boolean isIgnored() { + return ignored; + } + + public void setIgnored(boolean ignored) { + this.ignored = ignored; + } + + public int getAdded() { + return added; + } + + public void setAdded(int added) { + this.added = added; + } + + public int getUpdated() { + return updated; + } + + public void setUpdated(int updated) { + this.updated = updated; + } + + public int getRemoved() { + return removed; + } + + public void setRemoved(int removed) { + this.removed = removed; + } + + public int getFailed() { + return failed; + } + + public void setFailed(int failed) { + this.failed = failed; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + +} diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/AuthenticationManagementResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/AuthenticationManagementResource.java index 197aeb69d9..d5de7be076 100644 --- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/AuthenticationManagementResource.java +++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/AuthenticationManagementResource.java @@ -100,7 +100,7 @@ public interface AuthenticationManagementResource { @Path("/flows/{flowAlias}/executions") @GET @Produces(MediaType.APPLICATION_JSON) - Response getExecutions(@PathParam("flowAlias") String flowAlias); + List getExecutions(@PathParam("flowAlias") String flowAlias); @Path("/flows/{flowAlias}/executions") @PUT diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java index 6b4f368c7f..34ca64a436 100644 --- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java +++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java @@ -160,4 +160,14 @@ public interface RealmResource { @Path("attack-detection") AttackDetectionResource attackDetection(); + @Path("user-federation") + UserFederationProvidersResource userFederation(); + + @Path("testLDAPConnection") + @GET + @NoCache + Response testLDAPConnection(@QueryParam("action") String action, @QueryParam("connectionUrl") String connectionUrl, + @QueryParam("bindDn") String bindDn, @QueryParam("bindCredential") String bindCredential, + @QueryParam("useTruststoreSpi") String useTruststoreSpi); + } diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UserFederationProviderResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UserFederationProviderResource.java new file mode 100644 index 0000000000..5e1a99fe41 --- /dev/null +++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UserFederationProviderResource.java @@ -0,0 +1,103 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.admin.client.resource; + +import java.util.List; +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.keycloak.representations.idm.UserFederationMapperRepresentation; +import org.keycloak.representations.idm.UserFederationMapperTypeRepresentation; +import org.keycloak.representations.idm.UserFederationProviderRepresentation; +import org.keycloak.representations.idm.UserFederationSyncResultRepresentation; + +/** + * @author Marek Posolda + */ +public interface UserFederationProviderResource { + + @PUT + @Consumes(MediaType.APPLICATION_JSON) + void update(UserFederationProviderRepresentation rep); + + + @GET + @Produces(MediaType.APPLICATION_JSON) + UserFederationProviderRepresentation toRepresentation(); + + + @DELETE + void remove(); + + + @POST + @Path("sync") + @Produces(MediaType.APPLICATION_JSON) + UserFederationSyncResultRepresentation syncUsers(@QueryParam("action") String action); + + + @GET + @Path("mapper-types") + Map getMapperTypes(); + + + @GET + @Path("mappers") + @Produces(MediaType.APPLICATION_JSON) + List getMappers(); + + + @POST + @Path("mappers") + @Consumes(MediaType.APPLICATION_JSON) + Response addMapper(UserFederationMapperRepresentation mapper); + + + @GET + @Path("mappers/{id}") + @Produces(MediaType.APPLICATION_JSON) + UserFederationMapperRepresentation getMapperById(@PathParam("id") String id); + + + @PUT + @Path("mappers/{id}") + @Consumes(MediaType.APPLICATION_JSON) + void updateMapper(@PathParam("id") String id, UserFederationMapperRepresentation rep); + + + @DELETE + @Path("mappers/{id}") + void removeMapper(@PathParam("id") String id); + + + @POST + @Path("mappers/{id}/sync") + @Produces(MediaType.APPLICATION_JSON) + UserFederationSyncResultRepresentation syncMapperData(@PathParam("id") String mapperId, @QueryParam("direction") String direction); +} diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UserFederationProvidersResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UserFederationProvidersResource.java new file mode 100644 index 0000000000..e56ea3c09c --- /dev/null +++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UserFederationProvidersResource.java @@ -0,0 +1,66 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.admin.client.resource; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation; +import org.keycloak.representations.idm.UserFederationProviderRepresentation; + +/** + * @author Marek Posolda + */ +public interface UserFederationProvidersResource { + + @GET + @Path("providers") + @Produces(MediaType.APPLICATION_JSON) + List getProviderFactories(); + + + @GET + @Path("providers/{id}") + @Produces(MediaType.APPLICATION_JSON) + UserFederationProviderFactoryRepresentation getProviderFactory(@PathParam("id") String id); + + + @POST + @Path("instances") + @Consumes(MediaType.APPLICATION_JSON) + Response create(UserFederationProviderRepresentation rep); + + + @GET + @Path("instances") + @Produces(MediaType.APPLICATION_JSON) + List getProviderInstances(); + + + @Path("instances/{id}") + UserFederationProviderResource get(@PathParam("id") String id); + +} diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java index ecfc307331..2a56aa0b9c 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java @@ -158,6 +158,7 @@ public class UserFederationProviderResource { @POST @Path("sync") @NoCache + @Produces(MediaType.APPLICATION_JSON) public UserFederationSyncResult syncUsers(@QueryParam("action") String action) { auth.requireManage(); @@ -352,6 +353,7 @@ public class UserFederationProviderResource { @POST @Path("mappers/{id}/sync") @NoCache + @Produces(MediaType.APPLICATION_JSON) public UserFederationSyncResult syncMapperData(@PathParam("id") String mapperId, @QueryParam("direction") String direction) { auth.requireManage(); diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/DummyConfigurableUserFederationProviderFactory.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/DummyConfigurableUserFederationProviderFactory.java new file mode 100644 index 0000000000..ec63c89aff --- /dev/null +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/DummyConfigurableUserFederationProviderFactory.java @@ -0,0 +1,62 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.federation; + +import java.util.Arrays; +import java.util.List; + +import org.keycloak.provider.ConfiguredProvider; +import org.keycloak.provider.ProviderConfigProperty; + +/** + * @author Marek Posolda + */ +public class DummyConfigurableUserFederationProviderFactory extends DummyUserFederationProviderFactory implements ConfiguredProvider { + + public static final String PROVIDER_NAME = "dummy-configurable"; + + @Override + public String getId() { + return PROVIDER_NAME; + } + + @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); + } +} diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/DummyUserFederationProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/DummyUserFederationProvider.java new file mode 100644 index 0000000000..0ba4816fa8 --- /dev/null +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/DummyUserFederationProvider.java @@ -0,0 +1,149 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.federation; + +import org.keycloak.models.CredentialValidationOutput; +import org.keycloak.models.GroupModel; +import org.keycloak.models.RealmModel; +import org.keycloak.models.RoleModel; +import org.keycloak.models.UserCredentialModel; +import org.keycloak.models.UserFederationProvider; +import org.keycloak.models.UserModel; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class DummyUserFederationProvider implements UserFederationProvider { + + private final Map users; + + public DummyUserFederationProvider(Map users) { + this.users = users; + } + + @Override + public UserModel validateAndProxy(RealmModel realm, UserModel local) { + return local; + } + + @Override + public boolean synchronizeRegistrations() { + return true; + } + + @Override + public UserModel register(RealmModel realm, UserModel user) { + users.put(user.getUsername(), user); + return user; + } + + @Override + public boolean removeUser(RealmModel realm, UserModel user) { + return users.remove(user.getUsername()) != null; + } + + @Override + public UserModel getUserByUsername(RealmModel realm, String username) { + return users.get(username); + } + + @Override + public UserModel getUserByEmail(RealmModel realm, String email) { + return null; + } + + @Override + public List searchByAttributes(Map attributes, RealmModel realm, int maxResults) { + return Collections.emptyList(); + } + + @Override + public List getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) { + return Collections.emptyList(); + } + + @Override + public void preRemove(RealmModel realm) { + + } + + @Override + public void preRemove(RealmModel realm, RoleModel role) { + + } + + @Override + public void preRemove(RealmModel realm, GroupModel group) { + + } + + @Override + public boolean isValid(RealmModel realm, UserModel local) { + String username = local.getUsername(); + return users.containsKey(username); + } + + @Override + public Set getSupportedCredentialTypes(UserModel user) { + // Just user "test-user" is able to validate password with this federationProvider + if (user.getUsername().equals("test-user")) { + return Collections.singleton(UserCredentialModel.PASSWORD); + } else { + return Collections.emptySet(); + } + } + + @Override + public Set getSupportedCredentialTypes() { + return Collections.singleton(UserCredentialModel.PASSWORD); + } + + @Override + public boolean validCredentials(RealmModel realm, UserModel user, List input) { + if (user.getUsername().equals("test-user") && input.size() == 1) { + UserCredentialModel password = input.get(0); + if (password.getType().equals(UserCredentialModel.PASSWORD)) { + return "secret".equals(password.getValue()); + } + } + return false; + } + + @Override + public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) { + return validCredentials(realm, user, Arrays.asList(input)); + } + + @Override + public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) { + return CredentialValidationOutput.failed(); + } + + @Override + public void close() { + + } +} + diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/DummyUserFederationProviderFactory.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/DummyUserFederationProviderFactory.java new file mode 100644 index 0000000000..8bb9e11c2f --- /dev/null +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/DummyUserFederationProviderFactory.java @@ -0,0 +1,108 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.federation; + +import org.jboss.logging.Logger; +import org.keycloak.Config; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.models.UserFederationProvider; +import org.keycloak.models.UserFederationProviderFactory; +import org.keycloak.models.UserFederationProviderModel; +import org.keycloak.models.UserFederationSyncResult; +import org.keycloak.models.UserModel; +import org.keycloak.provider.ConfiguredProvider; +import org.keycloak.provider.ProviderConfigProperty; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class DummyUserFederationProviderFactory implements UserFederationProviderFactory { + + private static final Logger logger = Logger.getLogger(DummyUserFederationProviderFactory.class); + public static final String PROVIDER_NAME = "dummy"; + + private AtomicInteger fullSyncCounter = new AtomicInteger(); + private AtomicInteger changedSyncCounter = new AtomicInteger(); + + private Map users = new HashMap(); + + @Override + public UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) { + return new DummyUserFederationProvider(users); + } + + @Override + public Set getConfigurationOptions() { + Set list = new HashSet(); + list.add("important.config"); + return list; + } + + @Override + public UserFederationProvider create(KeycloakSession session) { + return new DummyUserFederationProvider(users); + } + + @Override + public void init(Config.Scope config) { + + } + + @Override + public void postInit(KeycloakSessionFactory factory) { + + } + + @Override + public void close() { + + } + + @Override + public String getId() { + return PROVIDER_NAME; + } + + @Override + public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model) { + logger.info("syncAllUsers invoked"); + fullSyncCounter.incrementAndGet(); + return UserFederationSyncResult.empty(); + } + + @Override + public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync) { + logger.info("syncChangedUsers invoked"); + changedSyncCounter.incrementAndGet(); + return UserFederationSyncResult.empty(); + } + + public int getFullSyncCounter() { + return fullSyncCounter.get(); + } + + public int getChangedSyncCounter() { + return changedSyncCounter.get(); + } + +} diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/resources/META-INF/services/org.keycloak.models.UserFederationProviderFactory b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/resources/META-INF/services/org.keycloak.models.UserFederationProviderFactory new file mode 100644 index 0000000000..015d4cde5e --- /dev/null +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/resources/META-INF/services/org.keycloak.models.UserFederationProviderFactory @@ -0,0 +1,36 @@ +# +# Copyright 2016 Red Hat, Inc. and/or its affiliates +# and other contributors as indicated by the @author tags. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# +# Copyright 2016 Red Hat, Inc. and/or its affiliates +# and other contributors as indicated by the @author tags. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +org.keycloak.testsuite.federation.DummyUserFederationProviderFactory +org.keycloak.testsuite.federation.DummyConfigurableUserFederationProviderFactory \ No newline at end of file diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/Assert.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/Assert.java index 2a82d48a62..267c832929 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/Assert.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/Assert.java @@ -22,16 +22,13 @@ import org.keycloak.representations.idm.IdentityProviderRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation; import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; import java.util.LinkedList; import java.util.List; import java.util.Set; -import static org.junit.Assert.assertArrayEquals; - /** * @author Stian Thorgersen */ @@ -49,16 +46,6 @@ public class Assert extends org.junit.Assert { assertArrayEquals("Expected: " + Arrays.toString(expected) + ", was: " + Arrays.toString(actualNames), expected, actualNames); } - private static List sort(List list) { - Collections.sort(list, new Comparator() { - @Override - public int compare(Object o1, Object o2) { - return name(o1).compareTo(name(o2)); - } - }); - return list; - } - private static String[] names(List list) { String[] names = new String[list.size()]; for (int i = 0; i < list.size(); i++) { @@ -69,7 +56,9 @@ public class Assert extends org.junit.Assert { } private static String name(Object o1) { - if (o1 instanceof RealmRepresentation) { + if (o1 instanceof String) { + return (String) o1; + } else if (o1 instanceof RealmRepresentation) { return ((RealmRepresentation) o1).getRealm(); } else if (o1 instanceof ClientRepresentation) { return ((ClientRepresentation) o1).getClientId(); @@ -79,7 +68,10 @@ public class Assert extends org.junit.Assert { return ((RoleRepresentation) o1).getName(); } else if (o1 instanceof UserRepresentation) { return ((UserRepresentation) o1).getUsername(); + } else if (o1 instanceof UserFederationProviderFactoryRepresentation) { + return ((UserFederationProviderFactoryRepresentation) o1).getId(); } + throw new IllegalArgumentException(); } } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/custom/AbstractCustomAccountManagementTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/custom/AbstractCustomAccountManagementTest.java index 36ff0f69bd..c8f6d56638 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/custom/AbstractCustomAccountManagementTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/custom/AbstractCustomAccountManagementTest.java @@ -56,14 +56,8 @@ public abstract class AbstractCustomAccountManagementTest extends AbstractAccoun } protected AuthenticationExecutionInfoRepresentation getExecution(String flowAlias, String provider) { - Response response = authMgmtResource.getExecutions(flowAlias); - - List executionReps = response.readEntity( - new GenericType>() { - }); - - response.close(); - + List executionReps = authMgmtResource.getExecutions(flowAlias); + for (AuthenticationExecutionInfoRepresentation exec : executionReps) { if (provider.equals(exec.getProviderId())) { return exec; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserFederationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserFederationTest.java new file mode 100644 index 0000000000..0cd3508692 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserFederationTest.java @@ -0,0 +1,357 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.admin; + +import java.util.LinkedList; +import java.util.List; + +import javax.ws.rs.BadRequestException; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; + +import org.junit.Test; +import org.keycloak.admin.client.resource.UserFederationProvidersResource; +import org.keycloak.common.constants.KerberosConstants; +import org.keycloak.models.AuthenticationExecutionModel; +import org.keycloak.models.LDAPConstants; +import org.keycloak.provider.ProviderConfigProperty; +import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation; +import org.keycloak.representations.idm.ConfigPropertyRepresentation; +import org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation; +import org.keycloak.representations.idm.UserFederationProviderRepresentation; +import org.keycloak.representations.idm.UserFederationSyncResultRepresentation; +import org.keycloak.testsuite.Assert; +import org.keycloak.testsuite.admin.authentication.AbstractAuthenticationTest; +import org.keycloak.testsuite.util.UserFederationProviderBuilder; + +/** + * @author Marek Posolda + */ +public class UserFederationTest extends AbstractAdminTest { + + @Test + public void testProviderFactories() { + List providerFactories = userFederation().getProviderFactories(); + Assert.assertNames(providerFactories, "ldap", "kerberos", "dummy", "dummy-configurable"); + + // Builtin provider without properties + UserFederationProviderFactoryRepresentation ldapProvider = userFederation().getProviderFactory("ldap"); + Assert.assertEquals(ldapProvider.getId(), "ldap"); + Assert.assertEquals(0, ldapProvider.getOptions().size()); + + // Configurable through the "old-way" options + UserFederationProviderFactoryRepresentation dummyProvider = userFederation().getProviderFactory("dummy"); + Assert.assertEquals(dummyProvider.getId(), "dummy"); + Assert.assertNames(new LinkedList<>(dummyProvider.getOptions()), "important.config"); + + // Configurable through the "new-way" ConfiguredProvider + UserFederationProviderFactoryRepresentation dummyConfiguredProvider = userFederation().getProviderFactory("dummy-configurable"); + Assert.assertEquals(dummyConfiguredProvider.getId(), "dummy-configurable"); + Assert.assertTrue(dummyConfiguredProvider.getOptions() == null || dummyConfiguredProvider.getOptions().isEmpty()); + Assert.assertEquals("Dummy User Federation Provider Help Text", dummyConfiguredProvider.getHelpText()); + Assert.assertEquals(2, dummyConfiguredProvider.getProperties().size()); + assertProviderConfigProperty(dummyConfiguredProvider.getProperties().get(0), "prop1", "Prop1", "prop1Default", "Prop1 HelpText", ProviderConfigProperty.STRING_TYPE); + assertProviderConfigProperty(dummyConfiguredProvider.getProperties().get(1), "prop2", "Prop2", "true", "Prop2 HelpText", ProviderConfigProperty.BOOLEAN_TYPE); + + try { + userFederation().getProviderFactory("not-existent"); + Assert.fail("Not expected to find not-existent provider"); + } catch (NotFoundException nfe) { + nfe.getResponse().close(); + } + } + + private UserFederationProvidersResource userFederation() { + return realm.userFederation(); + } + + private void assertProviderConfigProperty(ConfigPropertyRepresentation property, String name, String label, String defaultValue, String helpText, String type) { + Assert.assertEquals(name, property.getName()); + Assert.assertEquals(label, property.getLabel()); + Assert.assertEquals(defaultValue, property.getDefaultValue()); + Assert.assertEquals(helpText, property.getHelpText()); + Assert.assertEquals(type, property.getType()); + } + + + @Test + public void testCreateProvider() { + // create provider without configuration and displayName + UserFederationProviderRepresentation dummyRep1 = UserFederationProviderBuilder.create() + .providerName("dummy") + .displayName("") + .priority(2) + .fullSyncPeriod(1000) + .changedSyncPeriod(500) + .lastSync(123) + .build(); + + String id1 = createUserFederationProvider(dummyRep1); + + // create provider with configuration and displayName + UserFederationProviderRepresentation dummyRep2 = UserFederationProviderBuilder.create() + .providerName("dummy") + .displayName("dn1") + .priority(1) + .configProperty("prop1", "prop1Val") + .configProperty("prop2", "true") + .build(); + String id2 = createUserFederationProvider(dummyRep2); + + // Assert provider instances available + assertFederationProvider(userFederation().get(id1).toRepresentation(), id1, id1, "dummy", 2, 1000, 500, 123); + assertFederationProvider(userFederation().get(id2).toRepresentation(), id2, "dn1", "dummy", 1, -1, -1, -1, "prop1", "prop1Val", "prop2", "true"); + + // Assert sorted + List providerInstances = userFederation().getProviderInstances(); + Assert.assertEquals(providerInstances.size(), 2); + assertFederationProvider(providerInstances.get(0), id2, "dn1", "dummy", 1, -1, -1, -1, "prop1", "prop1Val", "prop2", "true"); + assertFederationProvider(providerInstances.get(1), id1, id1, "dummy", 2, 1000, 500, 123); + + // Remove providers + userFederation().get(id1).remove(); + userFederation().get(id2).remove(); + } + + + @Test + public void testValidateAndCreateLdapProvider() { + // Invalid filter + UserFederationProviderRepresentation ldapRep = UserFederationProviderBuilder.create() + .displayName("ldap1") + .providerName("ldap") + .priority(1) + .configProperty(LDAPConstants.CUSTOM_USER_SEARCH_FILTER, "dc=something") + .build(); + Response resp = userFederation().create(ldapRep); + Assert.assertEquals(400, resp.getStatus()); + resp.close(); + + // Invalid filter + ldapRep.getConfig().put(LDAPConstants.CUSTOM_USER_SEARCH_FILTER, "(dc=something"); + resp = userFederation().create(ldapRep); + Assert.assertEquals(400, resp.getStatus()); + resp.close(); + + // Invalid filter + ldapRep.getConfig().put(LDAPConstants.CUSTOM_USER_SEARCH_FILTER, "dc=something)"); + resp = userFederation().create(ldapRep); + Assert.assertEquals(400, resp.getStatus()); + resp.close(); + + // Assert nothing created so far + Assert.assertTrue(userFederation().getProviderInstances().isEmpty()); + + + // Valid filter. Creation success + ldapRep.getConfig().put(LDAPConstants.CUSTOM_USER_SEARCH_FILTER, "(dc=something)"); + String id1 = createUserFederationProvider(ldapRep); + + // Missing filter is ok too. Creation success + UserFederationProviderRepresentation ldapRep2 = UserFederationProviderBuilder.create() + .displayName("ldap2") + .providerName("ldap") + .priority(2) + .configProperty(LDAPConstants.BIND_DN, "cn=manager") + .configProperty(LDAPConstants.BIND_CREDENTIAL, "password") + .build(); + String id2 = createUserFederationProvider(ldapRep2); + + // Assert both providers created + List providerInstances = userFederation().getProviderInstances(); + Assert.assertEquals(providerInstances.size(), 2); + assertFederationProvider(providerInstances.get(0), id1, "ldap1", "ldap", 1, -1, -1, -1, LDAPConstants.CUSTOM_USER_SEARCH_FILTER, "(dc=something)"); + assertFederationProvider(providerInstances.get(1), id2, "ldap2", "ldap", 2, -1, -1, -1, LDAPConstants.BIND_DN, "cn=manager", LDAPConstants.BIND_CREDENTIAL, "password"); + + // Cleanup + userFederation().get(id1).remove(); + userFederation().get(id2).remove(); + } + + + @Test + public void testUpdateProvider() { + UserFederationProviderRepresentation ldapRep = UserFederationProviderBuilder.create() + .providerName("ldap") + .priority(2) + .configProperty(LDAPConstants.BIND_DN, "cn=manager") + .configProperty(LDAPConstants.BIND_CREDENTIAL, "password") + .build(); + String id = createUserFederationProvider(ldapRep); + assertFederationProvider(userFederation().get(id).toRepresentation(), id, id, "ldap", 2, -1, -1, -1, LDAPConstants.BIND_DN, "cn=manager", LDAPConstants.BIND_CREDENTIAL, "password"); + + // Assert update with invalid filter should fail + ldapRep = userFederation().get(id).toRepresentation(); + ldapRep.setDisplayName(""); + ldapRep.getConfig().put(LDAPConstants.CUSTOM_USER_SEARCH_FILTER, "(dc=something2"); + ldapRep.getConfig().put(LDAPConstants.BIND_DN, "cn=manager-updated"); + try { + userFederation().get(id).update(ldapRep); + Assert.fail("Not expected to successfull update"); + } catch (BadRequestException bre) { + bre.getResponse().close(); + } + + // Assert nothing was updated + assertFederationProvider(userFederation().get(id).toRepresentation(), id, id, "ldap", 2, -1, -1, -1, LDAPConstants.BIND_DN, "cn=manager", LDAPConstants.BIND_CREDENTIAL, "password"); + + // Change filter to be valid + ldapRep.getConfig().put(LDAPConstants.CUSTOM_USER_SEARCH_FILTER, "(dc=something2)"); + userFederation().get(id).update(ldapRep); + + // Assert updated successfully + ldapRep = userFederation().get(id).toRepresentation(); + assertFederationProvider(ldapRep, id, id, "ldap", 2, -1, -1, -1, LDAPConstants.BIND_DN, "cn=manager-updated", LDAPConstants.BIND_CREDENTIAL, "password", + LDAPConstants.CUSTOM_USER_SEARCH_FILTER, "(dc=something2)"); + + // Assert update displayName + ldapRep.setDisplayName("ldap2"); + userFederation().get(id).update(ldapRep); + assertFederationProvider(userFederation().get(id).toRepresentation(), id, "ldap2", "ldap", 2, -1, -1, -1, LDAPConstants.BIND_DN, "cn=manager-updated", LDAPConstants.BIND_CREDENTIAL, "password", + LDAPConstants.CUSTOM_USER_SEARCH_FILTER, "(dc=something2)"); + + + + // Cleanup + userFederation().get(id).remove(); + } + + + @Test + public void testKerberosAuthenticatorEnabledAutomatically() { + // Assert kerberos authenticator DISABLED + AuthenticationExecutionInfoRepresentation kerberosExecution = findKerberosExecution(); + Assert.assertEquals(kerberosExecution.getRequirement(), AuthenticationExecutionModel.Requirement.DISABLED.toString()); + + // create LDAP provider with kerberos + UserFederationProviderRepresentation ldapRep = UserFederationProviderBuilder.create() + .displayName("ldap2") + .providerName("ldap") + .priority(2) + .configProperty(KerberosConstants.ALLOW_KERBEROS_AUTHENTICATION, "true") + .build(); + String id = createUserFederationProvider(ldapRep); + + // Assert kerberos authenticator ALTERNATIVE + kerberosExecution = findKerberosExecution(); + Assert.assertEquals(kerberosExecution.getRequirement(), AuthenticationExecutionModel.Requirement.ALTERNATIVE.toString()); + + // Switch kerberos authenticator to DISABLED + kerberosExecution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED.toString()); + realm.flows().updateExecutions("browser", kerberosExecution); + + // update LDAP provider with kerberos + ldapRep = userFederation().get(id).toRepresentation(); + userFederation().get(id).update(ldapRep); + + // Assert kerberos authenticator ALTERNATIVE + kerberosExecution = findKerberosExecution(); + Assert.assertEquals(kerberosExecution.getRequirement(), AuthenticationExecutionModel.Requirement.ALTERNATIVE.toString()); + + // Cleanup + kerberosExecution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED.toString()); + realm.flows().updateExecutions("browser", kerberosExecution); + userFederation().get(id).remove(); + } + + + @Test (expected = NotFoundException.class) + public void testLookupNotExistentProvider() { + userFederation().get("not-existent").toRepresentation(); + } + + + @Test + public void testSyncFederationProvider() { + // create provider + UserFederationProviderRepresentation dummyRep1 = UserFederationProviderBuilder.create() + .providerName("dummy") + .build(); + String id1 = createUserFederationProvider(dummyRep1); + + + // Sync with unknown action shouldn't pass + try { + userFederation().get(id1).syncUsers("unknown"); + Assert.fail("Not expected to sync with unknown action"); + } catch (NotFoundException nfe) { + nfe.getResponse().close(); + } + + // Assert sync didn't happen + Assert.assertEquals(-1, userFederation().get(id1).toRepresentation().getLastSync()); + + // Sync and assert it happened + UserFederationSyncResultRepresentation syncResult = userFederation().get(id1).syncUsers("triggerFullSync"); + Assert.assertEquals("0 imported users, 0 updated users", syncResult.getStatus()); + int fullSyncTime = userFederation().get(id1).toRepresentation().getLastSync(); + Assert.assertTrue(fullSyncTime > 0); + + // Changed sync + setTimeOffset(50); + syncResult = userFederation().get(id1).syncUsers("triggerChangedUsersSync"); + Assert.assertEquals("0 imported users, 0 updated users", syncResult.getStatus()); + int changedSyncTime = userFederation().get(id1).toRepresentation().getLastSync(); + Assert.assertTrue(fullSyncTime + 50 <= changedSyncTime); + + // Cleanup + resetTimeOffset(); + userFederation().get(id1).remove(); + } + + + private String createUserFederationProvider(UserFederationProviderRepresentation rep) { + Response resp = userFederation().create(rep); + Assert.assertEquals(201, resp.getStatus()); + resp.close(); + return ApiUtil.getCreatedId(resp); + } + + private void assertFederationProvider(UserFederationProviderRepresentation rep, String id, String displayName, String providerName, + int priority, int fullSyncPeriod, int changeSyncPeriod, int lastSync, + String... config) { + Assert.assertEquals(id, rep.getId()); + Assert.assertEquals(displayName, rep.getDisplayName()); + Assert.assertEquals(providerName, rep.getProviderName()); + Assert.assertEquals(priority, rep.getPriority()); + Assert.assertEquals(fullSyncPeriod, rep.getFullSyncPeriod()); + Assert.assertEquals(changeSyncPeriod, rep.getChangedSyncPeriod()); + Assert.assertEquals(lastSync, rep.getLastSync()); + if (config == null) { + config = new String[] {}; + } + + Assert.assertEquals(rep.getConfig().size() * 2, config.length); + for (int i=0 ; i executionReps = realm.flows().getExecutions("browser"); + kerberosExecution = AbstractAuthenticationTest.findExecutionByProvider("auth-spnego", executionReps); + + Assert.assertNotNull(kerberosExecution); + return kerberosExecution; + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java index fb7e966156..50b11ac168 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java @@ -63,7 +63,7 @@ public abstract class AbstractAuthenticationTest extends AbstractKeycloakTest { } - AuthenticationExecutionInfoRepresentation findExecutionByProvider(String provider, List executions) { + public static AuthenticationExecutionInfoRepresentation findExecutionByProvider(String provider, List executions) { for (AuthenticationExecutionInfoRepresentation exec : executions) { if (provider.equals(exec.getProviderId())) { return exec; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java index afe702f033..7852e22b5f 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java @@ -68,20 +68,12 @@ public class ExecutionTest extends AbstractAuthenticationTest { authMgmtResource.addExecution("Copy of browser", params); // check execution was added - response = authMgmtResource.getExecutions("Copy of browser"); - AuthenticationExecutionInfoRepresentation exec; - AuthenticationExecutionInfoRepresentation authCookieExec; - try { - List executionReps = response.readEntity(new GenericType>() { - }); - exec = findExecutionByProvider("idp-review-profile", executionReps); - Assert.assertNotNull("idp-review-profile added", exec); + List executionReps = authMgmtResource.getExecutions("Copy of browser"); + AuthenticationExecutionInfoRepresentation exec = findExecutionByProvider("idp-review-profile", executionReps); + Assert.assertNotNull("idp-review-profile added", exec); - // we'll need auth-cookie later - authCookieExec = findExecutionByProvider("auth-cookie", executionReps); - } finally { - response.close(); - } + // we'll need auth-cookie later + AuthenticationExecutionInfoRepresentation authCookieExec = findExecutionByProvider("auth-cookie", executionReps); compareExecution(newExecInfo("Review Profile", "idp-review-profile", true, 0, 3, DISABLED, null, new String[]{REQUIRED, DISABLED}), exec); @@ -89,15 +81,9 @@ public class ExecutionTest extends AbstractAuthenticationTest { authMgmtResource.removeExecution(exec.getId()); // check execution was removed - response = authMgmtResource.getExecutions("Copy of browser"); - try { - List executionReps = response.readEntity(new GenericType>() { - }); - exec = findExecutionByProvider("idp-review-profile", executionReps); - Assert.assertNull("idp-review-profile removed", exec); - } finally { - response.close(); - } + executionReps = authMgmtResource.getExecutions("Copy of browser"); + exec = findExecutionByProvider("idp-review-profile", executionReps); + Assert.assertNull("idp-review-profile removed", exec); // now add the execution again using a different method and representation @@ -130,16 +116,9 @@ public class ExecutionTest extends AbstractAuthenticationTest { } // check execution was added - List executions; - response = authMgmtResource.getExecutions("Copy of browser"); - try { - executions = response.readEntity(new GenericType>() { - }); - exec = findExecutionByProvider("auth-cookie", executions); - Assert.assertNotNull("auth-cookie added", exec); - } finally { - response.close(); - } + List executions = authMgmtResource.getExecutions("Copy of browser"); + exec = findExecutionByProvider("auth-cookie", executions); + Assert.assertNotNull("auth-cookie added", exec); // Note: there is no checking in addExecution if requirement is one of requirementChoices // Thus we can have OPTIONAL which is neither ALTERNATIVE, nor DISABLED @@ -150,10 +129,7 @@ public class ExecutionTest extends AbstractAuthenticationTest { public void testUpdateExecution() { // get current auth-cookie execution - Response response = authMgmtResource.getExecutions("browser"); - List executionReps = response.readEntity( - new GenericType>() { - }); + List executionReps = authMgmtResource.getExecutions("browser"); AuthenticationExecutionInfoRepresentation exec = findExecutionByProvider("auth-cookie", executionReps); Assert.assertEquals("auth-cookie set to ALTERNATIVE", ALTERNATIVE, exec.getRequirement()); @@ -163,8 +139,7 @@ public class ExecutionTest extends AbstractAuthenticationTest { authMgmtResource.updateExecutions("browser", exec); // make sure the change is visible - response = authMgmtResource.getExecutions("browser"); - executionReps = response.readEntity(new GenericType>() {}); + executionReps = authMgmtResource.getExecutions("browser"); // get current auth-cookie execution AuthenticationExecutionInfoRepresentation exec2 = findExecutionByProvider("auth-cookie", executionReps); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java index 45f538fbd3..0f8487b74e 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java @@ -55,9 +55,7 @@ public class InitialFlowsTest extends AbstractAuthenticationTest { List flows = authMgmtResource.getFlows(); for (AuthenticationFlowRepresentation flow : flows) { // get all executions for flow - Response executions = authMgmtResource.getExecutions(flow.getAlias()); - List executionReps = executions.readEntity(new GenericType>() { - }); + List executionReps = authMgmtResource.getExecutions(flow.getAlias()); for (AuthenticationExecutionInfoRepresentation exec : executionReps) { // separately load referenced configurations diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ShiftExecutionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ShiftExecutionTest.java index b7c3c15c61..f9d4f001bd 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ShiftExecutionTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ShiftExecutionTest.java @@ -45,9 +45,7 @@ public class ShiftExecutionTest extends AbstractAuthenticationTest { } // get executions - response = authMgmtResource.getExecutions("Copy of browser"); - List executions = response.readEntity(new GenericType>() { - }); + List executions = authMgmtResource.getExecutions("Copy of browser"); AuthenticationExecutionInfoRepresentation last = executions.get(executions.size() - 1); AuthenticationExecutionInfoRepresentation oneButLast = executions.get(executions.size() - 2); @@ -55,9 +53,7 @@ public class ShiftExecutionTest extends AbstractAuthenticationTest { // shift last execution up authMgmtResource.raisePriority(last.getId()); - response = authMgmtResource.getExecutions("Copy of browser"); - List executions2 = response.readEntity(new GenericType>() { - }); + List executions2 = authMgmtResource.getExecutions("Copy of browser"); AuthenticationExecutionInfoRepresentation last2 = executions2.get(executions.size() - 1); AuthenticationExecutionInfoRepresentation oneButLast2 = executions2.get(executions.size() - 2); @@ -68,9 +64,7 @@ public class ShiftExecutionTest extends AbstractAuthenticationTest { // shift one before last down authMgmtResource.lowerPriority(oneButLast2.getId()); - response = authMgmtResource.getExecutions("Copy of browser"); - executions2 = response.readEntity(new GenericType>() { - }); + executions2 = authMgmtResource.getExecutions("Copy of browser"); last2 = executions2.get(executions.size() - 1); oneButLast2 = executions2.get(executions.size() - 2); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserFederationProviderBuilder.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserFederationProviderBuilder.java new file mode 100644 index 0000000000..61f45c76a9 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserFederationProviderBuilder.java @@ -0,0 +1,108 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.util; + +import java.util.HashMap; +import java.util.Map; + +import org.keycloak.representations.idm.UserFederationProviderRepresentation; + +/** + * @author Marek Posolda + */ +public class UserFederationProviderBuilder { + + private String id; + private String displayName; + private String providerName; + private Map config; + private int priority = 1; + private int fullSyncPeriod = -1; + private int changedSyncPeriod = -1; + private int lastSync = -1; + + private UserFederationProviderBuilder() {}; + + public static UserFederationProviderBuilder create() { + return new UserFederationProviderBuilder(); + } + + public void setId(String id) { + this.id = id; + } + + public UserFederationProviderBuilder displayName(String displayName) { + this.displayName = displayName; + return this; + } + + public UserFederationProviderBuilder providerName(String providerName) { + this.providerName = providerName; + return this; + } + + public UserFederationProviderBuilder configProperty(String key, String value) { + if (this.config == null) { + this.config = new HashMap<>(); + } + this.config.put(key, value); + return this; + } + + public UserFederationProviderBuilder removeConfigProperty(String key) { + if (this.config != null) { + this.config.remove(key); + } + return this; + } + + public UserFederationProviderBuilder priority(int priority) { + this.priority = priority; + return this; + } + + public UserFederationProviderBuilder fullSyncPeriod(int fullSyncPeriod) { + this.fullSyncPeriod = fullSyncPeriod; + return this; + } + + public UserFederationProviderBuilder changedSyncPeriod(int changedSyncPeriod) { + this.changedSyncPeriod = changedSyncPeriod; + return this; + } + + public UserFederationProviderBuilder lastSync(int lastSync) { + this.lastSync = lastSync; + return this; + } + + public UserFederationProviderRepresentation build() { + UserFederationProviderRepresentation rep = new UserFederationProviderRepresentation(); + rep.setId(id); + rep.setDisplayName(displayName); + rep.setProviderName(providerName); + rep.setConfig(config); + rep.setPriority(priority); + rep.setFullSyncPeriod(fullSyncPeriod); + rep.setChangedSyncPeriod(changedSyncPeriod); + rep.setLastSync(lastSync); + return rep; + } + + +}