[KEYCLOAK-10705] - Return full resource representation when querying policies by id

This commit is contained in:
Pedro Igor 2019-12-13 19:18:13 -03:00 committed by Stian Thorgersen
parent 9fd7ab81f0
commit 709cbfd4b7
11 changed files with 123 additions and 26 deletions

View file

@ -21,6 +21,8 @@ import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import com.fasterxml.jackson.annotation.JsonInclude;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
@ -36,6 +38,12 @@ public class AbstractPolicyRepresentation {
private Logic logic = Logic.POSITIVE;
private DecisionStrategy decisionStrategy = DecisionStrategy.UNANIMOUS;
private String owner;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private Set<ResourceRepresentation> resourcesData;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private Set<ScopeRepresentation> scopesData;
public String getId() {
return this.id;
@ -162,4 +170,20 @@ public class AbstractPolicyRepresentation {
public int hashCode() {
return Objects.hash(getId());
}
public <R> void setResourcesData(Set<ResourceRepresentation> resources) {
this.resourcesData = resources;
}
public Set<ResourceRepresentation> getResourcesData() {
return resourcesData;
}
public void setScopesData(Set<ScopeRepresentation> scopesData) {
this.scopesData = scopesData;
}
public Set<ScopeRepresentation> getScopesData() {
return scopesData;
}
}

View file

@ -57,6 +57,20 @@ public interface PoliciesResource {
@NoCache
List<PolicyRepresentation> policies();
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
List<PolicyRepresentation> policies(@QueryParam("policyId") String id,
@QueryParam("name") String name,
@QueryParam("type") String type,
@QueryParam("resource") String resource,
@QueryParam("scope") String scope,
@QueryParam("permission") Boolean permission,
@QueryParam("owner") String owner,
@QueryParam("fields") String fields,
@QueryParam("first") Integer firstResult,
@QueryParam("max") Integer maxResult);
@Path("providers")
@GET
@Produces(MediaType.APPLICATION_JSON)

View file

@ -24,6 +24,7 @@ import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.jboss.resteasy.annotations.cache.NoCache;
@ -41,6 +42,11 @@ public interface PolicyResource {
@NoCache
PolicyRepresentation toRepresentation();
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
PolicyRepresentation toRepresentation(@QueryParam("fields") String fields);
@PUT
@Consumes(MediaType.APPLICATION_JSON)
void update(PolicyRepresentation representation);

View file

@ -817,6 +817,10 @@ public class ModelToRepresentation {
}
public static <R extends AbstractPolicyRepresentation> R toRepresentation(Policy policy, AuthorizationProvider authorization, boolean genericRepresentation, boolean export) {
return toRepresentation(policy, authorization, genericRepresentation, export, false);
}
public static <R extends AbstractPolicyRepresentation> R toRepresentation(Policy policy, AuthorizationProvider authorization, boolean genericRepresentation, boolean export, boolean allFields) {
PolicyProviderFactory providerFactory = authorization.getProviderFactory(policy.getType());
R representation;
@ -840,6 +844,13 @@ public class ModelToRepresentation {
representation.setType(policy.getType());
representation.setDecisionStrategy(policy.getDecisionStrategy());
representation.setLogic(policy.getLogic());
if (allFields) {
representation.setResourcesData(policy.getResources().stream().map(
resource -> toRepresentation(resource, resource.getResourceServer(), authorization, true)).collect(Collectors.toSet()));
representation.setScopesData(policy.getScopes().stream().map(
resource -> toRepresentation(resource)).collect(Collectors.toSet()));
}
return representation;
}

View file

@ -45,22 +45,22 @@ public class PermissionService extends PolicyService {
protected PolicyTypeService doCreatePolicyTypeResource(String type) {
return new PolicyTypeService(type, resourceServer, authorization, auth, adminEvent) {
@Override
protected List<Object> doSearch(Integer firstResult, Integer maxResult, Map<String, String[]> filters) {
protected List<Object> doSearch(Integer firstResult, Integer maxResult, String fields, Map<String, String[]> filters) {
filters.put("permission", new String[] {Boolean.TRUE.toString()});
filters.put("type", new String[] {type});
return super.doSearch(firstResult, maxResult, filters);
return super.doSearch(firstResult, maxResult, fields, filters);
}
};
}
@Override
protected List<Object> doSearch(Integer firstResult, Integer maxResult, Map<String, String[]> filters) {
protected List<Object> doSearch(Integer firstResult, Integer maxResult, String fields, Map<String, String[]> filters) {
filters.put("permission", new String[] {Boolean.TRUE.toString()});
return super.doSearch(firstResult, maxResult, filters);
return super.doSearch(firstResult, maxResult, fields, filters);
}
@Override
protected AbstractPolicyRepresentation toRepresentation(Policy policy, AuthorizationProvider authorization) {
return ModelToRepresentation.toRepresentation(policy, authorization, false, false);
protected AbstractPolicyRepresentation toRepresentation(Policy policy, String fields, AuthorizationProvider authorization) {
return ModelToRepresentation.toRepresentation(policy, authorization, false, false, fields != null && fields.equals("*"));
}
}

View file

@ -26,6 +26,7 @@ import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
@ -121,7 +122,7 @@ public class PolicyResourceService {
@GET
@Produces("application/json")
@NoCache
public Response findById() {
public Response findById(@QueryParam("fields") String fields) {
if (auth != null) {
this.auth.realm().requireViewAuthorization();
}
@ -130,11 +131,15 @@ public class PolicyResourceService {
return Response.status(Status.NOT_FOUND).build();
}
return Response.ok(toRepresentation(policy, authorization)).build();
return Response.ok(toRepresentation(policy, fields, authorization)).build();
}
protected AbstractPolicyRepresentation toRepresentation(Policy policy, AuthorizationProvider authorization) {
return ModelToRepresentation.toRepresentation(policy, authorization, true, false);
private AbstractPolicyRepresentation toRepresentation(Policy policy, AuthorizationProvider authorization) {
return toRepresentation(policy, null, authorization);
}
protected AbstractPolicyRepresentation toRepresentation(Policy policy, String fields, AuthorizationProvider authorization) {
return ModelToRepresentation.toRepresentation(policy, authorization, true, false, fields != null && fields.equals("*"));
}
@Path("/dependentPolicies")

View file

@ -146,7 +146,7 @@ public class PolicyService {
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public Response findByName(@QueryParam("name") String name) {
public Response findByName(@QueryParam("name") String name, @QueryParam("fields") String fields) {
if (auth != null) {
this.auth.realm().requireViewAuthorization();
}
@ -163,7 +163,7 @@ public class PolicyService {
return Response.status(Status.OK).build();
}
return Response.ok(toRepresentation(model, authorization)).build();
return Response.ok(toRepresentation(model, fields, authorization)).build();
}
@GET
@ -176,6 +176,7 @@ public class PolicyService {
@QueryParam("scope") String scope,
@QueryParam("permission") Boolean permission,
@QueryParam("owner") String owner,
@QueryParam("fields") String fields,
@QueryParam("first") Integer firstResult,
@QueryParam("max") Integer maxResult) {
if (auth != null) {
@ -253,18 +254,18 @@ public class PolicyService {
}
return Response.ok(
doSearch(firstResult, maxResult, search))
doSearch(firstResult, maxResult, fields, search))
.build();
}
protected AbstractPolicyRepresentation toRepresentation(Policy model, AuthorizationProvider authorization) {
return ModelToRepresentation.toRepresentation(model, authorization, true, false);
protected AbstractPolicyRepresentation toRepresentation(Policy model, String fields, AuthorizationProvider authorization) {
return ModelToRepresentation.toRepresentation(model, authorization, true, false, fields != null && fields.equals("*"));
}
protected List<Object> doSearch(Integer firstResult, Integer maxResult, Map<String, String[]> filters) {
protected List<Object> doSearch(Integer firstResult, Integer maxResult, String fields, Map<String, String[]> filters) {
PolicyStore policyStore = authorization.getStoreFactory().getPolicyStore();
return policyStore.findByResourceServer(filters, resourceServer.getId(), firstResult != null ? firstResult : -1, maxResult != null ? maxResult : Constants.DEFAULT_MAX_RESULTS).stream()
.map(policy -> toRepresentation(policy, authorization))
.map(policy -> toRepresentation(policy, fields, authorization))
.collect(Collectors.toList());
}

View file

@ -58,8 +58,7 @@ public class PolicyTypeResourceService extends PolicyResourceService {
return representation;
}
@Override
protected AbstractPolicyRepresentation toRepresentation(Policy policy, AuthorizationProvider authorization) {
return ModelToRepresentation.toRepresentation(policy, authorization, false, false);
protected AbstractPolicyRepresentation toRepresentation(Policy policy, String fields, AuthorizationProvider authorization) {
return ModelToRepresentation.toRepresentation(policy, authorization, false, false, fields != null && fields.equals("*"));
}
}

View file

@ -87,13 +87,13 @@ public class PolicyTypeService extends PolicyService {
}
@Override
protected AbstractPolicyRepresentation toRepresentation(Policy policy, AuthorizationProvider authorization) {
protected AbstractPolicyRepresentation toRepresentation(Policy policy, String fields, AuthorizationProvider authorization) {
return ModelToRepresentation.toRepresentation(policy, authorization, false, false);
}
@Override
protected List<Object> doSearch(Integer firstResult, Integer maxResult, Map<String, String[]> filters) {
protected List<Object> doSearch(Integer firstResult, Integer maxResult, String fields, Map<String, String[]> filters) {
filters.put("type", new String[] {type});
return super.doSearch(firstResult, maxResult, filters);
return super.doSearch(firstResult, maxResult, fields, filters);
}
}

View file

@ -117,7 +117,7 @@ public class UserManagedPermissionService {
@Produces("application/json")
public Response findById(@PathParam("policyId") String policyId) {
checkRequest(getAssociatedResourceId(policyId), null);
return PolicyTypeResourceService.class.cast(delegate.getResource(policyId)).findById();
return PolicyTypeResourceService.class.cast(delegate.getResource(policyId)).findById(null);
}
@GET
@ -128,7 +128,7 @@ public class UserManagedPermissionService {
@QueryParam("scope") String scope,
@QueryParam("first") Integer firstResult,
@QueryParam("max") Integer maxResult) {
return delegate.findAll(null, name, "uma", resource, scope, true, identity.getId(), firstResult, maxResult);
return delegate.findAll(null, name, "uma", resource, scope, true, identity.getId(), null, firstResult, maxResult);
}
private Policy getPolicy(@PathParam("policyId") String policyId) {

View file

@ -18,17 +18,18 @@
package org.keycloak.testsuite.admin.client.authorization;
import org.junit.Test;
import org.keycloak.admin.client.resource.AuthorizationResource;
import org.keycloak.admin.client.resource.PoliciesResource;
import org.keycloak.admin.client.resource.PolicyResource;
import org.keycloak.admin.client.resource.ResourceResource;
import org.keycloak.admin.client.resource.ResourceScopeResource;
import org.keycloak.admin.client.resource.ResourceScopesResource;
import org.keycloak.admin.client.resource.ResourcesResource;
import org.keycloak.common.Profile;
import org.keycloak.representations.idm.authorization.DecisionStrategy;
import org.keycloak.representations.idm.authorization.Logic;
import org.keycloak.representations.idm.authorization.PolicyProviderRepresentation;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
@ -38,6 +39,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -147,6 +149,41 @@ public class GenericPolicyManagementTest extends AbstractAuthorizationTest {
assertTrue(providers.containsAll(expected));
}
@Test
public void testQueryPolicyByIdAllFields() {
PolicyResource policy = createTestingPolicy();
PolicyRepresentation representation = policy.toRepresentation("*");
Set<ResourceRepresentation> resources = representation.getResourcesData();
assertEquals(3, resources.size());
representation = policy.toRepresentation();
assertNull(representation.getResourcesData());
}
@Test
public void testQueryPolicyAllFields() {
AuthorizationResource authorization = getClientResource().authorization();
authorization.resources().create(new ResourceRepresentation("Resource A"));
ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
permission.setName("Permission A");
permission.addResource("Resource A");
authorization.permissions().resource().create(permission);
List<PolicyRepresentation> policies = authorization.policies()
.policies(null, "Permission A", null, null, null, true, null, "*", -1, -1);
assertEquals(1, policies.size());
assertEquals(1, policies.get(0).getResourcesData().size());
policies = authorization.policies()
.policies(null, "Permission A", null, null, null, true, null, null, -1, -1);
assertEquals(1, policies.size());
assertNull(policies.get(0).getResourcesData());
}
private PolicyResource createTestingPolicy() {
Map<String, String> config = new HashMap<>();