diff --git a/core/src/main/java/org/keycloak/representations/idm/UserFederationSyncResultRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/SynchronizationResultRepresentation.java similarity index 94% rename from core/src/main/java/org/keycloak/representations/idm/UserFederationSyncResultRepresentation.java rename to core/src/main/java/org/keycloak/representations/idm/SynchronizationResultRepresentation.java index 08509efd50..dd17dfa98b 100644 --- a/core/src/main/java/org/keycloak/representations/idm/UserFederationSyncResultRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/SynchronizationResultRepresentation.java @@ -20,7 +20,7 @@ package org.keycloak.representations.idm; /** * @author Marek Posolda */ -public class UserFederationSyncResultRepresentation { +public class SynchronizationResultRepresentation { private boolean ignored; @@ -31,6 +31,9 @@ public class UserFederationSyncResultRepresentation { private String status; + public SynchronizationResultRepresentation() { + } + public boolean isIgnored() { return ignored; } 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 42b619655e..0e85682ec6 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 @@ -208,6 +208,10 @@ public interface RealmResource { @Path("components") ComponentsResource components(); + @Path("user-storage") + UserStorageProviderResource userStorage(); + + @Path("keys") KeyResource keys(); 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 deleted file mode 100644 index 9ba7638709..0000000000 --- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UserFederationProviderResource.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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 org.keycloak.representations.idm.UserFederationMapperRepresentation; -import org.keycloak.representations.idm.UserFederationMapperTypeRepresentation; -import org.keycloak.representations.idm.UserFederationProviderRepresentation; -import org.keycloak.representations.idm.UserFederationSyncResultRepresentation; - -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 java.util.List; -import java.util.Map; - -/** - * @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") - @Produces(MediaType.APPLICATION_JSON) - 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 deleted file mode 100644 index e98c008598..0000000000 --- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UserFederationProvidersResource.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation; -import org.keycloak.representations.idm.UserFederationProviderRepresentation; - -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 java.util.List; - -/** - * @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/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UserStorageProviderResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UserStorageProviderResource.java new file mode 100644 index 0000000000..974e6e33d0 --- /dev/null +++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UserStorageProviderResource.java @@ -0,0 +1,44 @@ +/* + * 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 org.keycloak.representations.idm.SynchronizationResultRepresentation; + +import javax.ws.rs.POST; +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; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public interface UserStorageProviderResource { + @POST + @Path("{componentId}/sync") + @Produces(MediaType.APPLICATION_JSON) + SynchronizationResultRepresentation syncUsers(@QueryParam("action") String action); + + @POST + @Path("{componentId}/mappers/{mapperId}/sync") + @Produces(MediaType.APPLICATION_JSON) + SynchronizationResultRepresentation syncMapperData(@PathParam("componentId") String componentId, @PathParam("mapperId") String mapperId, @QueryParam("direction") String direction); + + +} diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserStorageProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserStorageProviderResource.java index 8e29779d99..6476dce931 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/UserStorageProviderResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/UserStorageProviderResource.java @@ -34,6 +34,7 @@ import org.keycloak.storage.ldap.LDAPStorageProviderFactory; import org.keycloak.storage.ldap.mappers.LDAPStorageMapper; import org.keycloak.storage.user.SynchronizationResult; +import javax.ws.rs.BadRequestException; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @@ -141,7 +142,7 @@ public class UserStorageProviderResource { ComponentModel mapperModel = realm.getComponent(mapperId); if (mapperModel == null) throw new NotFoundException("Mapper model not found"); LDAPStorageMapper mapper = session.getProvider(LDAPStorageMapper.class, mapperModel); - ProviderFactory factory = session.getKeycloakSessionFactory().getProviderFactory(LDAPStorageProvider.class, parentModel.getProviderId()); + ProviderFactory factory = session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, parentModel.getProviderId()); LDAPStorageProviderFactory providerFactory = (LDAPStorageProviderFactory)factory; LDAPStorageProvider federationProvider = providerFactory.create(session, parentModel); @@ -154,7 +155,7 @@ public class UserStorageProviderResource { } else if ("keycloakToFed".equals(direction)) { syncResult = mapper.syncDataFromKeycloakToFederationProvider(mapperModel, federationProvider, session, realm); } else { - throw new NotFoundException("Unknown direction: " + direction); + throw new BadRequestException("Unknown direction: " + direction); } Map eventRep = new HashMap<>(); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserStorageMapperTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserStorageMapperTest.java index fa7eb145d5..933861aae9 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserStorageMapperTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserStorageMapperTest.java @@ -17,31 +17,7 @@ package org.keycloak.testsuite.admin; -import org.junit.After; -import org.junit.Before; import org.junit.Ignore; -import org.junit.Test; -import org.keycloak.admin.client.resource.UserFederationProviderResource; -import org.keycloak.events.admin.OperationType; -import org.keycloak.events.admin.ResourceType; -import org.keycloak.representations.idm.ConfigPropertyRepresentation; -import org.keycloak.representations.idm.UserFederationMapperRepresentation; -import org.keycloak.representations.idm.UserFederationMapperTypeRepresentation; -import org.keycloak.representations.idm.UserFederationProviderRepresentation; -import org.keycloak.representations.idm.UserFederationSyncResultRepresentation; -import org.keycloak.testsuite.Assert; -import org.keycloak.testsuite.util.AdminEventPaths; -import org.keycloak.testsuite.util.UserFederationProviderBuilder; - -import javax.ws.rs.BadRequestException; -import javax.ws.rs.NotFoundException; -import javax.ws.rs.core.Response; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; /** * @author Marek Posolda diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserStorageRestTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserStorageRestTest.java index 315bc8b0a6..9d5fdb6d72 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserStorageRestTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserStorageRestTest.java @@ -18,37 +18,13 @@ package org.keycloak.testsuite.admin; import org.junit.Ignore; -import org.junit.Test; -import org.keycloak.admin.client.resource.UserFederationProvidersResource; -import org.keycloak.common.constants.KerberosConstants; -import org.keycloak.events.admin.OperationType; -import org.keycloak.events.admin.ResourceType; -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.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.AdminEventPaths; -import org.keycloak.testsuite.util.UserFederationProviderBuilder; - -import javax.ws.rs.BadRequestException; -import javax.ws.rs.NotFoundException; -import javax.ws.rs.core.Response; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; /** * @author Marek Posolda */ @Ignore public class UserStorageRestTest extends AbstractAdminTest { - +/* @Test public void testProviderFactories() { List providerFactories = userFederation().getProviderFactories(); @@ -339,7 +315,7 @@ public class UserStorageRestTest extends AbstractAdminTest { Assert.assertEquals(-1, userFederation().get(id1).toRepresentation().getLastSync()); // Sync and assert it happened - UserFederationSyncResultRepresentation syncResult = userFederation().get(id1).syncUsers("triggerFullSync"); + SynchronizationResultRepresentation syncResult = userFederation().get(id1).syncUsers("triggerFullSync"); Assert.assertEquals("0 imported users, 0 updated users", syncResult.getStatus()); Map eventRep = new HashMap<>(); @@ -404,4 +380,5 @@ public class UserStorageRestTest extends AbstractAdminTest { Assert.assertNotNull(kerberosExecution); return kerberosExecution; } + */ } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/AdminEventPaths.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/AdminEventPaths.java index 74e0046999..5e61d00c06 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/AdminEventPaths.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/AdminEventPaths.java @@ -35,8 +35,6 @@ import org.keycloak.admin.client.resource.RoleByIdResource; import org.keycloak.admin.client.resource.RoleMappingResource; import org.keycloak.admin.client.resource.RoleResource; import org.keycloak.admin.client.resource.RolesResource; -import org.keycloak.admin.client.resource.UserFederationProviderResource; -import org.keycloak.admin.client.resource.UserFederationProvidersResource; import org.keycloak.admin.client.resource.UserResource; import org.keycloak.admin.client.resource.UsersResource; @@ -284,29 +282,6 @@ public class AdminEventPaths { return uri.toString(); } - // USER FEDERATION PROVIDERS AND MAPPERS - - public static String userFederationsResourcePath() { - URI uri = UriBuilder.fromUri("").path(RealmResource.class, "userFederation").build(); - return uri.toString(); - } - - public static String userFederationCreateResourcePath() { - URI uri = UriBuilder.fromUri(userFederationsResourcePath()).path(UserFederationProvidersResource.class, "create").build(); - return uri.toString(); - } - - public static String userFederationResourcePath(String userFederationId) { - URI uri = UriBuilder.fromUri(userFederationsResourcePath()).path(UserFederationProvidersResource.class, "get").build(userFederationId); - return uri.toString(); - } - - public static String userFederationMapperResourcePath(String userFederationId, String userFederationMapperId) { - URI uri = UriBuilder.fromUri(userFederationResourcePath(userFederationId)) - .path(UserFederationProviderResource.class, "getMapperById").build(userFederationMapperId); - return uri.toString(); - } - // CLIENT INITIAL ACCESS public static String clientInitialAccessPath(String clientInitialAccessId) { diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapperSyncTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapperSyncTest.java index e5a9ff3ff2..9b41bb6433 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapperSyncTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapperSyncTest.java @@ -25,8 +25,11 @@ import org.junit.Test; import org.junit.rules.RuleChain; import org.junit.rules.TestRule; import org.junit.runners.MethodSorters; +import org.keycloak.admin.client.Keycloak; import org.keycloak.common.util.MultivaluedHashMap; import org.keycloak.component.ComponentModel; +import org.keycloak.models.Constants; +import org.keycloak.representations.idm.SynchronizationResultRepresentation; import org.keycloak.storage.UserStorageProvider; import org.keycloak.storage.UserStorageProviderModel; import org.keycloak.storage.ldap.LDAPStorageProvider; @@ -50,9 +53,14 @@ import org.keycloak.storage.user.SynchronizationResult; import org.keycloak.testsuite.rule.KeycloakRule; import org.keycloak.testsuite.rule.LDAPRule; +import javax.ws.rs.BadRequestException; import java.util.List; import java.util.Set; +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.MASTER; +import static org.keycloak.models.AdminRoles.ADMIN; +import static org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT; + /** * @author Marek Posolda */ @@ -106,8 +114,12 @@ public class LDAPGroupMapperSyncTest { .outerRule(ldapRule) .around(keycloakRule); + protected Keycloak adminClient; + @Before public void before() { + adminClient = Keycloak.getInstance(AUTH_SERVER_ROOT, MASTER, ADMIN, ADMIN, Constants.ADMIN_CLI_CLIENT_ID); + KeycloakSession session = keycloakRule.startSession(); try { RealmModel realm = session.realms().getRealmByName("test"); @@ -166,6 +178,24 @@ public class LDAPGroupMapperSyncTest { } } + @Test + public void testSyncRestAPI() { + KeycloakSession session = keycloakRule.startSession(); + try { + RealmModel realm = session.realms().getRealmByName("test"); + ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(realm,ldapModel, "groupsMapper"); + try { + // testing KEYCLOAK-3980 which threw an NPE because I was looking up the factory wrong. + SynchronizationResultRepresentation syncResultRep = adminClient.realm("test").userStorage().syncMapperData(ldapModel.getId(), mapperModel.getId(), "error"); + Assert.fail("Should throw 400"); + } catch (BadRequestException e) { + } + } finally { + keycloakRule.stopSession(session, false); + } + + } + @Test public void test02_syncWithGroupInheritance() throws Exception { KeycloakSession session = keycloakRule.startSession(); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPTestUtils.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPTestUtils.java index df86f1f712..db69be7a10 100644 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPTestUtils.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPTestUtils.java @@ -29,6 +29,7 @@ import org.keycloak.models.UserProvider; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.models.utils.UserModelDelegate; import org.keycloak.representations.idm.CredentialRepresentation; +import org.keycloak.representations.idm.SynchronizationResultRepresentation; import org.keycloak.storage.UserStorageProvider; import org.keycloak.storage.ldap.LDAPStorageProvider; import org.keycloak.storage.ldap.LDAPUtils; @@ -309,4 +310,10 @@ public class LDAPTestUtils { Assert.assertEquals(expectedRemoved, syncResult.getRemoved()); Assert.assertEquals(expectedFailed, syncResult.getFailed()); } + public static void assertSyncEquals(SynchronizationResultRepresentation syncResult, int expectedAdded, int expectedUpdated, int expectedRemoved, int expectedFailed) { + Assert.assertEquals(expectedAdded, syncResult.getAdded()); + Assert.assertEquals(expectedUpdated, syncResult.getUpdated()); + Assert.assertEquals(expectedRemoved, syncResult.getRemoved()); + Assert.assertEquals(expectedFailed, syncResult.getFailed()); + } }