keycloak-aplcache

Changes

services/src/main/java/org/keycloak/authorization/admin/PermissionTypeService.java 94(+0 -94)

Details

diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/PolicyRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/PolicyRepresentation.java
index dc04991..e36d7af 100644
--- a/core/src/main/java/org/keycloak/representations/idm/authorization/PolicyRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/PolicyRepresentation.java
@@ -18,53 +18,14 @@ package org.keycloak.representations.idm.authorization;
 
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Objects;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
-public class PolicyRepresentation {
+public class PolicyRepresentation extends AbstractPolicyRepresentation {
 
-    private String id;
-    private String name;
-    private String description;
-    private String type;
-    private Logic logic = Logic.POSITIVE;
-    private DecisionStrategy decisionStrategy = DecisionStrategy.UNANIMOUS;
     private Map<String, String> config = new HashMap();
 
-    public String getId() {
-        return this.id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getType() {
-        return this.type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public DecisionStrategy getDecisionStrategy() {
-        return this.decisionStrategy;
-    }
-
-    public void setDecisionStrategy(DecisionStrategy decisionStrategy) {
-        this.decisionStrategy = decisionStrategy;
-    }
-
-    public Logic getLogic() {
-        return logic;
-    }
-
-    public void setLogic(Logic logic) {
-        this.logic = logic;
-    }
-
     public Map<String, String> getConfig() {
         return this.config;
     }
@@ -72,33 +33,4 @@ public class PolicyRepresentation {
     public void setConfig(Map<String, String> config) {
         this.config = config;
     }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getDescription() {
-        return this.description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    @Override
-    public boolean equals(final Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        final PolicyRepresentation policy = (PolicyRepresentation) o;
-        return Objects.equals(getId(), policy.getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(getId());
-    }
 }
\ No newline at end of file
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/AuthorizationResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/AuthorizationResource.java
index 07276ec..de8d958 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/AuthorizationResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/AuthorizationResource.java
@@ -23,6 +23,7 @@ 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.core.MediaType;
 
@@ -58,4 +59,7 @@ public interface AuthorizationResource {
 
     @Path("/policy")
     PoliciesResource policies();
+
+    @Path("/permission")
+    PermissionsResource permissions();
 }
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PermissionsResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PermissionsResource.java
new file mode 100644
index 0000000..6c16080
--- /dev/null
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PermissionsResource.java
@@ -0,0 +1,28 @@
+/*
+ * 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 javax.ws.rs.Path;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public interface PermissionsResource {
+
+    @Path("resource")
+    ResourcePermissionsResource resource();
+}
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PoliciesResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PoliciesResource.java
index e5120c6..2d31ab1 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PoliciesResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PoliciesResource.java
@@ -28,6 +28,7 @@ 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;
 import javax.ws.rs.core.Response;
 import java.util.List;
@@ -45,6 +46,12 @@ public interface PoliciesResource {
     @Path("{id}")
     PolicyResource policy(@PathParam("id") String id);
 
+    @Path("/search")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    PolicyRepresentation findByName(@QueryParam("name") String name);
+
     @GET
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourcePermissionResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourcePermissionResource.java
new file mode 100644
index 0000000..ec49ec8
--- /dev/null
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourcePermissionResource.java
@@ -0,0 +1,69 @@
+/*
+ * 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.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public interface ResourcePermissionResource {
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    ResourcePermissionRepresentation toRepresentation();
+
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    void update(ResourcePermissionRepresentation representation);
+
+    @DELETE
+    void remove();
+
+    @Path("/associatedPolicies")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    List<PolicyRepresentation> associatedPolicies();
+
+    @Path("/dependentPolicies")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    List<PolicyRepresentation> dependentPolicies();
+
+    @Path("/resources")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    List<ResourceRepresentation> resources();
+
+}
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourcePermissionsResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourcePermissionsResource.java
new file mode 100644
index 0000000..d4dd0ed
--- /dev/null
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourcePermissionsResource.java
@@ -0,0 +1,42 @@
+/*
+ * 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 javax.ws.rs.Consumes;
+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.authorization.ResourcePermissionRepresentation;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public interface ResourcePermissionsResource {
+
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    Response create(ResourcePermissionRepresentation representation);
+
+    @Path("{id}")
+    ResourcePermissionResource findById(@PathParam("id") String id);
+
+}
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourceScopesResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourceScopesResource.java
index 3a48114..ddcaf53 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourceScopesResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourceScopesResource.java
@@ -25,6 +25,7 @@ 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;
 import javax.ws.rs.core.Response;
 import java.util.List;
@@ -46,4 +47,10 @@ public interface ResourceScopesResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     List<ScopeRepresentation> scopes();
+
+    @Path("/search")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    ScopeRepresentation findByName(@QueryParam("name") String name);
 }
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourcesResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourcesResource.java
index 07438d0..e7daaa1 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourcesResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourcesResource.java
@@ -57,5 +57,10 @@ public interface ResourcesResource {
     @GET
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
+    List<ResourceRepresentation> findByName(@QueryParam("name") String name);
+
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
     List<ResourceRepresentation> resources();
 }
diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 1d27f3d..766e275 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -2113,7 +2113,7 @@ public class RepresentationToModel {
                 type = "rules";
             }
             if (authorization.getProvider(type) == null) {
-                throw new RuntimeException("Unknown polucy type [" + type + "]. Could not find a provider for this type.");
+                throw new RuntimeException("Unknown policy type [" + type + "]. Could not find a provider for this type.");
             }
         }
 
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PermissionService.java b/services/src/main/java/org/keycloak/authorization/admin/PermissionService.java
index 32a607f..4ada87d 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PermissionService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PermissionService.java
@@ -28,18 +28,14 @@ import org.keycloak.services.resources.admin.RealmAuth;
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
 public class PermissionService extends PolicyService {
+
     public PermissionService(ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
         super(resourceServer, authorization, auth);
     }
 
     @Override
-    protected Object doCreatePolicyTypeResource(String type) {
-        return new PermissionTypeService(type, resourceServer, authorization, auth);
-    }
-
-    @Override
     protected PolicyResourceService doCreatePolicyResource(Policy policy) {
-        return new PermissionResourceService(policy, resourceServer, authorization, auth);
+        return new PolicyTypeResourceService(policy, resourceServer, authorization, auth);
     }
 
     @Override
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
index 66a3d1a..6a9a32f 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
@@ -50,8 +50,10 @@ import org.keycloak.authorization.store.PolicyStore;
 import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.models.Constants;
 import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
 import org.keycloak.representations.idm.authorization.PolicyProviderRepresentation;
 import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.services.ErrorResponse;
 import org.keycloak.services.resources.admin.RealmAuth;
 import org.keycloak.util.JsonSerialization;
 
@@ -72,10 +74,10 @@ public class PolicyService {
 
     @Path("{type}")
     public Object getResource(@PathParam("type") String type) {
-        PolicyProviderFactory providerFactory = authorization.getProviderFactory(type);
+        PolicyProviderFactory providerFactory = getPolicyProviderFactory(type);
 
         if (providerFactory != null) {
-            return doCreatePolicyTypeResource(type);
+            return new PolicyTypeService(type, resourceServer, authorization, auth);
         }
 
         Policy policy = authorization.getStoreFactory().getPolicyStore().findById(type, resourceServer.getId());
@@ -83,10 +85,6 @@ public class PolicyService {
         return doCreatePolicyResource(policy);
     }
 
-    protected Object doCreatePolicyTypeResource(String type) {
-        return new PolicyTypeService(type, resourceServer, authorization, auth);
-    }
-
     protected Object doCreatePolicyResource(Policy policy) {
         return new PolicyResourceService(policy, resourceServer, authorization, auth);
     }
@@ -95,13 +93,39 @@ public class PolicyService {
     @Consumes(MediaType.APPLICATION_JSON)
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
-    @Deprecated
     public Response create(String payload) {
         this.auth.requireManage();
-        return Response.status(Status.CREATED).entity(doCreate(payload)).build();
+
+        AbstractPolicyRepresentation representation = doCreateRepresentation(payload);
+
+        Policy existing = authorization.getStoreFactory().getPolicyStore().findByName(representation.getName(), resourceServer.getId());
+
+        if (existing != null) {
+            return ErrorResponse.exists("Policy with name [" + representation.getName() + "] already exists");
+        }
+
+        Policy policy = doCreate(representation);
+        PolicyProviderAdminService provider = getPolicyProviderAdminResource(representation.getType());
+
+        if (provider != null) {
+            try {
+                provider.onCreate(policy, representation);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+
+        representation.setId(policy.getId());
+
+        return Response.status(Status.CREATED).entity(representation).build();
     }
 
-    protected Object doCreate(String payload) {
+    protected Policy doCreate(AbstractPolicyRepresentation representation) {
+        return create(PolicyRepresentation.class.cast(representation));
+    }
+
+    protected AbstractPolicyRepresentation doCreateRepresentation(String payload) {
         PolicyRepresentation representation;
 
         try {
@@ -110,12 +134,10 @@ public class PolicyService {
             throw new RuntimeException("Failed to deserialize representation", cause);
         }
 
-        create(representation);
-
         return representation;
     }
 
-    public void create(PolicyRepresentation representation) {
+    public Policy create(PolicyRepresentation representation) {
         Policy policy = toModel(representation, this.resourceServer, authorization);
         PolicyProviderAdminService resource = getPolicyProviderAdminResource(policy.getType());
 
@@ -127,7 +149,7 @@ public class PolicyService {
             }
         }
 
-        representation.setId(policy.getId());
+        return policy;
     }
 
     protected Object toRepresentation(Policy model) {
@@ -268,7 +290,7 @@ public class PolicyService {
     }
 
     protected PolicyProviderAdminService getPolicyProviderAdminResource(String policyType) {
-        PolicyProviderFactory providerFactory = authorization.getProviderFactory(policyType);
+        PolicyProviderFactory providerFactory = getPolicyProviderFactory(policyType);
 
         if (providerFactory != null) {
             return providerFactory.getAdminResource(resourceServer, authorization);
@@ -277,6 +299,10 @@ public class PolicyService {
         return null;
     }
 
+    private PolicyProviderFactory getPolicyProviderFactory(String policyType) {
+        return authorization.getProviderFactory(policyType);
+    }
+
     private void findAssociatedPolicies(Policy policy, List<Policy> policies) {
         policy.getAssociatedPolicies().forEach(associated -> {
             policies.add(associated);
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeService.java
index 7d3f8b4..865e8db 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeService.java
@@ -16,13 +16,20 @@
  */
 package org.keycloak.authorization.admin;
 
+import static org.keycloak.models.utils.RepresentationToModel.toModel;
+
+import java.io.IOException;
+
 import javax.ws.rs.Path;
 
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
 import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.util.JsonSerialization;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -44,4 +51,36 @@ public class PolicyTypeService extends PolicyService {
 
         return resource;
     }
+
+    @Override
+    protected Object doCreatePolicyResource(Policy policy) {
+        return new PolicyTypeResourceService(policy, resourceServer,authorization, auth);
+    }
+
+    @Override
+    protected AbstractPolicyRepresentation doCreateRepresentation(String payload) {
+        PolicyProviderAdminService provider = getPolicyProviderAdminResource(type);
+        Class<? extends AbstractPolicyRepresentation> representationType = provider.getRepresentationType();
+
+        if (representationType == null) {
+            throw new RuntimeException("Policy provider for type [" + type + "] returned a null representation type.");
+        }
+
+        AbstractPolicyRepresentation representation;
+
+        try {
+            representation = JsonSerialization.readValue(payload, representationType);
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to deserialize JSON using policy provider for type [" + type + "].", e);
+        }
+
+        representation.setType(type);
+
+        return representation;
+    }
+
+    @Override
+    protected Policy doCreate(AbstractPolicyRepresentation representation) {
+        return toModel(representation, resourceServer, authorization);
+    }
 }
diff --git a/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java b/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
index 7724830..1ec9a13 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
@@ -41,6 +41,7 @@ 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 javax.ws.rs.core.Response.Status;
 
@@ -69,8 +70,8 @@ public class ScopeService {
     }
 
     @POST
-    @Consumes("application/json")
-    @Produces("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
     public Response create(ScopeRepresentation scope) {
         this.auth.requireManage();
         Scope model = toModel(scope, this.resourceServer, authorization);
@@ -82,8 +83,8 @@ public class ScopeService {
 
     @Path("{id}")
     @PUT
-    @Consumes("application/json")
-    @Produces("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
     public Response update(@PathParam("id") String id, ScopeRepresentation scope) {
         this.auth.requireManage();
         scope.setId(id);
@@ -134,7 +135,7 @@ public class ScopeService {
 
     @Path("{id}")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public Response findById(@PathParam("id") String id) {
         this.auth.requireView();
         Scope model = this.authorization.getStoreFactory().getScopeStore().findById(id, resourceServer.getId());
@@ -148,7 +149,7 @@ public class ScopeService {
 
     @Path("{id}/resources")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public Response getResources(@PathParam("id") String id) {
         this.auth.requireView();
         StoreFactory storeFactory = this.authorization.getStoreFactory();
@@ -170,7 +171,7 @@ public class ScopeService {
 
     @Path("{id}/permissions")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public Response getPermissions(@PathParam("id") String id) {
         this.auth.requireView();
         StoreFactory storeFactory = this.authorization.getStoreFactory();
@@ -195,7 +196,7 @@ public class ScopeService {
 
     @Path("/search")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public Response find(@QueryParam("name") String name) {
         this.auth.requireView();
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ResourcePermissionManagementTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ResourcePermissionManagementTest.java
new file mode 100644
index 0000000..b1572da
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ResourcePermissionManagementTest.java
@@ -0,0 +1,263 @@
+/*
+ * 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.client.authorization;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.IntFunction;
+import java.util.stream.Collectors;
+
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.core.Response;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.admin.client.resource.AuthorizationResource;
+import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.admin.client.resource.ClientsResource;
+import org.keycloak.admin.client.resource.RealmResource;
+import org.keycloak.admin.client.resource.ResourcePermissionResource;
+import org.keycloak.admin.client.resource.ResourcePermissionsResource;
+import org.keycloak.authorization.client.AuthzClient;
+import org.keycloak.authorization.client.Configuration;
+import org.keycloak.authorization.client.representation.ResourceRepresentation;
+import org.keycloak.authorization.client.representation.ScopeRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.authorization.DecisionStrategy;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
+import org.keycloak.testsuite.AbstractKeycloakTest;
+import org.keycloak.testsuite.util.AdminClientUtil;
+import org.keycloak.testsuite.util.ClientBuilder;
+import org.keycloak.testsuite.util.RealmBuilder;
+import org.keycloak.testsuite.util.UserBuilder;
+import org.keycloak.util.JsonSerialization;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ResourcePermissionManagementTest extends AbstractKeycloakTest {
+
+    @Override
+    public void addTestRealms(List<RealmRepresentation> testRealms) {
+        testRealms.add(RealmBuilder.create().name("authz-test")
+                .user(UserBuilder.create().username("marta").password("password"))
+                .user(UserBuilder.create().username("kolo").password("password"))
+                .client(ClientBuilder.create().clientId("resource-server-test")
+                        .secret("secret")
+                        .authorizationServicesEnabled(true)
+                        .redirectUris("http://localhost/resource-server-test")
+                        .defaultRoles("uma_protection")
+                        .directAccessGrants())
+                .build());
+    }
+
+    @Before
+    public void configureAuthorization() throws Exception {
+        createResourcesAndScopes();
+        RealmResource realm = getRealm();
+        createPolicies(realm, getClient(realm));
+    }
+
+    @Test
+    public void testCreateResourcePermission() {
+        AuthorizationResource authorization = getClient(getRealm()).authorization();
+        ResourcePermissionRepresentation representation = new ResourcePermissionRepresentation();
+
+        representation.setName("Resource A Permission");
+        representation.setDescription("description");
+        representation.setDecisionStrategy(DecisionStrategy.CONSENSUS);
+        representation.setLogic(Logic.NEGATIVE);
+        representation.addResource(getResourceId("Resource A", authorization));
+        representation.addPolicies(getPolicyIds(Arrays.asList("Only Marta Policy", "Only Kolo Policy"), authorization).stream().toArray((IntFunction<String[]>) value -> new String[value]));
+
+        assertCreated(authorization, representation);
+    }
+
+    @Test
+    public void testCreateResourceType() {
+        AuthorizationResource authorization = getClient(getRealm()).authorization();
+        ResourcePermissionRepresentation representation = new ResourcePermissionRepresentation();
+
+        representation.setName("Resource A Type Permission");
+        representation.setDescription("description");
+        representation.setDecisionStrategy(DecisionStrategy.CONSENSUS);
+        representation.setLogic(Logic.NEGATIVE);
+        representation.setResourceType("test-resource");
+        representation.addPolicies(getPolicyIds(Arrays.asList("Only Marta Policy"), authorization).stream().toArray((IntFunction<String[]>) value -> new String[value]));
+
+        assertCreated(authorization, representation);
+    }
+
+    @Test
+    public void testDelete() {
+        AuthorizationResource authorization = getClient(getRealm()).authorization();
+        ResourcePermissionRepresentation representation = new ResourcePermissionRepresentation();
+
+        representation.setName("Test Delete Permission");
+        representation.setResourceType("test-resource");
+        representation.addPolicies(getPolicyIds(Arrays.asList("Only Marta Policy"), authorization).stream().toArray((IntFunction<String[]>) value -> new String[value]));
+
+        ResourcePermissionsResource permissions = authorization.permissions().resource();
+        Response response = permissions.create(representation);
+        ResourcePermissionRepresentation created = response.readEntity(ResourcePermissionRepresentation.class);
+
+        permissions.findById(created.getId()).remove();
+
+        ResourcePermissionResource removed = permissions.findById(created.getId());
+
+        try {
+            removed.toRepresentation();
+            fail("Permission not removed");
+        } catch (NotFoundException ignore) {
+
+        }
+    }
+
+    @Test
+    public void failCreateWithSameName() {
+        AuthorizationResource authorization = getClient(getRealm()).authorization();
+        ResourcePermissionRepresentation permission1 = new ResourcePermissionRepresentation();
+
+        permission1.setName("Conflicting Name Permission");
+        permission1.setResourceType("test-resource");
+        permission1.addPolicies(getPolicyIds(Arrays.asList("Only Marta Policy"), authorization).stream().toArray((IntFunction<String[]>) value -> new String[value]));
+
+        ResourcePermissionsResource permissions = authorization.permissions().resource();
+
+        permissions.create(permission1);
+
+        ResourcePermissionRepresentation permission2 = new ResourcePermissionRepresentation();
+
+        permission2.setName(permission1.getName());
+
+        Response response = permissions.create(permission2);
+
+        assertEquals(Response.Status.CONFLICT.getStatusCode(), response.getStatus());
+    }
+
+    private void assertCreated(AuthorizationResource authorization, ResourcePermissionRepresentation representation) {
+        ResourcePermissionsResource permissions = authorization.permissions().resource();
+        Response response = permissions.create(representation);
+        ResourcePermissionRepresentation created = response.readEntity(ResourcePermissionRepresentation.class);
+
+        assertNotNull(created);
+        assertNotNull(created.getId());
+
+        ResourcePermissionResource permission = permissions.findById(created.getId());
+        ResourcePermissionRepresentation found = permission.toRepresentation();
+
+        assertNotNull(found);
+        assertEquals(created.getId(), found.getId());
+        assertEquals(created.getName(), found.getName());
+        assertEquals(created.getDescription(), found.getDescription());
+        assertEquals(created.getDecisionStrategy(), found.getDecisionStrategy());
+        assertEquals(created.getLogic(), found.getLogic());
+        assertEquals(created.getResourceType(), found.getResourceType());
+        assertNull(found.getResources());
+        assertNull(found.getPolicies());
+
+        assertEquals(representation.getPolicies().size(), permission.associatedPolicies().stream().map(representation1 -> representation1.getId()).filter(policyId -> representation.getPolicies().contains(policyId)).count());
+
+        if (representation.getResources() != null) {
+            assertEquals(representation.getResources().size(), permission.resources().stream().map(representation1 -> representation1.getId()).filter(resourceId -> representation.getResources().contains(resourceId)).count());
+        } else {
+            assertTrue(permission.resources().isEmpty());
+        }
+    }
+
+    private void createResourcesAndScopes() throws IOException {
+        AuthzClient authzClient = getAuthzClient();
+        Set<ScopeRepresentation> scopes = new HashSet<>();
+
+        scopes.add(new ScopeRepresentation("read"));
+        scopes.add(new ScopeRepresentation("write"));
+        scopes.add(new ScopeRepresentation("execute"));
+
+        List<ResourceRepresentation> resources = new ArrayList<>();
+
+        resources.add(new ResourceRepresentation("Resource A", scopes));
+        resources.add(new ResourceRepresentation("Resource B", scopes));
+        resources.add(new ResourceRepresentation("Resource C", scopes));
+
+        resources.forEach(resource -> authzClient.protection().resource().create(resource));
+    }
+
+    private void createPolicies(RealmResource realm, ClientResource client) throws IOException {
+        createUserPolicy("Only Marta Policy", realm, client, "marta");
+        createUserPolicy("Only Kolo Policy", realm, client, "kolo");
+    }
+
+    private void createUserPolicy(String name, RealmResource realm, ClientResource client, String username) throws IOException {
+        String userId = realm.users().search(username).stream().map(representation -> representation.getId()).findFirst().orElseThrow(() -> new RuntimeException("Expected user [userId]"));
+
+        PolicyRepresentation representation = new PolicyRepresentation();
+
+        representation.setName(name);
+        representation.setType("user");
+
+        Map<String, String> config = new HashMap<>();
+
+        config.put("users", JsonSerialization.writeValueAsString(new String[] {userId}));
+
+        representation.setConfig(config);
+
+        client.authorization().policies().create(representation);
+    }
+
+    private ClientResource getClient(RealmResource realm) {
+        ClientsResource clients = realm.clients();
+        return clients.findByClientId("resource-server-test").stream().map(representation -> clients.get(representation.getId())).findFirst().orElseThrow(() -> new RuntimeException("Expected client [resource-server-test]"));
+    }
+
+    private RealmResource getRealm() {
+        try {
+            return AdminClientUtil.createAdminClient().realm("authz-test");
+        } catch (Exception cause) {
+            throw new RuntimeException("Failed to create admin client", cause);
+        }
+    }
+
+    private String getResourceId(String resourceName, AuthorizationResource authorization) {
+        return authorization.resources().findByName(resourceName).stream().map(representation -> representation.getId()).findFirst().orElseThrow(() -> new RuntimeException("Expected user [userId]"));
+    }
+
+    private List<String> getPolicyIds(List<String> policies, AuthorizationResource authorization) {
+        return policies.stream().map(policyName -> authorization.policies().findByName(policyName).getId()).collect(Collectors.toList());
+    }
+
+    private AuthzClient getAuthzClient() {
+        try {
+            return AuthzClient.create(JsonSerialization.readValue(getClass().getResourceAsStream("/authorization-test/default-keycloak.json"), Configuration.class));
+        } catch (IOException cause) {
+            throw new RuntimeException("Failed to create authz client", cause);
+        }
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/ConflictingScopePermissionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/ConflictingScopePermissionTest.java
index da835d5..1b0b50b 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/ConflictingScopePermissionTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/ConflictingScopePermissionTest.java
@@ -33,6 +33,7 @@ import java.util.stream.Collectors;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.keycloak.admin.client.resource.AuthorizationResource;
 import org.keycloak.admin.client.resource.ClientResource;
 import org.keycloak.admin.client.resource.ClientsResource;
 import org.keycloak.admin.client.resource.RealmResource;
@@ -192,8 +193,9 @@ public class ConflictingScopePermissionTest extends AbstractKeycloakTest {
     }
 
     private void createResourcePermission(String name, String resourceName, List<String> policies, ClientResource client) throws IOException {
-        String resourceId = client.authorization().resources().find(resourceName, null, null, null, null, -1, -1).stream().map(representation -> representation.getId()).findFirst().orElseThrow(() -> new RuntimeException("Expected user [userId]"));
-        List<String> policyIds = client.authorization().policies().policies().stream().filter(representation -> policies.contains(representation.getName())).map(representation -> representation.getId()).collect(Collectors.toList());
+        AuthorizationResource authorization = client.authorization();
+        String resourceId = getResourceId(resourceName, authorization);
+        List<String> policyIds = getPolicyIds(policies, authorization);
 
         PolicyRepresentation representation = new PolicyRepresentation();
 
@@ -207,18 +209,23 @@ public class ConflictingScopePermissionTest extends AbstractKeycloakTest {
 
         representation.setConfig(config);
 
-        client.authorization().policies().create(representation);
+        authorization.policies().create(representation);
+    }
+
+    private String getResourceId(String resourceName, AuthorizationResource authorization) {
+        return authorization.resources().findByName(resourceName).stream().map(representation -> representation.getId()).findFirst().orElseThrow(() -> new RuntimeException("Expected user [userId]"));
     }
 
     private void createScopePermission(String name, String resourceName, List<String> scopes, List<String> policies, ClientResource client) throws IOException {
+        AuthorizationResource authorization = client.authorization();
         String resourceId = null;
 
         if (resourceName != null) {
-            resourceId = client.authorization().resources().find(resourceName, null, null, null, null, -1, -1).stream().map(representation -> representation.getId()).findFirst().orElseThrow(() -> new RuntimeException("Expected user [userId]"));
+            resourceId = getResourceId(resourceName, authorization);
         }
 
-        List<String> scopeIds = client.authorization().scopes().scopes().stream().filter(representation -> policies.contains(representation.getName())).map(representation -> representation.getId()).collect(Collectors.toList());
-        List<String> policyIds = client.authorization().policies().policies().stream().filter(representation -> policies.contains(representation.getName())).map(representation -> representation.getId()).collect(Collectors.toList());
+        List<String> scopeIds = scopes.stream().map(scopeName -> authorization.scopes().findByName(scopeName).getId()).collect(Collectors.toList());
+        List<String> policyIds = getPolicyIds(policies, authorization);
 
         PolicyRepresentation representation = new PolicyRepresentation();
 
@@ -236,7 +243,11 @@ public class ConflictingScopePermissionTest extends AbstractKeycloakTest {
 
         representation.setConfig(config);
 
-        client.authorization().policies().create(representation);
+        authorization.policies().create(representation);
+    }
+
+    private List<String> getPolicyIds(List<String> policies, AuthorizationResource authorization) {
+        return policies.stream().map(policyName -> authorization.policies().findByName(policyName).getId()).collect(Collectors.toList());
     }
 
     private AuthzClient getAuthzClient() {