Merge pull request #4078 from pedroigor/KEYCLOAK-3135

[KEYCLOAK-3135] - Rules UI Tests
This commit is contained in:
Pedro Igor 2017-04-25 18:04:09 -03:00 committed by GitHub
commit 0ccb98a81f
24 changed files with 964 additions and 51 deletions

View file

@ -23,9 +23,7 @@ import java.util.List;
import org.keycloak.Config;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.policy.provider.PolicyProvider;
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
@ -74,6 +72,16 @@ public class AggregatePolicyProviderFactory implements PolicyProviderFactory<Agg
verifyCircularReference(policy, new ArrayList<>());
}
@Override
public AggregatePolicyRepresentation toRepresentation(Policy policy, AggregatePolicyRepresentation representation) {
return representation;
}
@Override
public Class<AggregatePolicyRepresentation> getRepresentationType() {
return AggregatePolicyRepresentation.class;
}
private void verifyCircularReference(Policy policy, List<String> ids) {
if (!policy.getType().equals("aggregate")) {
return;

View file

@ -17,13 +17,14 @@
package org.keycloak.authorization.policy.provider.drools;
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.representations.idm.authorization.RulePolicyRepresentation;
import org.kie.api.runtime.KieContainer;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
@ -39,24 +40,24 @@ public class DroolsPolicyAdminResource implements PolicyProviderAdminService {
@Path("/resolveModules")
@POST
@Consumes("application/json")
@Consumes(MediaType.APPLICATION_JSON)
@Produces("application/json")
public Response resolveModules(PolicyRepresentation policy) {
public Response resolveModules(RulePolicyRepresentation policy) {
return Response.ok(getContainer(policy).getKieBaseNames()).build();
}
@Path("/resolveSessions")
@POST
@Consumes("application/json")
@Produces("application/json")
public Response resolveSessions(PolicyRepresentation policy) {
return Response.ok(getContainer(policy).getKieSessionNamesInKieBase(policy.getConfig().get("moduleName"))).build();
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response resolveSessions(RulePolicyRepresentation policy) {
return Response.ok(getContainer(policy).getKieSessionNamesInKieBase(policy.getModuleName())).build();
}
private KieContainer getContainer(PolicyRepresentation policy) {
String groupId = policy.getConfig().get("mavenArtifactGroupId");
String artifactId = policy.getConfig().get("mavenArtifactId");
String version = policy.getConfig().get("mavenArtifactVersion");
private KieContainer getContainer(RulePolicyRepresentation policy) {
String groupId = policy.getArtifactGroupId();
String artifactId = policy.getArtifactId();
String version = policy.getArtifactVersion();
return this.factory.getKieContainer(groupId, artifactId, version);
}
}

View file

@ -13,8 +13,8 @@ import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.representations.idm.authorization.RulePolicyRepresentation;
import org.kie.api.KieServices;
import org.kie.api.KieServices.Factory;
import org.kie.api.runtime.KieContainer;
@ -22,7 +22,7 @@ import org.kie.api.runtime.KieContainer;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class DroolsPolicyProviderFactory implements PolicyProviderFactory {
public class DroolsPolicyProviderFactory implements PolicyProviderFactory<RulePolicyRepresentation> {
private KieServices ks;
private final Map<String, DroolsPolicy> containers = Collections.synchronizedMap(new HashMap<>());
@ -61,12 +61,14 @@ public class DroolsPolicyProviderFactory implements PolicyProviderFactory {
}
@Override
public void onCreate(Policy policy, AbstractPolicyRepresentation representation, AuthorizationProvider authorization) {
public void onCreate(Policy policy, RulePolicyRepresentation representation, AuthorizationProvider authorization) {
updateConfig(policy, representation);
update(policy);
}
@Override
public void onUpdate(Policy policy, AbstractPolicyRepresentation representation, AuthorizationProvider authorization) {
public void onUpdate(Policy policy, RulePolicyRepresentation representation, AuthorizationProvider authorization) {
updateConfig(policy, representation);
update(policy);
}
@ -80,6 +82,23 @@ public class DroolsPolicyProviderFactory implements PolicyProviderFactory {
remove(policy);
}
@Override
public RulePolicyRepresentation toRepresentation(Policy policy, RulePolicyRepresentation representation) {
representation.setArtifactGroupId(policy.getConfig().get("mavenArtifactGroupId"));
representation.setArtifactId(policy.getConfig().get("mavenArtifactId"));
representation.setArtifactVersion(policy.getConfig().get("mavenArtifactVersion"));
representation.setScannerPeriod(policy.getConfig().get("scannerPeriod"));
representation.setScannerPeriodUnit(policy.getConfig().get("scannerPeriodUnit"));
representation.setSessionName(policy.getConfig().get("sessionName"));
representation.setModuleName(policy.getConfig().get("moduleName"));
return representation;
}
@Override
public Class<RulePolicyRepresentation> getRepresentationType() {
return RulePolicyRepresentation.class;
}
@Override
public void init(Config.Scope config) {
this.ks = Factory.get();
@ -100,6 +119,20 @@ public class DroolsPolicyProviderFactory implements PolicyProviderFactory {
return "rules";
}
private void updateConfig(Policy policy, RulePolicyRepresentation representation) {
Map<String, String> config = policy.getConfig();
config.put("mavenArtifactGroupId", representation.getArtifactGroupId());
config.put("mavenArtifactId", representation.getArtifactId());
config.put("mavenArtifactVersion", representation.getArtifactVersion());
config.put("scannerPeriod", representation.getScannerPeriod());
config.put("scannerPeriodUnit", representation.getScannerPeriodUnit());
config.put("sessionName", representation.getSessionName());
config.put("moduleName", representation.getModuleName());
policy.setConfig(config);
}
void update(Policy policy) {
remove(policy);
this.containers.put(policy.getId(), new DroolsPolicy(this.ks, policy));

View file

@ -0,0 +1,92 @@
/*
* 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.representations.idm.authorization;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class RulePolicyRepresentation extends AbstractPolicyRepresentation {
private String artifactGroupId;
private String artifactId;
private String artifactVersion;
private String moduleName;
private String sessionName;
private String scannerPeriod;
private String scannerPeriodUnit;
@Override
public String getType() {
return "rules";
}
public String getArtifactGroupId() {
return artifactGroupId;
}
public void setArtifactGroupId(String artifactGroupId) {
this.artifactGroupId = artifactGroupId;
}
public String getArtifactId() {
return artifactId;
}
public void setArtifactId(String artifactId) {
this.artifactId = artifactId;
}
public String getArtifactVersion() {
return artifactVersion;
}
public void setArtifactVersion(String artifactVersion) {
this.artifactVersion = artifactVersion;
}
public String getModuleName() {
return moduleName;
}
public void setModuleName(String moduleName) {
this.moduleName = moduleName;
}
public String getSessionName() {
return sessionName;
}
public void setSessionName(String sessionName) {
this.sessionName = sessionName;
}
public String getScannerPeriod() {
return scannerPeriod;
}
public void setScannerPeriod(String scannerPeriod) {
this.scannerPeriod = scannerPeriod;
}
public String getScannerPeriodUnit() {
return scannerPeriodUnit;
}
public void setScannerPeriodUnit(String scannerPeriodUnit) {
this.scannerPeriodUnit = scannerPeriodUnit;
}
}

View file

@ -0,0 +1,50 @@
/*
* 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.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.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface AggregatePoliciesResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
Response create(AggregatePolicyRepresentation representation);
@Path("{id}")
AggregatePolicyResource findById(@PathParam("id") String id);
@Path("/search")
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
AggregatePolicyRepresentation findByName(@QueryParam("name") String name);
}

View file

@ -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.AggregatePolicyRepresentation;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface AggregatePolicyResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
AggregatePolicyRepresentation toRepresentation();
@PUT
@Consumes(MediaType.APPLICATION_JSON)
void update(AggregatePolicyRepresentation 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();
}

View file

@ -80,4 +80,10 @@ public interface PoliciesResource {
@Path("time")
TimePoliciesResource time();
@Path("aggregate")
AggregatePoliciesResource aggregate();
@Path("rules")
RulePoliciesResource rule();
}

View file

@ -0,0 +1,50 @@
/*
* 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.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.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.representations.idm.authorization.RulePolicyRepresentation;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface RulePoliciesResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
Response create(RulePolicyRepresentation representation);
@Path("{id}")
RulePolicyResource findById(@PathParam("id") String id);
@Path("/search")
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
RulePolicyRepresentation findByName(@QueryParam("name") String name);
}

View file

@ -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.RulePolicyRepresentation;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface RulePolicyResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
RulePolicyRepresentation toRepresentation();
@PUT
@Consumes(MediaType.APPLICATION_JSON)
void update(RulePolicyRepresentation 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();
}

View file

@ -47,7 +47,7 @@ import org.keycloak.testsuite.util.UserBuilder;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public abstract class AbstractPermissionManagementTest extends AbstractKeycloakTest {
public abstract class AbstractPolicyManagementTest extends AbstractKeycloakTest {
@Override
public void addTestRealms(List<RealmRepresentation> testRealms) {

View file

@ -0,0 +1,116 @@
/*
* 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.fail;
import java.util.Collections;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.Response;
import org.junit.Test;
import org.keycloak.admin.client.resource.AggregatePoliciesResource;
import org.keycloak.admin.client.resource.AggregatePolicyResource;
import org.keycloak.admin.client.resource.AuthorizationResource;
import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation;
import org.keycloak.representations.idm.authorization.DecisionStrategy;
import org.keycloak.representations.idm.authorization.Logic;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class AggregatePolicyManagementTest extends AbstractPolicyManagementTest {
@Test
public void testCreate() {
AuthorizationResource authorization = getClient().authorization();
AggregatePolicyRepresentation representation = new AggregatePolicyRepresentation();
representation.setName("Aggregate Policy");
representation.setDescription("description");
representation.setDecisionStrategy(DecisionStrategy.CONSENSUS);
representation.setLogic(Logic.NEGATIVE);
representation.addPolicy("Only Marta Policy", "Only Kolo Policy");
assertCreated(authorization, representation);
}
@Test
public void testUpdate() {
AuthorizationResource authorization = getClient().authorization();
AggregatePolicyRepresentation representation = new AggregatePolicyRepresentation();
representation.setName("Update Aggregate Policy");
representation.setDescription("description");
representation.setDecisionStrategy(DecisionStrategy.CONSENSUS);
representation.setLogic(Logic.NEGATIVE);
representation.addPolicy("Only Marta Policy", "Only Kolo Policy");
assertCreated(authorization, representation);
representation.setName("changed");
representation.setDescription("changed");
representation.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
representation.setLogic(Logic.POSITIVE);
representation.getPolicies().clear();
representation.addPolicy("Only Kolo Policy");
AggregatePoliciesResource policies = authorization.policies().aggregate();
AggregatePolicyResource policy = policies.findById(representation.getId());
policy.update(representation);
assertRepresentation(representation, policy);
}
@Test
public void testDelete() {
AuthorizationResource authorization = getClient().authorization();
AggregatePolicyRepresentation representation = new AggregatePolicyRepresentation();
representation.setName("Test Delete Policy");
representation.addPolicy("Only Marta Policy");
AggregatePoliciesResource policies = authorization.policies().aggregate();
Response response = policies.create(representation);
AggregatePolicyRepresentation created = response.readEntity(AggregatePolicyRepresentation.class);
policies.findById(created.getId()).remove();
AggregatePolicyResource removed = policies.findById(created.getId());
try {
removed.toRepresentation();
fail("Policy not removed");
} catch (NotFoundException ignore) {
}
}
private void assertCreated(AuthorizationResource authorization, AggregatePolicyRepresentation representation) {
AggregatePoliciesResource permissions = authorization.policies().aggregate();
Response response = permissions.create(representation);
AggregatePolicyRepresentation created = response.readEntity(AggregatePolicyRepresentation.class);
AggregatePolicyResource permission = permissions.findById(created.getId());
assertRepresentation(representation, permission);
}
private void assertRepresentation(AggregatePolicyRepresentation representation, AggregatePolicyResource policy) {
AggregatePolicyRepresentation actual = policy.toRepresentation();
assertRepresentation(representation, actual, () -> policy.resources(), () -> Collections.emptyList(), () -> policy.associatedPolicies());
}
}

View file

@ -35,7 +35,7 @@ import org.keycloak.representations.idm.authorization.Logic;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class JSPolicyManagementTest extends AbstractPermissionManagementTest {
public class JSPolicyManagementTest extends AbstractPolicyManagementTest {
@Test
public void testCreate() {

View file

@ -35,7 +35,7 @@ import org.keycloak.representations.idm.authorization.ResourcePermissionRepresen
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class ResourcePermissionManagementTest extends AbstractPermissionManagementTest {
public class ResourcePermissionManagementTest extends AbstractPolicyManagementTest {
@Test
public void testCreateResourcePermission() {

View file

@ -24,7 +24,6 @@ import static org.junit.Assert.fail;
import java.util.Collections;
import java.util.stream.Collectors;
import javax.management.relation.Role;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.Response;
@ -47,7 +46,7 @@ import org.keycloak.testsuite.util.RolesBuilder;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class RolePolicyManagementTest extends AbstractPermissionManagementTest {
public class RolePolicyManagementTest extends AbstractPolicyManagementTest {
@Override
protected RealmBuilder createTestRealm() {

View file

@ -0,0 +1,131 @@
/*
* 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.fail;
import java.util.Collections;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.Response;
import org.junit.Test;
import org.keycloak.admin.client.resource.AuthorizationResource;
import org.keycloak.admin.client.resource.RulePoliciesResource;
import org.keycloak.admin.client.resource.RulePolicyResource;
import org.keycloak.common.Version;
import org.keycloak.representations.idm.authorization.DecisionStrategy;
import org.keycloak.representations.idm.authorization.Logic;
import org.keycloak.representations.idm.authorization.RulePolicyRepresentation;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class RulesPolicyManagementTest extends AbstractPolicyManagementTest {
@Test
public void testCreate() {
assertCreated(getClient().authorization(), createDefaultRepresentation("Rule Policy"));
}
@Test
public void testUpdate() {
AuthorizationResource authorization = getClient().authorization();
RulePolicyRepresentation representation = createDefaultRepresentation("Update Rule Policy");
assertCreated(authorization, representation);
representation.setName("changed");
representation.setDescription("changed");
representation.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
representation.setLogic(Logic.POSITIVE);
representation.setScannerPeriod("12");
representation.setScannerPeriodUnit("Days");
representation.setModuleName("PhotozAuthzContextualPolicy");
representation.setSessionName("MainContextualSession");
RulePoliciesResource policies = authorization.policies().rule();
RulePolicyResource policy = policies.findById(representation.getId());
policy.update(representation);
assertRepresentation(representation, policy);
}
@Test
public void testDelete() {
AuthorizationResource authorization = getClient().authorization();
RulePolicyRepresentation representation = createDefaultRepresentation("Delete Rule Policy");
RulePoliciesResource policies = authorization.policies().rule();
Response response = policies.create(representation);
RulePolicyRepresentation created = response.readEntity(RulePolicyRepresentation.class);
policies.findById(created.getId()).remove();
RulePolicyResource removed = policies.findById(created.getId());
try {
removed.toRepresentation();
fail("Policy not removed");
} catch (NotFoundException ignore) {
}
}
private RulePolicyRepresentation createDefaultRepresentation(String name) {
RulePolicyRepresentation representation = new RulePolicyRepresentation();
representation.setName(name);
representation.setDescription("description");
representation.setDecisionStrategy(DecisionStrategy.CONSENSUS);
representation.setLogic(Logic.NEGATIVE);
representation.setArtifactGroupId("org.keycloak");
representation.setArtifactId("photoz-authz-policy");
representation.setArtifactVersion(Version.VERSION);
representation.setModuleName("PhotozAuthzOwnerPolicy");
representation.setSessionName("MainOwnerSession");
representation.setScannerPeriod("1");
representation.setScannerPeriodUnit("Minutes");
return representation;
}
private void assertCreated(AuthorizationResource authorization, RulePolicyRepresentation representation) {
RulePoliciesResource permissions = authorization.policies().rule();
Response response = permissions.create(representation);
RulePolicyRepresentation created = response.readEntity(RulePolicyRepresentation.class);
RulePolicyResource permission = permissions.findById(created.getId());
assertRepresentation(representation, permission);
}
private void assertRepresentation(RulePolicyRepresentation expected, RulePolicyResource policy) {
RulePolicyRepresentation actual = policy.toRepresentation();
assertRepresentation(expected, actual, () -> policy.resources(), () -> Collections.emptyList(), () -> policy.associatedPolicies());
assertEquals(expected.getName(), actual.getName());
assertEquals(expected.getDescription(), actual.getDescription());
assertEquals(expected.getLogic(), actual.getLogic());
assertEquals(expected.getArtifactGroupId(), actual.getArtifactGroupId());
assertEquals(expected.getArtifactId(), actual.getArtifactId());
assertEquals(expected.getArtifactVersion(), actual.getArtifactVersion());
assertEquals(expected.getModuleName(), actual.getModuleName());
assertEquals(expected.getSessionName(), actual.getSessionName());
assertEquals(expected.getScannerPeriod(), actual.getScannerPeriod());
assertEquals(expected.getScannerPeriodUnit(), actual.getScannerPeriodUnit());
}
}

View file

@ -33,7 +33,7 @@ import org.keycloak.representations.idm.authorization.ScopePermissionRepresentat
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class ScopePermissionManagementTest extends AbstractPermissionManagementTest {
public class ScopePermissionManagementTest extends AbstractPolicyManagementTest {
@Test
public void testCreateResourceScopePermission() {

View file

@ -35,7 +35,7 @@ import org.keycloak.representations.idm.authorization.Logic;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class TimePolicyManagementTest extends AbstractPermissionManagementTest {
public class TimePolicyManagementTest extends AbstractPolicyManagementTest {
@Test
public void testCreate() {

View file

@ -43,7 +43,7 @@ import org.keycloak.testsuite.util.UserBuilder;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class UserPolicyManagementTest extends AbstractPermissionManagementTest {
public class UserPolicyManagementTest extends AbstractPolicyManagementTest {
@Override
protected RealmBuilder createTestRealm() {

View file

@ -24,6 +24,7 @@ import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentat
import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
import org.keycloak.representations.idm.authorization.RulePolicyRepresentation;
import org.keycloak.representations.idm.authorization.TimePolicyRepresentation;
import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
import org.keycloak.testsuite.page.Form;
@ -58,6 +59,9 @@ public class Policies extends Form {
@Page
private TimePolicy timePolicy;
@Page
private RulePolicy rulePolicy;
public PoliciesTable policies() {
return table;
}
@ -87,6 +91,10 @@ public class Policies extends Form {
timePolicy.form().populate((TimePolicyRepresentation) expected);
timePolicy.form().save();
return (P) timePolicy;
} else if ("rules".equals(type)) {
rulePolicy.form().populate((RulePolicyRepresentation) expected);
rulePolicy.form().save();
return (P) rulePolicy;
}
return null;
@ -110,6 +118,8 @@ public class Policies extends Form {
jsPolicy.form().populate((JSPolicyRepresentation) representation);
} else if ("time".equals(type)) {
timePolicy.form().populate((TimePolicyRepresentation) representation);
} else if ("rules".equals(type)) {
rulePolicy.form().populate((RulePolicyRepresentation) representation);
}
return;
@ -134,6 +144,8 @@ public class Policies extends Form {
return (P) jsPolicy;
} else if ("time".equals(type)) {
return (P) timePolicy;
} else if ("rules".equals(type)) {
return (P) rulePolicy;
}
}
}
@ -159,6 +171,8 @@ public class Policies extends Form {
jsPolicy.form().delete();
} else if ("time".equals(type)) {
timePolicy.form().delete();
} else if ("rules".equals(type)) {
rulePolicy.form().delete();
}
return;

View file

@ -0,0 +1,41 @@
/*
* 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.console.page.clients.authorization.policy;
import org.jboss.arquillian.graphene.page.Page;
import org.keycloak.representations.idm.authorization.RulePolicyRepresentation;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class RulePolicy implements PolicyTypeUI {
@Page
private RulePolicyForm form;
public RulePolicyForm form() {
return form;
}
public RulePolicyRepresentation toRepresentation() {
return form.toRepresentation();
}
public void update(RulePolicyRepresentation expected) {
form().populate(expected);
}
}

View file

@ -0,0 +1,114 @@
/*
* 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.console.page.clients.authorization.policy;
import org.keycloak.representations.idm.authorization.Logic;
import org.keycloak.representations.idm.authorization.RulePolicyRepresentation;
import org.keycloak.testsuite.page.Form;
import org.keycloak.testsuite.util.WaitUtils;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.ui.Select;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class RulePolicyForm extends Form {
@FindBy(id = "name")
private WebElement name;
@FindBy(id = "description")
private WebElement description;
@FindBy(id = "artifactGroupId")
private WebElement artifactGroupId;
@FindBy(id = "artifactId")
private WebElement artifactId;
@FindBy(id = "artifactVersion")
private WebElement artifactVersion;
@FindBy(id = "moduleName")
private Select moduleName;
@FindBy(id = "sessionName")
private Select sessionName;
@FindBy(id = "scannerPeriod")
private WebElement scannerPeriod;
@FindBy(id = "scannerPeriodUnit")
private Select scannerPeriodUnit;
@FindBy(id = "logic")
private Select logic;
@FindBy(xpath = "//i[contains(@class,'pficon-delete')]")
private WebElement deleteButton;
@FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']")
private WebElement confirmDelete;
@FindBy(id = "resolveModule")
private WebElement resolveModuleButton;
public void populate(RulePolicyRepresentation expected) {
setInputValue(name, expected.getName());
setInputValue(description, expected.getDescription());
setInputValue(artifactGroupId, expected.getArtifactGroupId());
setInputValue(artifactId, expected.getArtifactId());
setInputValue(artifactVersion, expected.getArtifactVersion());
resolveModuleButton.click();
WaitUtils.waitForPageToLoad(driver);
moduleName.selectByVisibleText(expected.getModuleName());
WaitUtils.pause(1000);
sessionName.selectByVisibleText(expected.getSessionName());
setInputValue(scannerPeriod, expected.getScannerPeriod());
scannerPeriodUnit.selectByVisibleText(expected.getScannerPeriodUnit());
logic.selectByValue(expected.getLogic().name());
save();
}
public void delete() {
deleteButton.click();
confirmDelete.click();
}
public RulePolicyRepresentation toRepresentation() {
RulePolicyRepresentation representation = new RulePolicyRepresentation();
representation.setName(getInputValue(name));
representation.setDescription(getInputValue(description));
representation.setLogic(Logic.valueOf(logic.getFirstSelectedOption().getText().toUpperCase()));
representation.setArtifactGroupId(getInputValue(artifactGroupId));
representation.setArtifactId(getInputValue(artifactId));
representation.setArtifactVersion(getInputValue(artifactVersion));
representation.setModuleName(moduleName.getFirstSelectedOption().getText());
representation.setSessionName(sessionName.getFirstSelectedOption().getText());
representation.setScannerPeriod(getInputValue(scannerPeriod));
representation.setScannerPeriodUnit(scannerPeriodUnit.getFirstSelectedOption().getText());
return representation;
}
}

View file

@ -0,0 +1,112 @@
/*
* 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.console.authorization;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.junit.Test;
import org.keycloak.common.Version;
import org.keycloak.representations.idm.authorization.Logic;
import org.keycloak.representations.idm.authorization.RulePolicyRepresentation;
import org.keycloak.testsuite.console.page.clients.authorization.policy.RulePolicy;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class RulePolicyManagementTest extends AbstractAuthorizationSettingsTest {
@Test
public void testUpdate() throws InterruptedException {
authorizationPage.navigateTo();
RulePolicyRepresentation expected = createDefaultRepresentation("Test Rule Policy");
expected = createPolicy(expected);
String previousName = expected.getName();
expected.setName("Changed " + previousName);
expected.setDescription("Changed description");
expected.setLogic(Logic.NEGATIVE);
expected.setModuleName("PhotozAuthzContextualPolicy");
expected.setSessionName("MainContextualSession");
expected.setScannerPeriod("12");
expected.setScannerPeriodUnit("Days");
authorizationPage.navigateTo();
authorizationPage.authorizationTabs().policies().update(previousName, expected);
assertAlertSuccess();
authorizationPage.navigateTo();
RulePolicy actual = authorizationPage.authorizationTabs().policies().name(expected.getName());
assertPolicy(expected, actual);
}
@Test
public void testDelete() throws InterruptedException {
authorizationPage.navigateTo();
RulePolicyRepresentation expected =createDefaultRepresentation("Delete Rule Policy");
expected = createPolicy(expected);
authorizationPage.navigateTo();
authorizationPage.authorizationTabs().policies().delete(expected.getName());
assertAlertSuccess();
authorizationPage.navigateTo();
assertNull(authorizationPage.authorizationTabs().policies().policies().findByName(expected.getName()));
}
private RulePolicyRepresentation createDefaultRepresentation(String name) {
RulePolicyRepresentation expected = new RulePolicyRepresentation();
expected.setName(name);
expected.setDescription("description");
expected.setArtifactGroupId("org.keycloak");
expected.setArtifactId("photoz-authz-policy");
expected.setArtifactVersion(Version.VERSION);
expected.setModuleName("PhotozAuthzOwnerPolicy");
expected.setSessionName("MainOwnerSession");
expected.setScannerPeriod("1");
expected.setScannerPeriodUnit("Minutes");
return expected;
}
private RulePolicyRepresentation createPolicy(RulePolicyRepresentation expected) {
RulePolicy policy = authorizationPage.authorizationTabs().policies().create(expected);
assertAlertSuccess();
return assertPolicy(expected, policy);
}
private RulePolicyRepresentation assertPolicy(RulePolicyRepresentation expected, RulePolicy policy) {
RulePolicyRepresentation actual = policy.toRepresentation();
assertEquals(expected.getName(), actual.getName());
assertEquals(expected.getDescription(), actual.getDescription());
assertEquals(expected.getLogic(), actual.getLogic());
assertEquals(expected.getArtifactGroupId(), actual.getArtifactGroupId());
assertEquals(expected.getArtifactId(), actual.getArtifactId());
assertEquals(expected.getArtifactVersion(), actual.getArtifactVersion());
assertEquals(expected.getModuleName(), actual.getModuleName());
assertEquals(expected.getSessionName(), actual.getSessionName());
assertEquals(expected.getScannerPeriod(), actual.getScannerPeriod());
assertEquals(expected.getScannerPeriodUnit(), actual.getScannerPeriodUnit());
return actual;
}
}

View file

@ -757,6 +757,8 @@ module.controller('ResourceServerPolicyDroolsDetailCtrl', function($scope, $http
policy = $scope.policy;
}
delete policy.config;
$http.post(authUrl + '/admin/realms/'+ $route.current.params.realm + '/clients/' + client.id + '/authz/resource-server/policy/rules/provider/resolveModules'
, policy).success(function(data) {
$scope.drools.moduleNames = data;
@ -765,6 +767,8 @@ module.controller('ResourceServerPolicyDroolsDetailCtrl', function($scope, $http
}
$scope.resolveSessions = function() {
delete $scope.policy.config;
$http.post(authUrl + '/admin/realms/'+ $route.current.params.realm + '/clients/' + client.id + '/authz/resource-server/policy/rules/provider/resolveSessions'
, $scope.policy).success(function(data) {
$scope.drools.moduleSessions = data;
@ -773,17 +777,21 @@ module.controller('ResourceServerPolicyDroolsDetailCtrl', function($scope, $http
},
onInitUpdate : function(policy) {
policy.config.scannerPeriod = parseInt(policy.config.scannerPeriod);
policy.scannerPeriod = parseInt(policy.scannerPeriod);
$scope.resolveModules(policy);
},
onUpdate : function() {
$scope.policy.config.resources = JSON.stringify($scope.policy.config.resources);
delete $scope.policy.config;
},
onInitCreate : function(newPolicy) {
newPolicy.config.scannerPeriod = 1;
newPolicy.config.scannerPeriodUnit = 'Hours';
newPolicy.scannerPeriod = 1;
newPolicy.scannerPeriodUnit = 'Hours';
},
onCreate : function() {
delete $scope.policy.config;
}
}, realm, client, $scope);
});

View file

@ -31,31 +31,31 @@
<kc-tooltip>{{:: 'authz-policy-description.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="policy.config.mavenArtifactGroupId">{{:: 'authz-policy-drools-maven-artifact' | translate}} <span class="required" data-ng-show="create">*</span></label>
<button data-ng-click="resolveModules()" class="btn btn-primary">{{:: 'authz-policy-drools-maven-artifact-resolve' | translate}}</button>
<label class="col-md-2 control-label" for="artifactGroupId">{{:: 'authz-policy-drools-maven-artifact' | translate}} <span class="required" data-ng-show="create">*</span></label>
<button data-ng-click="resolveModules()" id="resolveModule" class="btn btn-primary">{{:: 'authz-policy-drools-maven-artifact-resolve' | translate}}</button>
<div class="col-sm-3">
<input class="form-control" type="text" id="policy.config.mavenArtifactGroupId" name="policy.config.mavenArtifactGroupId" data-ng-model="policy.config.mavenArtifactGroupId" placeholder="Group Identifier" required>
<input class="form-control" type="text" id="artifactGroupId" name="artifactGroupId" data-ng-model="policy.artifactGroupId" placeholder="Group Identifier" required>
</div>
<kc-tooltip>{{:: 'authz-policy-drools-maven-artifact.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="policy.config.mavenArtifactId"></label>
<label class="col-md-2 control-label" for="artifactId"></label>
<div class="col-sm-3">
<input class="form-control" type="text" id="policy.config.mavenArtifactId" name="policy.config.mavenArtifactId" data-ng-model="policy.config.mavenArtifactId" autofocus placeholder="Artifact Identifier" required>
<input class="form-control" type="text" id="artifactId" name="artifactId" data-ng-model="policy.artifactId" autofocus placeholder="Artifact Identifier" required>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="policy.config.mavenArtifactVersion"></label>
<label class="col-md-2 control-label" for="artifactVersion"></label>
<div class="col-sm-3">
<input class="form-control" type="text" id="policy.config.mavenArtifactVersion" name="policy.config.mavenArtifactVersion" data-ng-model="policy.config.mavenArtifactVersion" autofocus placeholder="Version" required>
<input class="form-control" type="text" id="artifactVersion" name="artifactVersion" data-ng-model="policy.artifactVersion" autofocus placeholder="Version" required>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="policy.config.moduleName">{{:: 'authz-policy-drools-module' | translate}} <span class="required" data-ng-show="create">*</span></label>
<label class="col-md-2 control-label" for="moduleName">{{:: 'authz-policy-drools-module' | translate}} <span class="required" data-ng-show="create">*</span></label>
<div class="col-sm-3">
<div>
<select class="form-control" id="policy.config.moduleName"
ng-model="policy.config.moduleName"
<select class="form-control" id="moduleName"
ng-model="policy.moduleName"
ng-options="moduleName as moduleName for moduleName in drools.moduleNames"
ng-change="resolveSessions()"
ng-disabled="!drools.moduleNames.length"
@ -66,11 +66,11 @@
<kc-tooltip>{{:: 'authz-policy-drools-module.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="policy.config.sessionName">{{:: 'authz-policy-drools-session' | translate}} <span class="required" data-ng-show="create">*</span></label>
<label class="col-md-2 control-label" for="sessionName">{{:: 'authz-policy-drools-session' | translate}} <span class="required" data-ng-show="create">*</span></label>
<div class="col-sm-3">
<div>
<select class="form-control" id="policy.config.sessionName"
ng-model="policy.config.sessionName"
<select class="form-control" id="sessionName"
ng-model="policy.sessionName"
ng-options="sessionName as sessionName for sessionName in drools.moduleSessions"
ng-disabled="!drools.moduleSessions.length"
required>
@ -80,14 +80,14 @@
<kc-tooltip>{{:: 'authz-policy-drools-session.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="policy.config.scannerPeriod">{{:: 'authz-policy-drools-update-period' | translate}}</label>
<label class="col-md-2 control-label" for="scannerPeriod">{{:: 'authz-policy-drools-update-period' | translate}}</label>
<div class="col-md-6 time-selector">
<input class="form-control" type="number" required min="1" max="31536000" data-ng-model="policy.config.scannerPeriod" id="policy.config.scannerPeriod"
name="policy.config.scannerPeriod"
ng-disabled="!policy.config.sessionName"/>
<select class="form-control" name="policy.config.scannerPeriodUnit"
data-ng-model="policy.config.scannerPeriodUnit"
ng-disabled="!policy.config.sessionName">
<input class="form-control" type="number" required min="1" max="31536000" data-ng-model="policy.scannerPeriod" id="scannerPeriod"
name="scannerPeriod"
ng-disabled="!policy.sessionName"/>
<select class="form-control" id="scannerPeriodUnit" name="scannerPeriodUnit"
data-ng-model="policy.scannerPeriodUnit"
ng-disabled="!policy.sessionName">
<option value="Seconds">{{:: 'seconds' | translate}}</option>
<option value="Minutes">{{:: 'minutes' | translate}}</option>
<option value="Hours">{{:: 'hours' | translate}}</option>
@ -97,10 +97,10 @@
<kc-tooltip>{{:: 'authz-policy-drools-update-period.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix">
<label class="col-md-2 control-label" for="policy.logic">{{:: 'authz-policy-logic' | translate}}</label>
<label class="col-md-2 control-label" for="logic">{{:: 'authz-policy-logic' | translate}}</label>
<div class="col-sm-1">
<select class="form-control" id="policy.logic"
<select class="form-control" id="logic"
data-ng-model="policy.logic">
<option value="POSITIVE">{{:: 'authz-policy-logic-positive' | translate}}</option>
<option value="NEGATIVE">{{:: 'authz-policy-logic-negative' | translate}}</option>