From b80701589c26850b2aadd20f078bfa96dd0b55ef Mon Sep 17 00:00:00 2001 From: Corentin Dupont Date: Fri, 17 Aug 2018 17:42:07 +0200 Subject: [PATCH] [KEYCLOAK-7804] - Option to return resource body --- .../client/resource/ProtectedResource.java | 105 ++++++++++-------- .../protection/resource/ResourceService.java | 9 +- ...ResourceManagementWithAuthzClientTest.java | 51 ++++++++- 3 files changed, 115 insertions(+), 50 deletions(-) diff --git a/authz/client/src/main/java/org/keycloak/authorization/client/resource/ProtectedResource.java b/authz/client/src/main/java/org/keycloak/authorization/client/resource/ProtectedResource.java index 80c9e42727..72cd7aacf1 100644 --- a/authz/client/src/main/java/org/keycloak/authorization/client/resource/ProtectedResource.java +++ b/authz/client/src/main/java/org/keycloak/authorization/client/resource/ProtectedResource.java @@ -17,14 +17,14 @@ */ package org.keycloak.authorization.client.resource; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; +import com.fasterxml.jackson.core.type.TypeReference; import org.keycloak.authorization.client.Configuration; import org.keycloak.authorization.client.representation.ServerConfiguration; import org.keycloak.authorization.client.util.Http; +import org.keycloak.authorization.client.util.HttpMethod; import org.keycloak.authorization.client.util.Throwables; import org.keycloak.authorization.client.util.TokenCallable; import org.keycloak.representations.idm.authorization.ResourceRepresentation; @@ -128,13 +128,13 @@ public class ProtectedResource { * @return a {@link ResourceRepresentation} */ public ResourceRepresentation findByName(String name) { - String[] representations = find(null, name, null, configuration.getResource(), null, null, false, null, null); + List representations = find(null, name, null, configuration.getResource(), null, null, false, true, null, null); - if (representations.length == 0) { + if (representations.isEmpty()) { return null; } - return findById(representations[0]); + return representations.get(0); } /** @@ -145,13 +145,13 @@ public class ProtectedResource { * @return a {@link ResourceRepresentation} */ public ResourceRepresentation findByName(String name, String ownerId) { - String[] representations = find(null, name, null, ownerId, null, null, false, null, null); + List representations = find(null, name, null, ownerId, null, null, false, true,null, null); - if (representations.length == 0) { + if (representations.isEmpty()) { return null; } - return findById(representations[0]); + return representations.get(0); } /** @@ -172,19 +172,7 @@ public class ProtectedResource { Callable callable = new Callable() { @Override public String[] call() throws Exception { - return http.get(serverConfiguration.getResourceRegistrationEndpoint()) - .authorizationBearer(pat.call()) - .param("_id", id) - .param("name", name) - .param("uri", uri) - .param("owner", owner) - .param("type", type) - .param("scope", scope) - .param("matchingUri", Boolean.valueOf(matchingUri).toString()) - .param("deep", Boolean.FALSE.toString()) - .param("first", firstResult != null ? firstResult.toString() : null) - .param("max", maxResult != null ? maxResult.toString() : null) - .response().json(String[].class).execute(); + return (String[]) createFindRequest(id, name, uri, owner, type, scope, matchingUri, false, firstResult, maxResult).response().json(String[].class).execute(); } }; try { @@ -194,6 +182,40 @@ public class ProtectedResource { } } + /** + * Query the server for any resource with the matching arguments. + * + * @param id the resource id + * @param name the resource name + * @param uri the resource uri + * @param owner the resource owner + * @param type the resource type + * @param scope the resource scope + * @param matchingUri the resource uri. Use this parameter to lookup a resource that best match the given uri + * @param deep if the result should be a list of resource representations with details about the resource. If false, only ids are returned + * @param firstResult the position of the first resource to retrieve + * @param maxResult the maximum number of resources to retrieve + * @return a list of resource representations or an array of strings representing resource ids, depending on the generic type + */ + public R find(final String id, final String name, final String uri, final String owner, final String type, final String scope, final boolean matchingUri, final boolean deep, final Integer firstResult, final Integer maxResult) { + if (deep) { + Callable> callable = new Callable>() { + @Override + public List call() { + return (List) createFindRequest(id, name, uri, owner, type, scope, matchingUri, deep, firstResult, maxResult).response().json(new TypeReference>() { + }).execute(); + } + }; + try { + return (R) callable.call(); + } catch (Exception cause) { + return (R) Throwables.retryAndWrapExceptionIfNecessary(callable, pat, "Could not find resource", cause); + } + } + + return (R) find(id, name, uri, owner, type, scope, matchingUri, firstResult, maxResult); + } + /** * Query the server for all resources. * @@ -235,19 +257,7 @@ public class ProtectedResource { * @param uri the resource uri */ public List findByUri(String uri) { - String[] ids = find(null, null, uri, null, null, null, false, null, null); - - if (ids.length == 0) { - return Collections.emptyList(); - } - - List representations = new ArrayList<>(); - - for (String id : ids) { - representations.add(findById(id)); - } - - return representations; + return find(null, null, uri, null, null, null, false, true, null, null); } /** @@ -258,18 +268,21 @@ public class ProtectedResource { * @return a list of resources */ public List findByMatchingUri(String uri) { - String[] ids = find(null, null, uri, null, null, null, true, null, null); + return find(null, null, uri, null, null, null, true, true,null, null); + } - if (ids.length == 0) { - return Collections.emptyList(); - } - - List representations = new ArrayList<>(); - - for (String id : ids) { - representations.add(findById(id)); - } - - return representations; + private HttpMethod createFindRequest(String id, String name, String uri, String owner, String type, String scope, boolean matchingUri, boolean deep, Integer firstResult, Integer maxResult) { + return http.get(serverConfiguration.getResourceRegistrationEndpoint()) + .authorizationBearer(pat.call()) + .param("_id", id) + .param("name", name) + .param("uri", uri) + .param("owner", owner) + .param("type", type) + .param("scope", scope) + .param("matchingUri", Boolean.valueOf(matchingUri).toString()) + .param("deep", Boolean.toString(deep)) + .param("first", firstResult != null ? firstResult.toString() : null) + .param("max", maxResult != null ? maxResult.toString() : null); } } \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java b/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java index 4368a9afc1..de83a61d6b 100644 --- a/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java +++ b/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java @@ -128,7 +128,12 @@ public class ResourceService { @QueryParam("deep") Boolean deep, @QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResult) { - return resourceManager.find(id, name, uri, owner, type, scope, matchingUri, deep, firstResult, maxResult, (BiFunction) (resource, deep1) -> resource.getId()); + + if(deep != null && deep) { + return resourceManager.find(id, name, uri, owner, type, scope, matchingUri, deep, firstResult, maxResult); + } else { + return resourceManager.find(id, name, uri, owner, type, scope, matchingUri, deep, firstResult, maxResult, (BiFunction) (resource, deep1) -> resource.getId()); + } } private void checkResourceServerSettings() { @@ -136,4 +141,4 @@ public class ResourceService { throw new ErrorResponseException("not_supported", "Remote management is disabled.", Status.BAD_REQUEST); } } -} \ No newline at end of file +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ResourceManagementWithAuthzClientTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ResourceManagementWithAuthzClientTest.java index 5800071844..1855f9ef01 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ResourceManagementWithAuthzClientTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ResourceManagementWithAuthzClientTest.java @@ -19,12 +19,22 @@ package org.keycloak.testsuite.admin.client.authorization; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import java.io.IOException; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; +import org.hamcrest.collection.IsMapContaining; import org.junit.Test; import org.keycloak.authorization.client.AuthzClient; import org.keycloak.authorization.client.Configuration; @@ -96,6 +106,36 @@ public class ResourceManagementWithAuthzClientTest extends ResourceManagementTes assertEquals("/resources/{pattern}/sub-resources/{pattern}/*", resources.get(0).getUri()); } + @Test + public void testFindDeep() { + ResourceRepresentation resource1 = new ResourceRepresentation("/*", new HashSet<>()); + + resource1.addScope("a", "b", "c"); + resource1.setType("type"); + + Map> attributes = new HashMap<>(); + + attributes.put("a", Arrays.asList("a")); + attributes.put("b", Arrays.asList("b")); + attributes.put("c", Arrays.asList("c")); + + resource1.setAttributes(attributes); + + resource1.setIconUri("icon"); + resource1.setUris(new HashSet<>(Arrays.asList("/a", "/b", "/c"))); + + ResourceRepresentation resource = doCreateResource(resource1); + AuthzClient authzClient = getAuthzClient(); + List representations = authzClient.protection().resource().find(resource.getId(), null, null, null, null, null, false, true,null, null); + + assertEquals(1, representations.size()); + assertEquals(resource.getId(), representations.get(0).getId()); + assertEquals(resource.getName(), representations.get(0).getName()); + assertEquals(resource.getIconUri(), representations.get(0).getIconUri()); + assertThat(resource.getUris(), Matchers.containsInAnyOrder(representations.get(0).getUris().toArray())); + assertThat(resource.getAttributes().entrySet(), Matchers.containsInAnyOrder(representations.get(0).getAttributes().entrySet().toArray())); + } + @Override protected ResourceRepresentation doCreateResource(ResourceRepresentation newResource) { ResourceRepresentation resource = toResourceRepresentation(newResource); @@ -127,7 +167,7 @@ public class ResourceManagementWithAuthzClientTest extends ResourceManagementTes resourceRepresentation.setId(created.getId()); resourceRepresentation.setName(created.getName()); resourceRepresentation.setIconUri(created.getIconUri()); - resourceRepresentation.setUri(created.getUri()); + resourceRepresentation.setUris(created.getUris()); resourceRepresentation.setType(created.getType()); resourceRepresentation.setOwner(created.getOwner()); resourceRepresentation.setScopes(created.getScopes().stream().map(scopeRepresentation -> { @@ -151,7 +191,13 @@ public class ResourceManagementWithAuthzClientTest extends ResourceManagementTes resource.setId(newResource.getId()); resource.setName(newResource.getName()); resource.setIconUri(newResource.getIconUri()); - resource.setUri(newResource.getUri()); + + if (newResource.getUris() != null && !newResource.getUris().isEmpty()) { + resource.setUris(newResource.getUris()); + } else { + resource.setUri(newResource.getUri()); + } + resource.setType(newResource.getType()); if (newResource.getOwner() != null) { @@ -169,6 +215,7 @@ public class ResourceManagementWithAuthzClientTest extends ResourceManagementTes resource.setAttributes(newResource.getAttributes()); + return resource; }