keycloak-uncached

Details

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 80c9e42..72cd7aa 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<ResourceRepresentation> 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<ResourceRepresentation> 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<String[]> callable = new Callable<String[]>() {
             @Override
             public String[] call() throws Exception {
-                return http.<String[]>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 {
@@ -195,6 +183,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> 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<List<ResourceRepresentation>> callable = new Callable<List<ResourceRepresentation>>() {
+                @Override
+                public List<ResourceRepresentation> call() {
+                    return (List<ResourceRepresentation>) createFindRequest(id, name, uri, owner, type, scope, matchingUri, deep, firstResult, maxResult).response().json(new TypeReference<List<ResourceRepresentation>>() {
+                    }).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.
      *
      * @return @return an array of strings with the resource ids
@@ -235,19 +257,7 @@ public class ProtectedResource {
      * @param uri the resource uri
      */
     public List<ResourceRepresentation> findByUri(String uri) {
-        String[] ids = find(null, null, uri, null, null, null, false, null, null);
-
-        if (ids.length == 0) {
-            return Collections.emptyList();
-        }
-
-        List<ResourceRepresentation> 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<ResourceRepresentation> findByMatchingUri(String uri) {
-        String[] ids = find(null, null, uri, null, null, null, true, null, null);
-
-        if (ids.length == 0) {
-            return Collections.emptyList();
-        }
-
-        List<ResourceRepresentation> representations = new ArrayList<>();
-
-        for (String id : ids) {
-            representations.add(findById(id));
-        }
+        return find(null, null, uri, null, null, null, true, true,null, null);
+    }
 
-        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 4368a9a..de83a61 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, Boolean, String>) (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, Boolean, String>) (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 5800071..1855f9e 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<String, List<String>> 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<ResourceRepresentation> 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;
     }