keycloak-aplcache
Changes
authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyProviderFactory.java 12(+4 -8)
core/src/main/java/org/keycloak/representations/idm/authorization/AbstractPolicyRepresentation.java 8(+8 -0)
core/src/main/java/org/keycloak/representations/idm/authorization/AggregatePolicyRepresentation.java 28(+28 -0)
core/src/main/java/org/keycloak/representations/idm/authorization/JSPolicyRepresentation.java 5(+5 -0)
core/src/main/java/org/keycloak/representations/idm/authorization/RolePolicyRepresentation.java 5(+5 -0)
core/src/main/java/org/keycloak/representations/idm/authorization/TimePolicyRepresentation.java 5(+5 -0)
core/src/main/java/org/keycloak/representations/idm/authorization/UserPolicyRepresentation.java 5(+5 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/Permissions.java 82(+82 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ResourcePermission.java 43(+43 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ResourcePermissionForm.java 264(+264 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicy.java 42(+42 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicyForm.java 165(+165 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicy.java 42(+42 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicyForm.java 77(+77 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java 140(+137 -3)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/PolicyTypeUI.java 23(+23 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicy.java 41(+41 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicyForm.java 284(+284 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicy.java 41(+41 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicyForm.java 129(+129 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicy.java 41(+41 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicyForm.java 190(+190 -0)
testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AbstractAuthorizationSettingsTest.java 2(+2 -0)
testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AggregatePolicyManagementTest.java 147(+147 -0)
testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/JSPolicyManagementTest.java 93(+93 -0)
testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ResourcePermissionManagementTest.java 182(+182 -0)
testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/RolePolicyManagementTest.java 232(+232 -0)
testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/TimePolicyManagementTest.java 127(+127 -0)
testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/UserPolicyManagementTest.java 116(+116 -0)
themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html 16(+8 -8)
themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html 1(+1 -0)
themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html 8(+4 -4)
themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html 8(+4 -4)
themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-role-detail.html 8(+4 -4)
themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html 12(+6 -6)
Details
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyProviderFactory.java
index 0cfbabd..655d8d1 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyProviderFactory.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyProviderFactory.java
@@ -29,12 +29,13 @@ 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.AggregatePolicyRepresentation;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
-public class AggregatePolicyProviderFactory implements PolicyProviderFactory<PolicyRepresentation> {
+public class AggregatePolicyProviderFactory implements PolicyProviderFactory<AggregatePolicyRepresentation> {
private AggregatePolicyProvider provider = new AggregatePolicyProvider();
@@ -54,22 +55,17 @@ public class AggregatePolicyProviderFactory implements PolicyProviderFactory<Pol
}
@Override
- public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) {
- return null;
- }
-
- @Override
public PolicyProvider create(KeycloakSession session) {
return null;
}
@Override
- public void onCreate(Policy policy, PolicyRepresentation representation, AuthorizationProvider authorization) {
+ public void onCreate(Policy policy, AggregatePolicyRepresentation representation, AuthorizationProvider authorization) {
verifyCircularReference(policy, new ArrayList<>());
}
@Override
- public void onUpdate(Policy policy, PolicyRepresentation representation, AuthorizationProvider authorization) {
+ public void onUpdate(Policy policy, AggregatePolicyRepresentation representation, AuthorizationProvider authorization) {
verifyCircularReference(policy, new ArrayList<>());
}
diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/AbstractPolicyRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/AbstractPolicyRepresentation.java
index e0be800..6d19a84 100644
--- a/core/src/main/java/org/keycloak/representations/idm/authorization/AbstractPolicyRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/AbstractPolicyRepresentation.java
@@ -88,6 +88,10 @@ public class AbstractPolicyRepresentation {
return policies;
}
+ public void setPolicies(Set<String> policies) {
+ this.policies = policies;
+ }
+
public void addPolicy(String... id) {
if (this.policies == null) {
this.policies = new HashSet<>();
@@ -99,6 +103,10 @@ public class AbstractPolicyRepresentation {
return resources;
}
+ public void setResources(Set<String> resources) {
+ this.resources = resources;
+ }
+
public void addResource(String id) {
if (this.resources == null) {
this.resources = new HashSet<>();
diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/AggregatePolicyRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/AggregatePolicyRepresentation.java
new file mode 100644
index 0000000..6ac1238
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/AggregatePolicyRepresentation.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.representations.idm.authorization;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class AggregatePolicyRepresentation extends AbstractPolicyRepresentation {
+
+ @Override
+ public String getType() {
+ return "aggregate";
+ }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/JSPolicyRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/JSPolicyRepresentation.java
index ed37a6d..1321792 100644
--- a/core/src/main/java/org/keycloak/representations/idm/authorization/JSPolicyRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/JSPolicyRepresentation.java
@@ -23,6 +23,11 @@ public class JSPolicyRepresentation extends AbstractPolicyRepresentation {
private String code;
+ @Override
+ public String getType() {
+ return "js";
+ }
+
public String getCode() {
return code;
}
diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/RolePolicyRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/RolePolicyRepresentation.java
index 2a89710..a4f2973 100644
--- a/core/src/main/java/org/keycloak/representations/idm/authorization/RolePolicyRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/RolePolicyRepresentation.java
@@ -26,6 +26,11 @@ public class RolePolicyRepresentation extends AbstractPolicyRepresentation {
private Set<RoleDefinition> roles;
+ @Override
+ public String getType() {
+ return "role";
+ }
+
public Set<RoleDefinition> getRoles() {
return roles;
}
diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/TimePolicyRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/TimePolicyRepresentation.java
index e4115e1..8b8e66a 100644
--- a/core/src/main/java/org/keycloak/representations/idm/authorization/TimePolicyRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/TimePolicyRepresentation.java
@@ -34,6 +34,11 @@ public class TimePolicyRepresentation extends AbstractPolicyRepresentation {
private String minute;
private String minuteEnd;
+ @Override
+ public String getType() {
+ return "time";
+ }
+
public String getNotBefore() {
return notBefore;
}
diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/UserPolicyRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/UserPolicyRepresentation.java
index dc38e65..239e55f 100644
--- a/core/src/main/java/org/keycloak/representations/idm/authorization/UserPolicyRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/UserPolicyRepresentation.java
@@ -26,6 +26,11 @@ public class UserPolicyRepresentation extends AbstractPolicyRepresentation {
private Set<String> users;
+ @Override
+ public String getType() {
+ return "user";
+ }
+
public Set<String> getUsers() {
return users;
}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/Permissions.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/Permissions.java
index c29ab76..9900247 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/Permissions.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/Permissions.java
@@ -16,8 +16,18 @@
*/
package org.keycloak.testsuite.console.page.clients.authorization.permission;
+import static org.openqa.selenium.By.tagName;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.PolicyTypeUI;
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>
@@ -27,7 +37,79 @@ public class Permissions extends Form {
@FindBy(css = "table[class*='table']")
private PermissionsTable table;
+ @FindBy(id = "create-permission")
+ private Select createSelect;
+
+ @Page
+ private ResourcePermission resourcePermission;
+
public PermissionsTable permissions() {
return table;
}
+
+ public <P extends PolicyTypeUI> P create(AbstractPolicyRepresentation expected) {
+ String type = expected.getType();
+
+ createSelect.selectByValue(type);
+
+ if ("resource".equals(type)) {
+ resourcePermission.form().populate((ResourcePermissionRepresentation) expected);
+ resourcePermission.form().save();
+ return (P) resourcePermission;
+ } else if ("scope".equals(type)) {
+ return null;
+ }
+
+ return null;
+ }
+
+ public void update(String name, AbstractPolicyRepresentation representation) {
+ for (WebElement row : permissions().rows()) {
+ PolicyRepresentation actual = permissions().toRepresentation(row);
+ if (actual.getName().equalsIgnoreCase(name)) {
+ row.findElements(tagName("a")).get(0).click();
+ WaitUtils.waitForPageToLoad(driver);
+ String type = representation.getType();
+
+ if ("resource".equals(type)) {
+ resourcePermission.form().populate((ResourcePermissionRepresentation) representation);
+ }
+
+ return;
+ }
+ }
+ }
+
+ public <P extends PolicyTypeUI> P name(String name) {
+ for (WebElement row : permissions().rows()) {
+ PolicyRepresentation actual = permissions().toRepresentation(row);
+ if (actual.getName().equalsIgnoreCase(name)) {
+ row.findElements(tagName("a")).get(0).click();
+ WaitUtils.waitForPageToLoad(driver);
+ String type = actual.getType();
+ if ("resource".equals(type)) {
+ return (P) resourcePermission;
+ }
+ }
+ }
+ return null;
+ }
+
+ public void delete(String name) {
+ for (WebElement row : permissions().rows()) {
+ PolicyRepresentation actual = permissions().toRepresentation(row);
+ if (actual.getName().equalsIgnoreCase(name)) {
+ row.findElements(tagName("a")).get(0).click();
+ WaitUtils.waitForPageToLoad(driver);
+
+ String type = actual.getType();
+
+ if ("resource".equals(type)) {
+ resourcePermission.form().delete();
+ }
+
+ return;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ResourcePermission.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ResourcePermission.java
new file mode 100644
index 0000000..d6c4f3a
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ResourcePermission.java
@@ -0,0 +1,43 @@
+/*
+ * 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.permission;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.PolicyTypeUI;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ResourcePermission implements PolicyTypeUI {
+
+ @Page
+ private ResourcePermissionForm form;
+
+ public ResourcePermissionForm form() {
+ return form;
+ }
+
+ public ResourcePermissionRepresentation toRepresentation() {
+ return form.toRepresentation();
+ }
+
+ public void update(ResourcePermissionRepresentation expected) {
+ form().populate(expected);
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ResourcePermissionForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ResourcePermissionForm.java
new file mode 100644
index 0000000..87facb3
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ResourcePermissionForm.java
@@ -0,0 +1,264 @@
+/*
+ * 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.permission;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.jboss.arquillian.graphene.fragment.Root;
+import org.keycloak.representations.idm.authorization.DecisionStrategy;
+import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
+import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
+import org.keycloak.testsuite.page.Form;
+import org.keycloak.testsuite.util.WaitUtils;
+import org.openqa.selenium.By;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+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 ResourcePermissionForm extends Form {
+
+ @FindBy(id = "name")
+ private WebElement name;
+
+ @FindBy(id = "description")
+ private WebElement description;
+
+ @FindBy(id = "decisionStrategy")
+ private Select decisionStrategy;
+
+ @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='applyToResourceTypeFlag']]")
+ private OnOffSwitch resourceTypeSwitch;
+
+ @FindBy(id = "resourceType")
+ private WebElement resourceType;
+
+ @FindBy(xpath = "//i[contains(@class,'pficon-delete')]")
+ private WebElement deleteButton;
+
+ @FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']")
+ private WebElement confirmDelete;
+
+ @FindBy(id = "s2id_policies")
+ private PolicyInput policyInput;
+
+ @FindBy(id = "s2id_resources")
+ private ResourceInput resourceInput;
+
+ public void populate(ResourcePermissionRepresentation expected) {
+ setInputValue(name, expected.getName());
+ setInputValue(description, expected.getDescription());
+ decisionStrategy.selectByValue(expected.getDecisionStrategy().name());
+
+ resourceTypeSwitch.setOn(expected.getResourceType() != null);
+
+ if (expected.getResourceType() != null) {
+ setInputValue(resourceType, expected.getResourceType());
+ } else {
+ resourceTypeSwitch.setOn(false);
+ Set<String> selectedResources = resourceInput.getSelected();
+ Set<String> resources = expected.getResources();
+
+ for (String resource : resources) {
+ if (!selectedResources.contains(resource)) {
+ resourceInput.select(resource);
+ }
+ }
+
+ for (String selected : selectedResources) {
+ boolean isSelected = false;
+
+ for (String resource : resources) {
+ if (selected.equals(resource)) {
+ isSelected = true;
+ break;
+ }
+ }
+
+ if (!isSelected) {
+ resourceInput.unSelect(selected, driver);
+ }
+ }
+ }
+
+ Set<String> selectedPolicies = policyInput.getSelected();
+ Set<String> policies = expected.getPolicies();
+
+ for (String policy : policies) {
+ if (!selectedPolicies.contains(policy)) {
+ policyInput.select(policy, driver);
+ }
+ }
+
+ for (String selected : selectedPolicies) {
+ boolean isSelected = false;
+
+ for (String policy : policies) {
+ if (selected.equals(policy)) {
+ isSelected = true;
+ break;
+ }
+ }
+
+ if (!isSelected) {
+ policyInput.unSelect(selected, driver);
+ }
+ }
+
+ WaitUtils.pause(1000);
+
+ save();
+ }
+
+ public void delete() {
+ deleteButton.click();
+ confirmDelete.click();
+ }
+
+ public ResourcePermissionRepresentation toRepresentation() {
+ ResourcePermissionRepresentation representation = new ResourcePermissionRepresentation();
+
+ representation.setName(getInputValue(name));
+ representation.setDescription(getInputValue(description));
+ representation.setDecisionStrategy(DecisionStrategy.valueOf(decisionStrategy.getFirstSelectedOption().getText().toUpperCase()));
+ representation.setPolicies(policyInput.getSelected());
+ representation.setResources(resourceInput.getSelected());
+
+ return representation;
+ }
+
+ public class PolicyInput {
+
+ @Root
+ private WebElement root;
+
+ @FindBy(xpath = "//input[contains(@class,'select2-input')]")
+ private WebElement search;
+
+ @FindBy(xpath = "//div[contains(@class,'select2-result-label')]")
+ private List<WebElement> result;
+
+ @FindBy(xpath = "//li[contains(@class,'select2-search-choice')]")
+ private List<WebElement> selection;
+
+ public void select(String name, WebDriver driver) {
+ root.click();
+ WaitUtils.pause(1000);
+
+ Actions actions = new Actions(driver);
+
+ actions.sendKeys(name).perform();
+ WaitUtils.pause(1000);
+
+ if (result.isEmpty()) {
+ actions.sendKeys(Keys.ESCAPE).perform();
+ return;
+ }
+ for (WebElement result : result) {
+ if (result.getText().equalsIgnoreCase(name)) {
+ result.click();
+ return;
+ }
+ }
+ }
+
+ public Set<String> getSelected() {
+ HashSet<String> values = new HashSet<>();
+
+ for (WebElement selected : selection) {
+ values.add(selected.findElements(By.tagName("div")).get(0).getText());
+ }
+
+ return values;
+ }
+
+ public void unSelect(String name, WebDriver driver) {
+ for (WebElement selected : selection) {
+ WebElement selection = selected.findElements(By.tagName("div")).get(0);
+ if (name.equals(selection.getText())) {
+ WebElement element = selection.findElement(By.xpath("//a[contains(@class,'select2-search-choice-close')]"));
+ JavascriptExecutor executor = (JavascriptExecutor) driver;
+ executor.executeScript("arguments[0].click();", element);
+ WaitUtils.pause(1000);
+ return;
+ }
+ }
+ }
+ }
+
+ public class ResourceInput {
+
+ @Root
+ private WebElement root;
+
+ @FindBy(xpath = "//input[contains(@class,'select2-input')]")
+ private WebElement search;
+
+ @FindBy(xpath = "//div[contains(@class,'select2-result-label')]")
+ private List<WebElement> result;
+
+ @FindBy(xpath = "//li[contains(@class,'select2-search-choice')]")
+ private List<WebElement> selection;
+
+ public void select(String name) {
+ root.click();
+ WaitUtils.pause(1000);
+ setInputValue(search, name);
+ WaitUtils.pause(1000);
+ if (result.isEmpty()) {
+ search.sendKeys(Keys.ESCAPE);
+ return;
+ }
+ for (WebElement result : result) {
+ if (result.getText().equalsIgnoreCase(name)) {
+ result.click();
+ return;
+ }
+ }
+ }
+
+ public Set<String> getSelected() {
+ HashSet<String> values = new HashSet<>();
+
+ for (WebElement selected : selection) {
+ values.add(selected.findElements(By.tagName("div")).get(0).getText());
+ }
+
+ return values;
+ }
+
+ public void unSelect(String name, WebDriver driver) {
+ for (WebElement selected : selection) {
+ if (name.equals(selected.findElements(By.tagName("div")).get(0).getText())) {
+ WebElement element = selected.findElement(By.xpath("//a[contains(@class,'select2-search-choice-close')]"));
+ JavascriptExecutor executor = (JavascriptExecutor) driver;
+ executor.executeScript("arguments[0].click();", element);
+ WaitUtils.pause(1000);
+ return;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicy.java
new file mode 100644
index 0000000..3a27d2b
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicy.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.testsuite.console.page.clients.authorization.policy;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class AggregatePolicy implements PolicyTypeUI {
+
+ @Page
+ private AggregatePolicyForm form;
+
+ public AggregatePolicyForm form() {
+ return form;
+ }
+
+ public AggregatePolicyRepresentation toRepresentation() {
+ return form.toRepresentation();
+ }
+
+ public void update(AggregatePolicyRepresentation expected) {
+ form().populate(expected);
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicyForm.java
new file mode 100644
index 0000000..c1d5f21
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicyForm.java
@@ -0,0 +1,165 @@
+/*
+ * 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 java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.jboss.arquillian.graphene.fragment.Root;
+import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.testsuite.page.Form;
+import org.keycloak.testsuite.util.WaitUtils;
+import org.openqa.selenium.By;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+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 AggregatePolicyForm extends Form {
+
+ @FindBy(id = "name")
+ private WebElement name;
+
+ @FindBy(id = "description")
+ private WebElement description;
+
+ @FindBy(id = "logic")
+ private Select logic;
+
+ @FindBy(xpath = "//i[contains(@class,'pficon-delete')]")
+ private WebElement deleteButton;
+
+ @FindBy(id = "s2id_policies")
+ private PolicyInput policyInput;
+
+ @FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']")
+ private WebElement confirmDelete;
+
+ public void populate(AggregatePolicyRepresentation expected) {
+ setInputValue(name, expected.getName());
+ setInputValue(description, expected.getDescription());
+ logic.selectByValue(expected.getLogic().name());
+
+ Set<String> selectedPolicies = policyInput.getSelected();
+ Set<String> policies = expected.getPolicies();
+
+ for (String policy : policies) {
+ if (!selectedPolicies.contains(policy)) {
+ policyInput.select(policy, driver);
+ }
+ }
+
+ for (String selected : selectedPolicies) {
+ boolean isSelected = false;
+
+ for (String policy : policies) {
+ if (selected.equals(policy)) {
+ isSelected = true;
+ break;
+ }
+ }
+
+ if (!isSelected) {
+ policyInput.unSelect(selected, driver);
+ }
+ }
+
+ save();
+ }
+
+ public void delete() {
+ deleteButton.click();
+ confirmDelete.click();
+ }
+
+ public AggregatePolicyRepresentation toRepresentation() {
+ AggregatePolicyRepresentation representation = new AggregatePolicyRepresentation();
+
+ representation.setName(getInputValue(name));
+ representation.setDescription(getInputValue(description));
+ representation.setLogic(Logic.valueOf(logic.getFirstSelectedOption().getText().toUpperCase()));
+ representation.setPolicies(policyInput.getSelected());
+
+ return representation;
+ }
+
+ public class PolicyInput {
+
+ @Root
+ private WebElement root;
+
+ @FindBy(xpath = "//input[contains(@class,'select2-input')]")
+ private WebElement search;
+
+ @FindBy(xpath = "//div[contains(@class,'select2-result-label')]")
+ private List<WebElement> result;
+
+ @FindBy(xpath = "//li[contains(@class,'select2-search-choice')]")
+ private List<WebElement> selection;
+
+ public void select(String name, WebDriver driver) {
+ root.click();
+ WaitUtils.pause(1000);
+
+ Actions actions = new Actions(driver);
+
+ actions.sendKeys(name).perform();
+ WaitUtils.pause(1000);
+
+ if (result.isEmpty()) {
+ actions.sendKeys(Keys.ESCAPE).perform();
+ return;
+ }
+ for (WebElement result : result) {
+ if (result.getText().equalsIgnoreCase(name)) {
+ result.click();
+ return;
+ }
+ }
+ }
+
+ public Set<String> getSelected() {
+ HashSet<String> values = new HashSet<>();
+
+ for (WebElement selected : selection) {
+ values.add(selected.findElements(By.tagName("div")).get(0).getText());
+ }
+
+ return values;
+ }
+
+ public void unSelect(String name, WebDriver driver) {
+ for (WebElement selected : selection) {
+ if (name.equals(selected.findElements(By.tagName("div")).get(0).getText())) {
+ WebElement element = selected.findElement(By.xpath("//a[contains(@class,'select2-search-choice-close')]"));
+ JavascriptExecutor executor = (JavascriptExecutor) driver;
+ executor.executeScript("arguments[0].click();", element);
+ WaitUtils.pause(1000);
+ return;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicy.java
new file mode 100644
index 0000000..94fbb08
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicy.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.testsuite.console.page.clients.authorization.policy;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class JSPolicy implements PolicyTypeUI {
+
+ @Page
+ private JSPolicyForm form;
+
+ public JSPolicyForm form() {
+ return form;
+ }
+
+ public JSPolicyRepresentation toRepresentation() {
+ return form.toRepresentation();
+ }
+
+ public void update(JSPolicyRepresentation expected) {
+ form().populate(expected);
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicyForm.java
new file mode 100644
index 0000000..e83585b
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicyForm.java
@@ -0,0 +1,77 @@
+/*
+ * 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.JSPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.testsuite.page.Form;
+import org.openqa.selenium.JavascriptExecutor;
+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 JSPolicyForm extends Form {
+
+ @FindBy(id = "name")
+ private WebElement name;
+
+ @FindBy(id = "description")
+ private WebElement description;
+
+ @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;
+
+ public void populate(JSPolicyRepresentation expected) {
+ setInputValue(name, expected.getName());
+ setInputValue(description, expected.getDescription());
+ logic.selectByValue(expected.getLogic().name());
+
+ JavascriptExecutor scriptExecutor = (JavascriptExecutor) driver;
+
+ scriptExecutor.executeScript("angular.element(document.getElementById('code')).scope().policy.code = '" + expected.getCode() + "'");
+
+ save();
+ }
+
+ public void delete() {
+ deleteButton.click();
+ confirmDelete.click();
+ }
+
+ public JSPolicyRepresentation toRepresentation() {
+ JSPolicyRepresentation representation = new JSPolicyRepresentation();
+
+ representation.setName(getInputValue(name));
+ representation.setDescription(getInputValue(description));
+ representation.setLogic(Logic.valueOf(logic.getFirstSelectedOption().getText().toUpperCase()));
+
+ JavascriptExecutor scriptExecutor = (JavascriptExecutor) driver;
+
+ representation.setCode((String) scriptExecutor.executeScript("return angular.element(document.getElementById('code')).scope().policy.code;"));
+
+ return representation;
+ }
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java
index 36a198d..2a41efe 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java
@@ -16,9 +16,21 @@
*/
package org.keycloak.testsuite.console.page.clients.authorization.policy;
-import org.keycloak.testsuite.console.page.clients.authorization.permission.PermissionsTable;
+import static org.openqa.selenium.By.tagName;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation;
+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.TimePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
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>
@@ -26,9 +38,131 @@ import org.openqa.selenium.support.FindBy;
public class Policies extends Form {
@FindBy(css = "table[class*='table']")
- private PermissionsTable table;
+ private PoliciesTable table;
+
+ @FindBy(id = "create-policy")
+ private Select createSelect;
+
+ @Page
+ private RolePolicy rolePolicy;
+
+ @Page
+ private UserPolicy userPolicy;
+
+ @Page
+ private AggregatePolicy aggregatePolicy;
+
+ @Page
+ private JSPolicy jsPolicy;
- public PermissionsTable policies() {
+ @Page
+ private TimePolicy timePolicy;
+
+ public PoliciesTable policies() {
return table;
}
+
+ public <P extends PolicyTypeUI> P create(AbstractPolicyRepresentation expected) {
+ String type = expected.getType();
+
+ createSelect.selectByValue(type);
+
+ if ("role".equals(type)) {
+ rolePolicy.form().populate((RolePolicyRepresentation) expected);
+ rolePolicy.form().save();
+ return (P) rolePolicy;
+ } else if ("user".equals(type)) {
+ userPolicy.form().populate((UserPolicyRepresentation) expected);
+ userPolicy.form().save();
+ return (P) userPolicy;
+ } else if ("aggregate".equals(type)) {
+ aggregatePolicy.form().populate((AggregatePolicyRepresentation) expected);
+ aggregatePolicy.form().save();
+ return (P) aggregatePolicy;
+ } else if ("js".equals(type)) {
+ jsPolicy.form().populate((JSPolicyRepresentation) expected);
+ jsPolicy.form().save();
+ return (P) jsPolicy;
+ } else if ("time".equals(type)) {
+ timePolicy.form().populate((TimePolicyRepresentation) expected);
+ timePolicy.form().save();
+ return (P) timePolicy;
+ }
+
+ return null;
+ }
+
+ public void update(String name, AbstractPolicyRepresentation representation) {
+ for (WebElement row : policies().rows()) {
+ PolicyRepresentation actual = policies().toRepresentation(row);
+ if (actual.getName().equalsIgnoreCase(name)) {
+ row.findElements(tagName("a")).get(0).click();
+ WaitUtils.waitForPageToLoad(driver);
+ String type = representation.getType();
+
+ if ("role".equals(type)) {
+ rolePolicy.form().populate((RolePolicyRepresentation) representation);
+ } else if ("user".equals(type)) {
+ userPolicy.form().populate((UserPolicyRepresentation) representation);
+ } else if ("aggregate".equals(type)) {
+ aggregatePolicy.form().populate((AggregatePolicyRepresentation) representation);
+ } else if ("js".equals(type)) {
+ jsPolicy.form().populate((JSPolicyRepresentation) representation);
+ } else if ("time".equals(type)) {
+ timePolicy.form().populate((TimePolicyRepresentation) representation);
+ }
+
+ return;
+ }
+ }
+ }
+
+ public <P extends PolicyTypeUI> P name(String name) {
+ for (WebElement row : policies().rows()) {
+ PolicyRepresentation actual = policies().toRepresentation(row);
+ if (actual.getName().equalsIgnoreCase(name)) {
+ row.findElements(tagName("a")).get(0).click();
+ WaitUtils.waitForPageToLoad(driver);
+ String type = actual.getType();
+ if ("role".equals(type)) {
+ return (P) rolePolicy;
+ } else if ("user".equals(type)) {
+ return (P) userPolicy;
+ } else if ("aggregate".equals(type)) {
+ return (P) aggregatePolicy;
+ } else if ("js".equals(type)) {
+ return (P) jsPolicy;
+ } else if ("time".equals(type)) {
+ return (P) timePolicy;
+ }
+ }
+ }
+ return null;
+ }
+
+ public void delete(String name) {
+ for (WebElement row : policies().rows()) {
+ PolicyRepresentation actual = policies().toRepresentation(row);
+ if (actual.getName().equalsIgnoreCase(name)) {
+ row.findElements(tagName("a")).get(0).click();
+ WaitUtils.waitForPageToLoad(driver);
+
+ String type = actual.getType();
+
+ if ("role".equals(type)) {
+ rolePolicy.form().delete();
+ } else if ("user".equals(type)) {
+ userPolicy.form().delete();
+ } else if ("aggregate".equals(type)) {
+ aggregatePolicy.form().delete();
+ } else if ("js".equals(type)) {
+ jsPolicy.form().delete();
+ } else if ("time".equals(type)) {
+ timePolicy.form().delete();
+ }
+
+ return;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/PolicyTypeUI.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/PolicyTypeUI.java
new file mode 100644
index 0000000..ba3609d
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/PolicyTypeUI.java
@@ -0,0 +1,23 @@
+/*
+ * 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;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public interface PolicyTypeUI {
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicy.java
new file mode 100644
index 0000000..8d4be91
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicy.java
@@ -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.RolePolicyRepresentation;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class RolePolicy implements PolicyTypeUI {
+
+ @Page
+ private RolePolicyForm form;
+
+ public RolePolicyForm form() {
+ return form;
+ }
+
+ public RolePolicyRepresentation toRepresentation() {
+ return form.toRepresentation();
+ }
+
+ public void update(RolePolicyRepresentation expected) {
+ form().populate(expected);
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicyForm.java
new file mode 100644
index 0000000..29ae535
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicyForm.java
@@ -0,0 +1,284 @@
+/*
+ * 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 static org.openqa.selenium.By.tagName;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.jboss.arquillian.graphene.fragment.Root;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
+import org.keycloak.testsuite.page.Form;
+import org.keycloak.testsuite.util.WaitUtils;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+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 RolePolicyForm extends Form {
+
+ @FindBy(id = "name")
+ private WebElement name;
+
+ @FindBy(id = "description")
+ private WebElement description;
+
+ @FindBy(id = "logic")
+ private Select logic;
+
+ @FindBy(xpath = "//i[contains(@class,'pficon-delete')]")
+ private WebElement deleteButton;
+
+ @FindBy(id = "s2id_roles")
+ private RolesInput realmRolesInput;
+
+ @FindBy(id = "clients")
+ private Select clientsSelect;
+
+ @FindBy(id = "s2id_clientRoles")
+ private ClientRolesInput clientRolesInput;
+
+ @FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']")
+ private WebElement confirmDelete;
+
+ public void populate(RolePolicyRepresentation expected) {
+ setInputValue(name, expected.getName());
+ setInputValue(description, expected.getDescription());
+ logic.selectByValue(expected.getLogic().name());
+
+ Set<RolePolicyRepresentation.RoleDefinition> roles = expected.getRoles();
+
+ for (RolePolicyRepresentation.RoleDefinition role : roles) {
+ boolean clientRole = role.getId().indexOf('/') != -1;
+
+ if (clientRole) {
+ String[] parts = role.getId().split("/");
+ clientsSelect.selectByVisibleText(parts[0]);
+ clientRolesInput.select(parts[1], driver);
+ clientRolesInput.setRequired(parts[1], role);
+ } else {
+ realmRolesInput.select(role.getId(), driver);
+ realmRolesInput.setRequired(role.getId(), role);
+ }
+ }
+
+ unSelect(roles, realmRolesInput.getSelected());
+ unSelect(roles, clientRolesInput.getSelected());
+
+ save();
+ }
+
+ private void unSelect(Set<RolePolicyRepresentation.RoleDefinition> roles, Set<RolePolicyRepresentation.RoleDefinition> selection) {
+ for (RolePolicyRepresentation.RoleDefinition selected : selection) {
+ boolean isSelected = false;
+
+ for (RolePolicyRepresentation.RoleDefinition scope : roles) {
+ if (selected.getId().equals(scope.getId())) {
+ isSelected = true;
+ break;
+ }
+ }
+
+ if (!isSelected) {
+ boolean clientRole = selected.getId().indexOf('/') != -1;
+
+ if (clientRole) {
+ clientRolesInput.unSelect(selected.getId().split("/")[1], driver);
+ } else {
+ realmRolesInput.unSelect(selected.getId(), driver);
+ }
+ }
+ }
+ }
+
+ public void delete() {
+ deleteButton.click();
+ confirmDelete.click();
+ }
+
+ public RolePolicyRepresentation toRepresentation() {
+ RolePolicyRepresentation representation = new RolePolicyRepresentation();
+
+ representation.setName(getInputValue(name));
+ representation.setDescription(getInputValue(description));
+ representation.setLogic(Logic.valueOf(logic.getFirstSelectedOption().getText().toUpperCase()));
+
+ Set<RolePolicyRepresentation.RoleDefinition> roles = realmRolesInput.getSelected();
+
+ roles.addAll(clientRolesInput.getSelected());
+
+ representation.setRoles(roles);
+
+ return representation;
+ }
+
+ public class RolesInput extends AbstractRolesInput {
+ @Override
+ protected RolePolicyRepresentation.RoleDefinition getSelectedRoles(List<WebElement> tds) {
+ RolePolicyRepresentation.RoleDefinition selectedRole = new RolePolicyRepresentation.RoleDefinition();
+ selectedRole.setId(tds.get(0).getText());
+ selectedRole.setRequired(tds.get(1).findElement(By.tagName("input")).isSelected());
+ return selectedRole;
+ }
+
+ @Override
+ protected WebElement getRemoveButton(List<WebElement> tds) {
+ return tds.get(2);
+ }
+
+ @Override
+ protected List<WebElement> getSelectedElements() {
+ return root.findElements(By.xpath("(//table[@id='selected-realm-roles'])/tbody/tr"));
+ }
+
+ @Override
+ protected WebElement getRequiredColumn(List<WebElement> tds) {
+ return tds.get(1);
+ }
+ }
+
+ public class ClientRolesInput extends AbstractRolesInput {
+ @Override
+ protected WebElement getRemoveButton(List<WebElement> tds) {
+ return tds.get(3);
+ }
+
+ @Override
+ protected RolePolicyRepresentation.RoleDefinition getSelectedRoles(List<WebElement> tds) {
+ RolePolicyRepresentation.RoleDefinition selectedRole = new RolePolicyRepresentation.RoleDefinition();
+ selectedRole.setId(tds.get(1).getText() + "/" + tds.get(0).getText());
+ selectedRole.setRequired(tds.get(2).findElement(By.tagName("input")).isSelected());
+ return selectedRole;
+ }
+
+ @Override
+ protected List<WebElement> getSelectedElements() {
+ return root.findElements(By.xpath("(//table[@id='selected-client-roles'])/tbody/tr"));
+ }
+
+ @Override
+ protected WebElement getRequiredColumn(List<WebElement> tds) {
+ return tds.get(2);
+ }
+ }
+
+ public abstract class AbstractRolesInput {
+
+ @Root
+ protected WebElement root;
+
+ @FindBy(xpath = "//div[contains(@class,'select2-result-label')]")
+ private List<WebElement> result;
+
+ @FindBy(xpath = "//li[contains(@class,'select2-search-choice')]")
+ private List<WebElement> selection;
+
+ public void select(String roleId, WebDriver driver) {
+ root.click();
+ WaitUtils.pause(1000);
+
+ Actions actions = new Actions(driver);
+
+ actions.sendKeys(roleId).perform();
+ WaitUtils.pause(1000);
+
+ if (result.isEmpty()) {
+ actions.sendKeys(Keys.ESCAPE).perform();
+ return;
+ }
+
+ for (WebElement result : result) {
+ if (result.getText().equalsIgnoreCase(roleId)) {
+ result.click();
+ return;
+ }
+ }
+ }
+
+ public Set<RolePolicyRepresentation.RoleDefinition> getSelected() {
+ List<WebElement> realmRoles = getSelectedElements();
+ Set<RolePolicyRepresentation.RoleDefinition> values = new HashSet<>();
+
+ for (WebElement realmRole : realmRoles) {
+ List<WebElement> tds = realmRole.findElements(tagName("td"));
+ if (!(tds.isEmpty() || tds.get(0).getText().isEmpty())) {
+ values.add(getSelectedRoles(tds));
+ }
+ }
+
+ return values;
+ }
+
+ protected abstract RolePolicyRepresentation.RoleDefinition getSelectedRoles(List<WebElement> tds);
+
+ protected abstract List<WebElement> getSelectedElements();
+
+ public void unSelect(String name, WebDriver driver) {
+ Iterator<WebElement> iterator = getSelectedElements().iterator();
+
+ while (iterator.hasNext()) {
+ WebElement realmRole = iterator.next();
+ List<WebElement> tds = realmRole.findElements(tagName("td"));
+
+ if (!(tds.isEmpty() || tds.get(0).getText().isEmpty())) {
+ if (tds.get(0).getText().equals(name)) {
+ getRemoveButton(tds).findElement(By.tagName("button")).click();
+ return;
+ }
+ }
+ }
+ }
+
+ protected abstract WebElement getRemoveButton(List<WebElement> tds);
+
+ public void setRequired(String name, RolePolicyRepresentation.RoleDefinition role) {
+ Iterator<WebElement> iterator = getSelectedElements().iterator();
+
+ while (iterator.hasNext()) {
+ WebElement realmRole = iterator.next();
+ List<WebElement> tds = realmRole.findElements(tagName("td"));
+
+ if (!(tds.isEmpty() || tds.get(0).getText().isEmpty())) {
+ if (tds.get(0).getText().equals(name)) {
+ WebElement required = getRequiredColumn(tds).findElement(By.tagName("input"));
+
+ if (required.isSelected() && role.isRequired()) {
+ return;
+ } else if (!required.isSelected() && !role.isRequired()) {
+ return;
+ }
+
+ required.click();
+ return;
+ }
+ }
+ }
+ }
+
+ protected abstract WebElement getRequiredColumn(List<WebElement> tds);
+ }
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicy.java
new file mode 100644
index 0000000..ce2a20a
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicy.java
@@ -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.TimePolicyRepresentation;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class TimePolicy implements PolicyTypeUI {
+
+ @Page
+ private TimePolicyForm form;
+
+ public TimePolicyForm form() {
+ return form;
+ }
+
+ public TimePolicyRepresentation toRepresentation() {
+ return form.toRepresentation();
+ }
+
+ public void update(TimePolicyRepresentation expected) {
+ form().populate(expected);
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicyForm.java
new file mode 100644
index 0000000..5c31f33
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicyForm.java
@@ -0,0 +1,129 @@
+/*
+ * 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.TimePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.testsuite.page.Form;
+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 TimePolicyForm extends Form {
+
+ @FindBy(id = "name")
+ private WebElement name;
+
+ @FindBy(id = "description")
+ private WebElement description;
+
+ @FindBy(id = "logic")
+ private Select logic;
+
+ @FindBy(id = "notBefore")
+ private WebElement notBefore;
+
+ @FindBy(id = "notOnOrAfter")
+ private WebElement notOnOrAfter;
+
+ @FindBy(id = "dayMonth")
+ private WebElement dayMonth;
+
+ @FindBy(id = "month")
+ private WebElement month;
+
+ @FindBy(id = "year")
+ private WebElement year;
+
+ @FindBy(id = "hour")
+ private WebElement hour;
+
+ @FindBy(id = "minute")
+ private WebElement minute;
+
+ @FindBy(id = "dayMonthEnd")
+ private WebElement dayMonthEnd;
+
+ @FindBy(id = "monthEnd")
+ private WebElement monthEnd;
+
+ @FindBy(id = "yearEnd")
+ private WebElement yearEnd;
+
+ @FindBy(id = "hourEnd")
+ private WebElement hourEnd;
+
+ @FindBy(id = "minuteEnd")
+ private WebElement minuteEnd;
+
+
+ @FindBy(xpath = "//i[contains(@class,'pficon-delete')]")
+ private WebElement deleteButton;
+
+ @FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']")
+ private WebElement confirmDelete;
+
+ public void populate(TimePolicyRepresentation expected) {
+ setInputValue(name, expected.getName());
+ setInputValue(description, expected.getDescription());
+ logic.selectByValue(expected.getLogic().name());
+ setInputValue(notBefore, expected.getNotBefore());
+ setInputValue(notOnOrAfter, expected.getNotOnOrAfter());
+ setInputValue(dayMonth, expected.getDayMonth());
+ setInputValue(dayMonthEnd, expected.getDayMonthEnd());
+ setInputValue(month, expected.getMonth());
+ setInputValue(monthEnd, expected.getMonthEnd());
+ setInputValue(year, expected.getYear());
+ setInputValue(yearEnd, expected.getYearEnd());
+ setInputValue(hour, expected.getHour());
+ setInputValue(hourEnd, expected.getHourEnd());
+ setInputValue(minute, expected.getMinute());
+ setInputValue(minuteEnd, expected.getMinuteEnd());
+
+ save();
+ }
+
+ public void delete() {
+ deleteButton.click();
+ confirmDelete.click();
+ }
+
+ public TimePolicyRepresentation toRepresentation() {
+ TimePolicyRepresentation representation = new TimePolicyRepresentation();
+
+ representation.setName(getInputValue(name));
+ representation.setDescription(getInputValue(description));
+ representation.setLogic(Logic.valueOf(logic.getFirstSelectedOption().getText().toUpperCase()));
+ representation.setDayMonth(getInputValue(dayMonth));
+ representation.setDayMonthEnd(getInputValue(dayMonthEnd));
+ representation.setMonth(getInputValue(month));
+ representation.setMonthEnd(getInputValue(monthEnd));
+ representation.setYear(getInputValue(year));
+ representation.setYearEnd(getInputValue(yearEnd));
+ representation.setHour(getInputValue(hour));
+ representation.setHourEnd(getInputValue(hourEnd));
+ representation.setMinute(getInputValue(minute));
+ representation.setMinuteEnd(getInputValue(minuteEnd));
+ representation.setNotBefore(getInputValue(notBefore));
+ representation.setNotOnOrAfter(getInputValue(notOnOrAfter));
+
+ return representation;
+ }
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicy.java
new file mode 100644
index 0000000..cd5b8eb
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicy.java
@@ -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.UserPolicyRepresentation;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class UserPolicy implements PolicyTypeUI {
+
+ @Page
+ private UserPolicyForm form;
+
+ public UserPolicyForm form() {
+ return form;
+ }
+
+ public UserPolicyRepresentation toRepresentation() {
+ return form.toRepresentation();
+ }
+
+ public void update(UserPolicyRepresentation expected) {
+ form().populate(expected);
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicyForm.java
new file mode 100644
index 0000000..46caad0
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicyForm.java
@@ -0,0 +1,190 @@
+/*
+ * 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 static org.openqa.selenium.By.tagName;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.jboss.arquillian.graphene.fragment.Root;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
+import org.keycloak.testsuite.page.Form;
+import org.keycloak.testsuite.util.WaitUtils;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+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 UserPolicyForm extends Form {
+
+ @FindBy(id = "name")
+ private WebElement name;
+
+ @FindBy(id = "description")
+ private WebElement description;
+
+ @FindBy(id = "logic")
+ private Select logic;
+
+ @FindBy(xpath = "//i[contains(@class,'pficon-delete')]")
+ private WebElement deleteButton;
+
+ @FindBy(id = "s2id_users")
+ private UsersInput usersInput;
+
+ @FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']")
+ private WebElement confirmDelete;
+
+ public void populate(UserPolicyRepresentation expected) {
+ setInputValue(name, expected.getName());
+ setInputValue(description, expected.getDescription());
+ logic.selectByValue(expected.getLogic().name());
+
+ Set<String> users = expected.getUsers();
+
+ for (String user : users) {
+ usersInput.select(user, driver);
+ }
+
+ unSelect(users, usersInput.getSelected());
+
+ save();
+ }
+
+ private void unSelect(Set<String> users, Set<String> selection) {
+ for (String selected : selection) {
+ boolean isSelected = false;
+
+ for (String user : users) {
+ if (selected.equals(user)) {
+ isSelected = true;
+ break;
+ }
+ }
+
+ if (!isSelected) {
+ usersInput.unSelect(selected, driver);
+ }
+ }
+ }
+
+ public void delete() {
+ deleteButton.click();
+ confirmDelete.click();
+ }
+
+ public UserPolicyRepresentation toRepresentation() {
+ UserPolicyRepresentation representation = new UserPolicyRepresentation();
+
+ representation.setName(getInputValue(name));
+ representation.setDescription(getInputValue(description));
+ representation.setLogic(Logic.valueOf(logic.getFirstSelectedOption().getText().toUpperCase()));
+ representation.setUsers(usersInput.getSelected());
+
+ return representation;
+ }
+
+ public class UsersInput extends AbstractUserInput {
+ @Override
+ protected WebElement getRemoveButton(List<WebElement> tds) {
+ return tds.get(1);
+ }
+
+ @Override
+ protected List<WebElement> getSelectedElements() {
+ return root.findElements(By.xpath("(//table[@id='selected-users'])/tbody/tr"));
+ }
+ }
+
+ public abstract class AbstractUserInput {
+
+ @Root
+ protected WebElement root;
+
+ @FindBy(xpath = "//div[contains(@class,'select2-result-label')]")
+ private List<WebElement> result;
+
+ @FindBy(xpath = "//li[contains(@class,'select2-search-choice')]")
+ private List<WebElement> selection;
+
+ public void select(String roleId, WebDriver driver) {
+ root.click();
+ WaitUtils.pause(1000);
+
+ Actions actions = new Actions(driver);
+
+ actions.sendKeys(roleId).perform();
+ WaitUtils.pause(1000);
+
+ if (result.isEmpty()) {
+ actions.sendKeys(Keys.ESCAPE).perform();
+ return;
+ }
+
+ for (WebElement result : result) {
+ if (result.getText().equalsIgnoreCase(roleId)) {
+ result.click();
+ return;
+ }
+ }
+ }
+
+ public Set<String> getSelected() {
+ List<WebElement> users = getSelectedElements();
+ Set<String> values = new HashSet<>();
+
+ for (WebElement user : users) {
+ List<WebElement> tds = user.findElements(tagName("td"));
+ if (!(tds.isEmpty() || tds.get(0).getText().isEmpty())) {
+ values.add(tds.get(0).getText());
+ }
+ }
+
+ return values;
+ }
+
+ protected abstract List<WebElement> getSelectedElements();
+
+ public void unSelect(String name, WebDriver driver) {
+ Iterator<WebElement> iterator = getSelectedElements().iterator();
+
+ while (iterator.hasNext()) {
+ WebElement realmRole = iterator.next();
+ List<WebElement> tds = realmRole.findElements(tagName("td"));
+
+ if (!(tds.isEmpty() || tds.get(0).getText().isEmpty())) {
+ if (tds.get(0).getText().equals(name)) {
+ getRemoveButton(tds).findElement(By.tagName("button")).click();
+ return;
+ }
+ }
+ }
+ }
+
+ protected abstract WebElement getRemoveButton(List<WebElement> tds);
+ }
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AbstractAuthorizationSettingsTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AbstractAuthorizationSettingsTest.java
index 5bb5449..276985e 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AbstractAuthorizationSettingsTest.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AbstractAuthorizationSettingsTest.java
@@ -75,6 +75,8 @@ public abstract class AbstractAuthorizationSettingsTest extends AbstractClientTe
clientSettingsPage.tabs().authorization();
assertTrue(authorizationPage.isCurrent());
+ newClient.setId(found.getId());
+
return newClient;
}
}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AggregatePolicyManagementTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AggregatePolicyManagementTest.java
new file mode 100644
index 0000000..2051ac3
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AggregatePolicyManagementTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+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.PoliciesResource;
+import org.keycloak.admin.client.resource.RolePoliciesResource;
+import org.keycloak.admin.client.resource.RolesResource;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.AggregatePolicy;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.UserPolicy;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class AggregatePolicyManagementTest extends AbstractAuthorizationSettingsTest {
+
+ @Before
+ public void configureTest() {
+ super.configureTest();
+ RolesResource realmRoles = testRealmResource().roles();
+ realmRoles.create(new RoleRepresentation("Role A", "", false));
+ realmRoles.create(new RoleRepresentation("Role B", "", false));
+
+ RolePolicyRepresentation policyA = new RolePolicyRepresentation();
+
+ policyA.setName("Policy A");
+ policyA.addRole("Role A");
+
+ AuthorizationResource authorization = testRealmResource().clients().get(newClient.getId()).authorization();
+ PoliciesResource policies = authorization.policies();
+ RolePoliciesResource roles = policies.roles();
+
+ roles.create(policyA);
+
+ RolePolicyRepresentation policyB = new RolePolicyRepresentation();
+
+ policyB.setName("Policy B");
+ policyB.addRole("Role B");
+
+ roles.create(policyB);
+
+ UserPolicyRepresentation policyC = new UserPolicyRepresentation();
+
+ policyC.setName("Policy C");
+ policyC.addUser("test");
+
+ policies.users().create(policyC);
+ }
+
+ @Test
+ public void testUpdate() throws InterruptedException {
+ authorizationPage.navigateTo();
+ AggregatePolicyRepresentation expected = new AggregatePolicyRepresentation();
+
+ expected.setName("Test Aggregate Policy");
+ expected.setDescription("description");
+ expected.addPolicy("Policy A");
+ expected.addPolicy("Policy B");
+ expected.addPolicy("Policy C");
+
+ expected = createPolicy(expected);
+
+ String previousName = expected.getName();
+
+ expected.setName("Changed Test Aggregate Policy");
+ expected.setDescription("Changed description");
+ expected.setLogic(Logic.NEGATIVE);
+
+ expected.setPolicies(expected.getPolicies().stream().filter(policy -> !policy.equals("Policy B")).collect(Collectors.toSet()));
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().update(previousName, expected);
+ assertAlertSuccess();
+
+ authorizationPage.navigateTo();
+ AggregatePolicy actual = authorizationPage.authorizationTabs().policies().name(expected.getName());
+
+ assertPolicy(expected, actual);
+ }
+
+ @Test
+ public void testDeletePolicy() throws InterruptedException {
+ authorizationPage.navigateTo();
+ AggregatePolicyRepresentation expected = new AggregatePolicyRepresentation();
+
+ expected.setName("Test Aggregate Policy");
+ expected.setDescription("description");
+ expected.addPolicy("Policy C");
+
+ expected = createPolicy(expected);
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().delete(expected.getName());
+ assertAlertSuccess();
+ authorizationPage.navigateTo();
+ assertNull(authorizationPage.authorizationTabs().policies().policies().findByName(expected.getName()));
+ }
+
+ private AggregatePolicyRepresentation createPolicy(AggregatePolicyRepresentation expected) {
+ AggregatePolicy policy = authorizationPage.authorizationTabs().policies().create(expected);
+ assertAlertSuccess();
+ return assertPolicy(expected, policy);
+ }
+
+ private AggregatePolicyRepresentation assertPolicy(AggregatePolicyRepresentation expected, AggregatePolicy policy) {
+ AggregatePolicyRepresentation actual = policy.toRepresentation();
+
+ assertEquals(expected.getName(), actual.getName());
+ assertEquals(expected.getDescription(), actual.getDescription());
+ assertEquals(expected.getLogic(), actual.getLogic());
+
+ assertNotNull(actual.getPolicies());
+ assertEquals(expected.getPolicies().size(), actual.getPolicies().size());
+ assertEquals(0, actual.getPolicies().stream().filter(actualPolicy -> !expected.getPolicies().stream()
+ .filter(expectedPolicy -> actualPolicy.equals(expectedPolicy))
+ .findFirst().isPresent())
+ .count());
+
+ return actual;
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/JSPolicyManagementTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/JSPolicyManagementTest.java
new file mode 100644
index 0000000..fffce15
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/JSPolicyManagementTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.representations.idm.authorization.JSPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.JSPolicy;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class JSPolicyManagementTest extends AbstractAuthorizationSettingsTest {
+
+ @Test
+ public void testUpdate() throws InterruptedException {
+ authorizationPage.navigateTo();
+ JSPolicyRepresentation expected = new JSPolicyRepresentation();
+
+ expected.setName("Test JS Policy");
+ expected.setDescription("description");
+ expected.setCode("$evaluation.grant();");
+
+ expected = createPolicy(expected);
+
+ String previousName = expected.getName();
+
+ expected.setName("Changed Test JS Policy");
+ expected.setDescription("Changed description");
+ expected.setLogic(Logic.NEGATIVE);
+ expected.setCode("$evaluation.deny();");
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().update(previousName, expected);
+ assertAlertSuccess();
+
+ authorizationPage.navigateTo();
+ JSPolicy actual = authorizationPage.authorizationTabs().policies().name(expected.getName());
+
+ assertPolicy(expected, actual);
+ }
+
+ @Test
+ public void testDeletePolicy() throws InterruptedException {
+ authorizationPage.navigateTo();
+ JSPolicyRepresentation expected = new JSPolicyRepresentation();
+
+ expected.setName("Test JS Policy");
+ expected.setDescription("description");
+ expected.setCode("$evaluation.deny();");
+
+ expected = createPolicy(expected);
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().delete(expected.getName());
+ assertAlertSuccess();
+ authorizationPage.navigateTo();
+ assertNull(authorizationPage.authorizationTabs().policies().policies().findByName(expected.getName()));
+ }
+
+ private JSPolicyRepresentation createPolicy(JSPolicyRepresentation expected) {
+ JSPolicy policy = authorizationPage.authorizationTabs().policies().create(expected);
+ assertAlertSuccess();
+ return assertPolicy(expected, policy);
+ }
+
+ private JSPolicyRepresentation assertPolicy(JSPolicyRepresentation expected, JSPolicy policy) {
+ JSPolicyRepresentation actual = policy.toRepresentation();
+
+ assertEquals(expected.getName(), actual.getName());
+ assertEquals(expected.getDescription(), actual.getDescription());
+ assertEquals(expected.getLogic(), actual.getLogic());
+ assertEquals(expected.getCode(), actual.getCode());
+
+ return actual;
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ResourcePermissionManagementTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ResourcePermissionManagementTest.java
new file mode 100644
index 0000000..a4ab7ef
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ResourcePermissionManagementTest.java
@@ -0,0 +1,182 @@
+/*
+ * 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 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.PoliciesResource;
+import org.keycloak.admin.client.resource.ResourcesResource;
+import org.keycloak.admin.client.resource.RolePoliciesResource;
+import org.keycloak.admin.client.resource.RolesResource;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.authorization.DecisionStrategy;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
+import org.keycloak.testsuite.console.page.clients.authorization.permission.ResourcePermission;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ResourcePermissionManagementTest extends AbstractAuthorizationSettingsTest {
+
+ @Before
+ public void configureTest() {
+ super.configureTest();
+ RolesResource realmRoles = testRealmResource().roles();
+ realmRoles.create(new RoleRepresentation("Role A", "", false));
+ realmRoles.create(new RoleRepresentation("Role B", "", false));
+
+ RolePolicyRepresentation policyA = new RolePolicyRepresentation();
+
+ policyA.setName("Policy A");
+ policyA.addRole("Role A");
+
+ AuthorizationResource authorization = testRealmResource().clients().get(newClient.getId()).authorization();
+ PoliciesResource policies = authorization.policies();
+ RolePoliciesResource roles = policies.roles();
+
+ roles.create(policyA);
+
+ RolePolicyRepresentation policyB = new RolePolicyRepresentation();
+
+ policyB.setName("Policy B");
+ policyB.addRole("Role B");
+
+ roles.create(policyB);
+
+ UserPolicyRepresentation policyC = new UserPolicyRepresentation();
+
+ policyC.setName("Policy C");
+ policyC.addUser("test");
+
+ policies.users().create(policyC);
+
+ ResourcesResource resources = authorization.resources();
+
+ resources.create(new ResourceRepresentation("Resource A"));
+ resources.create(new ResourceRepresentation("Resource B"));
+ }
+
+ @Test
+ public void testUpdateResource() throws InterruptedException {
+ authorizationPage.navigateTo();
+ ResourcePermissionRepresentation expected = new ResourcePermissionRepresentation();
+
+ expected.setName("Test Resource A Permission");
+ expected.setDescription("description");
+ expected.addResource("Resource A");
+ expected.addPolicy("Policy A");
+ expected.addPolicy("Policy B");
+ expected.addPolicy("Policy C");
+
+ expected = createPermission(expected);
+
+ String previousName = expected.getName();
+
+ expected.setName("Changed Test Resource A Permission");
+ expected.setDescription("Changed description");
+ expected.setDecisionStrategy(DecisionStrategy.CONSENSUS);
+ expected.getResources().clear();
+ expected.addResource("Resource B");
+ expected.setPolicies(expected.getPolicies().stream().filter(policy -> !policy.equals("Policy B")).collect(Collectors.toSet()));
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().permissions().update(previousName, expected);
+ assertAlertSuccess();
+
+ authorizationPage.navigateTo();
+ ResourcePermission actual = authorizationPage.authorizationTabs().permissions().name(expected.getName());
+
+ assertPolicy(expected, actual);
+ }
+
+ @Test
+ public void testUpdateResourceType() throws InterruptedException {
+ authorizationPage.navigateTo();
+ ResourcePermissionRepresentation expected = new ResourcePermissionRepresentation();
+
+ expected.setName("Test Resource B Permission");
+ expected.setDescription("description");
+ expected.setResourceType("test-resource-type");
+ expected.addPolicy("Policy A");
+ expected.addPolicy("Policy B");
+ expected.addPolicy("Policy C");
+
+ expected = createPermission(expected);
+
+ String previousName = expected.getName();
+
+ expected.setName("Changed Test Resource B Permission");
+ expected.setDescription("Changed description");
+ expected.setDecisionStrategy(DecisionStrategy.CONSENSUS);
+
+ expected.setResourceType("changed-resource-type");
+ expected.setPolicies(expected.getPolicies().stream().filter(policy -> !policy.equals("Policy B")).collect(Collectors.toSet()));
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().permissions().update(previousName, expected);
+ assertAlertSuccess();
+
+ authorizationPage.navigateTo();
+ ResourcePermission actual = authorizationPage.authorizationTabs().permissions().name(expected.getName());
+
+ assertPolicy(expected, actual);
+ }
+
+ @Test
+ public void testDeletePolicy() throws InterruptedException {
+ authorizationPage.navigateTo();
+ ResourcePermissionRepresentation expected = new ResourcePermissionRepresentation();
+
+ expected.setName("Test Delete Resource Permission");
+ expected.setDescription("description");
+ expected.addResource("Resource B");
+ expected.addPolicy("Policy C");
+
+ expected = createPermission(expected);
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().permissions().delete(expected.getName());
+ assertAlertSuccess();
+ authorizationPage.navigateTo();
+ assertNull(authorizationPage.authorizationTabs().permissions().permissions().findByName(expected.getName()));
+ }
+
+ private ResourcePermissionRepresentation createPermission(ResourcePermissionRepresentation expected) {
+ ResourcePermission policy = authorizationPage.authorizationTabs().permissions().create(expected);
+ assertAlertSuccess();
+ return assertPolicy(expected, policy);
+ }
+
+ private ResourcePermissionRepresentation assertPolicy(ResourcePermissionRepresentation expected, ResourcePermission policy) {
+ ResourcePermissionRepresentation actual = policy.toRepresentation();
+
+ assertEquals(expected.getName(), actual.getName());
+ assertEquals(expected.getDescription(), actual.getDescription());
+ assertEquals(expected.getLogic(), actual.getLogic());
+
+ return actual;
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/RolePolicyManagementTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/RolePolicyManagementTest.java
new file mode 100644
index 0000000..713b93a
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/RolePolicyManagementTest.java
@@ -0,0 +1,232 @@
+/*
+ * 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.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.admin.client.resource.RolesResource;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.RolePolicy;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class RolePolicyManagementTest extends AbstractAuthorizationSettingsTest {
+
+ @Before
+ public void configureTest() {
+ super.configureTest();
+ RolesResource realmRoles = testRealmResource().roles();
+ realmRoles.create(new RoleRepresentation("Realm Role A", "", false));
+ realmRoles.create(new RoleRepresentation("Realm Role B", "", false));
+ realmRoles.create(new RoleRepresentation("Realm Role C", "", false));
+ RolesResource clientRoles = testRealmResource().clients().get(newClient.getId()).roles();
+ clientRoles.create(new RoleRepresentation("Client Role A", "", false));
+ clientRoles.create(new RoleRepresentation("Client Role B", "", false));
+ clientRoles.create(new RoleRepresentation("Client Role C", "", false));
+ }
+
+ @Test
+ public void testUpdateRealmRoles() throws InterruptedException {
+ authorizationPage.navigateTo();
+ RolePolicyRepresentation expected = new RolePolicyRepresentation();
+
+ expected.setName("Test Realm Role Policy");
+ expected.setDescription("description");
+ expected.addRole("Realm Role A");
+ expected.addRole("Realm Role B");
+ expected.addRole("Realm Role C");
+
+ expected = createPolicy(expected);
+
+ String previousName = expected.getName();
+
+ expected.setName("Changed Test Realm Role Policy");
+ expected.setDescription("Changed description");
+ expected.setLogic(Logic.NEGATIVE);
+
+ expected.setRoles(expected.getRoles().stream().filter(roleDefinition -> !roleDefinition.getId().equals("Realm Role B")).collect(Collectors.toSet()));
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().update(previousName, expected);
+ assertAlertSuccess();
+
+ authorizationPage.navigateTo();
+ RolePolicy actual = authorizationPage.authorizationTabs().policies().name(expected.getName());
+ expected = assertPolicy(expected, actual);
+
+ expected.getRoles().iterator().next().setRequired(true);
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().update(expected.getName(), expected);
+ assertAlertSuccess();
+ expected = assertPolicy(expected, actual);
+
+ expected.getRoles().clear();
+ expected.addRole("Realm Role B", true);
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().update(expected.getName(), expected);
+ assertAlertSuccess();
+ assertPolicy(expected, actual);
+ }
+
+ @Test
+ public void testUpdateClientRoles() throws InterruptedException {
+ authorizationPage.navigateTo();
+ RolePolicyRepresentation expected = new RolePolicyRepresentation();
+
+ expected.setName("Test Client Role Policy");
+ expected.setDescription("description");
+
+ String clientId = newClient.getClientId();
+
+ expected.addClientRole(clientId, "Client Role A");
+ expected.addClientRole(clientId, "Client Role B");
+ expected.addClientRole(clientId, "Client Role C");
+
+ expected = createPolicy(expected);
+
+ String previousName = expected.getName();
+
+ expected.setName("Changed Test Client Role Policy");
+ expected.setDescription("Changed description");
+
+ expected.setRoles(expected.getRoles().stream().filter(roleDefinition -> !roleDefinition.getId().contains("Client Role B")).collect(Collectors.toSet()));
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().update(previousName, expected);
+ assertAlertSuccess();
+
+ authorizationPage.navigateTo();
+ RolePolicy actual = authorizationPage.authorizationTabs().policies().name(expected.getName());
+ expected = assertPolicy(expected, actual);
+
+ expected.getRoles().iterator().next().setRequired(true);
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().update(expected.getName(), expected);
+ assertAlertSuccess();
+ expected = assertPolicy(expected, actual);
+
+ expected.getRoles().clear();
+ expected.addClientRole(clientId, "Client Role B", true);
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().update(expected.getName(), expected);
+ assertAlertSuccess();
+ assertPolicy(expected, actual);
+ }
+
+ @Test
+ public void testRealmAndClientRoles() throws InterruptedException {
+ authorizationPage.navigateTo();
+ RolePolicyRepresentation expected = new RolePolicyRepresentation();
+
+ expected.setName("Test Realm And Client Role Policy");
+ expected.setDescription("description");
+
+ String clientId = newClient.getClientId();
+
+ expected.addRole("Realm Role A");
+ expected.addRole("Realm Role C");
+ expected.addClientRole(clientId, "Client Role A");
+ expected.addClientRole(clientId, "Client Role B");
+ expected.addClientRole(clientId, "Client Role C");
+
+ expected = createPolicy(expected);
+ expected.setRoles(expected.getRoles().stream().filter(roleDefinition -> !roleDefinition.getId().contains("Client Role B") && !roleDefinition.getId().contains("Realm Role A")).collect(Collectors.toSet()));
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().update(expected.getName(), expected);
+ assertAlertSuccess();
+
+ authorizationPage.navigateTo();
+ RolePolicy actual = authorizationPage.authorizationTabs().policies().name(expected.getName());
+ expected = assertPolicy(expected, actual);
+
+ expected.getRoles().forEach(roleDefinition -> {
+ if (roleDefinition.getId().equals("Realm Role C")) {
+ roleDefinition.setRequired(true);
+ }
+ });
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().update(expected.getName(), expected);
+ assertAlertSuccess();
+ expected = assertPolicy(expected, actual);
+
+ expected.getRoles().clear();
+ expected.addClientRole(clientId, "Client Role B", true);
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().update(expected.getName(), expected);
+ assertAlertSuccess();
+ assertPolicy(expected, actual);
+ }
+
+ @Test
+ public void testDeletePolicy() throws InterruptedException {
+ authorizationPage.navigateTo();
+ RolePolicyRepresentation expected = new RolePolicyRepresentation();
+
+ expected.setName("Test Realm Role Policy");
+ expected.setDescription("description");
+ expected.addRole("Realm Role A");
+ expected.addRole("Realm Role B");
+ expected.addRole("Realm Role C");
+
+ expected = createPolicy(expected);
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().delete(expected.getName());
+ assertAlertSuccess();
+ authorizationPage.navigateTo();
+ assertNull(authorizationPage.authorizationTabs().policies().policies().findByName(expected.getName()));
+ }
+
+ private RolePolicyRepresentation createPolicy(RolePolicyRepresentation expected) {
+ RolePolicy policy = authorizationPage.authorizationTabs().policies().create(expected);
+ assertAlertSuccess();
+ return assertPolicy(expected, policy);
+ }
+
+ private RolePolicyRepresentation assertPolicy(RolePolicyRepresentation expected, RolePolicy policy) {
+ RolePolicyRepresentation actual = policy.toRepresentation();
+
+ assertEquals(expected.getName(), actual.getName());
+ assertEquals(expected.getDescription(), actual.getDescription());
+ assertEquals(expected.getLogic(), actual.getLogic());
+
+ assertNotNull(actual.getRoles());
+ assertEquals(expected.getRoles().size(), actual.getRoles().size());
+ assertEquals(0, actual.getRoles().stream().filter(actualDefinition -> !expected.getRoles().stream()
+ .filter(roleDefinition -> actualDefinition.getId().contains(roleDefinition.getId()) && actualDefinition.isRequired() == roleDefinition.isRequired())
+ .findFirst().isPresent())
+ .count());
+ return actual;
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/TimePolicyManagementTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/TimePolicyManagementTest.java
new file mode 100644
index 0000000..9e9d2e8
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/TimePolicyManagementTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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.representations.idm.authorization.JSPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.representations.idm.authorization.TimePolicyRepresentation;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.JSPolicy;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.TimePolicy;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class TimePolicyManagementTest extends AbstractAuthorizationSettingsTest {
+
+ @Test
+ public void testUpdate() throws InterruptedException {
+ authorizationPage.navigateTo();
+ TimePolicyRepresentation expected = new TimePolicyRepresentation();
+
+ expected.setName("Test Time Policy");
+ expected.setDescription("description");
+ expected.setNotBefore("2017-01-01 00:00:00");
+ expected.setNotBefore("2018-01-01 00:00:00");
+ expected.setDayMonth("1");
+ expected.setDayMonthEnd("2");
+ expected.setMonth("3");
+ expected.setMonthEnd("4");
+ expected.setYear("5");
+ expected.setYearEnd("6");
+ expected.setHour("7");
+ expected.setHourEnd("8");
+ expected.setMinute("9");
+ expected.setMinuteEnd("10");
+
+ expected = createPolicy(expected);
+
+ String previousName = expected.getName();
+
+ expected.setName("Changed Test Time Policy");
+ expected.setDescription("Changed description");
+ expected.setLogic(Logic.NEGATIVE);
+ expected.setNotBefore("2018-01-01 00:00:00");
+ expected.setNotBefore("2019-01-01 00:00:00");
+ expected.setDayMonth("23");
+ expected.setDayMonthEnd("25");
+ expected.setMonth("11");
+ expected.setMonthEnd("12");
+ expected.setYear("2020");
+ expected.setYearEnd("2021");
+ expected.setHour("17");
+ expected.setHourEnd("18");
+ expected.setMinute("19");
+ expected.setMinuteEnd("20");
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().update(previousName, expected);
+ assertAlertSuccess();
+
+ authorizationPage.navigateTo();
+ TimePolicy actual = authorizationPage.authorizationTabs().policies().name(expected.getName());
+
+ assertPolicy(expected, actual);
+ }
+
+ @Test
+ public void testDeletePolicy() throws InterruptedException {
+ authorizationPage.navigateTo();
+ TimePolicyRepresentation expected = new TimePolicyRepresentation();
+
+ expected.setName("Test Time Policy");
+ expected.setDescription("description");
+ expected.setNotBefore("2017-01-01 00:00:00");
+ expected.setNotBefore("2018-01-01 00:00:00");
+ expected.setDayMonth("1");
+ expected.setDayMonthEnd("2");
+ expected.setMonth("3");
+ expected.setMonthEnd("4");
+ expected.setYear("5");
+ expected.setYearEnd("6");
+ expected.setHour("7");
+ expected.setHourEnd("8");
+ expected.setMinute("9");
+ expected.setMinuteEnd("10");
+
+ expected = createPolicy(expected);
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().delete(expected.getName());
+ assertAlertSuccess();
+ authorizationPage.navigateTo();
+ assertNull(authorizationPage.authorizationTabs().policies().policies().findByName(expected.getName()));
+ }
+
+ private TimePolicyRepresentation createPolicy(TimePolicyRepresentation expected) {
+ TimePolicy policy = authorizationPage.authorizationTabs().policies().create(expected);
+ assertAlertSuccess();
+ return assertPolicy(expected, policy);
+ }
+
+ private TimePolicyRepresentation assertPolicy(TimePolicyRepresentation expected, TimePolicy policy) {
+ TimePolicyRepresentation actual = policy.toRepresentation();
+
+ assertEquals(expected.getName(), actual.getName());
+ assertEquals(expected.getDescription(), actual.getDescription());
+ assertEquals(expected.getLogic(), actual.getLogic());
+
+ return actual;
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/UserPolicyManagementTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/UserPolicyManagementTest.java
new file mode 100644
index 0000000..ed19bc5
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/UserPolicyManagementTest.java
@@ -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.console.authorization;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.stream.Collectors;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.admin.client.resource.UsersResource;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.UserPolicy;
+import org.keycloak.testsuite.util.UserBuilder;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class UserPolicyManagementTest extends AbstractAuthorizationSettingsTest {
+
+ @Before
+ public void configureTest() {
+ super.configureTest();
+ UsersResource users = testRealmResource().users();
+ users.create(UserBuilder.create().username("user a").build());
+ users.create(UserBuilder.create().username("user b").build());
+ users.create(UserBuilder.create().username("user c").build());
+ }
+
+ @Test
+ public void testUpdate() throws InterruptedException {
+ authorizationPage.navigateTo();
+ UserPolicyRepresentation expected = new UserPolicyRepresentation();
+
+ expected.setName("Test User Policy");
+ expected.setDescription("description");
+ expected.addUser("user a");
+ expected.addUser("user b");
+ expected.addUser("user c");
+
+ expected = createPolicy(expected);
+
+ String previousName = expected.getName();
+
+ expected.setName("Changed Test User Policy");
+ expected.setDescription("Changed description");
+ expected.setLogic(Logic.NEGATIVE);
+
+ expected.setUsers(expected.getUsers().stream().filter(user -> !user.equals("user b")).collect(Collectors.toSet()));
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().update(previousName, expected);
+ assertAlertSuccess();
+
+ authorizationPage.navigateTo();
+ UserPolicy actual = authorizationPage.authorizationTabs().policies().name(expected.getName());
+
+ assertPolicy(expected, actual);
+ }
+
+ @Test
+ public void testDeletePolicy() throws InterruptedException {
+ authorizationPage.navigateTo();
+ UserPolicyRepresentation expected = new UserPolicyRepresentation();
+
+ expected.setName("Test User Policy");
+ expected.setDescription("description");
+ expected.addUser("user c");
+
+ expected = createPolicy(expected);
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().delete(expected.getName());
+ assertAlertSuccess();
+ authorizationPage.navigateTo();
+ assertNull(authorizationPage.authorizationTabs().policies().policies().findByName(expected.getName()));
+ }
+
+ private UserPolicyRepresentation createPolicy(UserPolicyRepresentation expected) {
+ UserPolicy policy = authorizationPage.authorizationTabs().policies().create(expected);
+ assertAlertSuccess();
+ return assertPolicy(expected, policy);
+ }
+
+ private UserPolicyRepresentation assertPolicy(UserPolicyRepresentation expected, UserPolicy policy) {
+ UserPolicyRepresentation actual = policy.toRepresentation();
+
+ assertEquals(expected.getName(), actual.getName());
+ assertEquals(expected.getDescription(), actual.getDescription());
+ assertEquals(expected.getLogic(), actual.getLogic());
+
+ assertNotNull(actual.getUsers());
+ assertEquals(expected.getUsers().size(), actual.getUsers().size());
+ assertEquals(0, actual.getUsers().stream().filter(actualUser -> !expected.getUsers().stream()
+ .filter(expectedUser -> actualUser.equals(expectedUser))
+ .findFirst().isPresent())
+ .count());
+ return actual;
+ }
+}
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
index 3db9401..9918041 100644
--- a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
@@ -1789,7 +1789,6 @@ module.controller('ResourceServerPolicyAggregateDetailCtrl', function($scope, $r
},
onInitUpdate : function(policy) {
- policy.config.applyPolicies = [];
ResourceServerPolicy.associatedPolicies({
realm : $route.current.params.realm,
client : client.id,
@@ -1816,11 +1815,11 @@ module.controller('ResourceServerPolicyAggregateDetailCtrl', function($scope, $r
policies.push($scope.selectedPolicies[i].id);
}
- $scope.policy.config.applyPolicies = JSON.stringify(policies);
+ $scope.policy.policies = policies;
+ delete $scope.policy.config;
},
onInitCreate : function(newPolicy) {
- newPolicy.config = {};
newPolicy.decisionStrategy = 'UNANIMOUS';
},
@@ -1831,7 +1830,8 @@ module.controller('ResourceServerPolicyAggregateDetailCtrl', function($scope, $r
policies.push($scope.selectedPolicies[i].id);
}
- $scope.policy.config.applyPolicies = JSON.stringify(policies);
+ $scope.policy.policies = policies;
+ delete $scope.policy.config;
}
}, realm, client, $scope);
});
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html
index 7a5ba6d..221a902 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html
@@ -36,36 +36,36 @@
<kc-tooltip>{{:: 'authz-permission-resource-apply-to-resource-type.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix" data-ng-hide="applyToResourceTypeFlag">
- <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-resources' | translate}} <span class="required">*</span></label>
+ <label class="col-md-2 control-label" for="resources">{{:: 'authz-resources' | translate}} <span class="required">*</span></label>
<div class="col-md-6">
- <input type="hidden" ui-select2="resourcesUiSelect" id="reqActions" data-ng-model="selectedResource" data-placeholder="{{:: 'authz-select-resource' | translate}}..." data-ng-required="!applyToResourceTypeFlag"/>
+ <input type="hidden" ui-select2="resourcesUiSelect" id="resources" data-ng-model="selectedResource" data-placeholder="{{:: 'authz-select-resource' | translate}}..." data-ng-required="!applyToResourceTypeFlag"/>
</div>
<kc-tooltip>{{:: 'authz-permission-resource-resource.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix" data-ng-show="applyToResourceTypeFlag">
- <label class="col-md-2 control-label" for="policy.resourceType">{{:: 'authz-resource-type' | translate}} <span class="required">*</span></label>
+ <label class="col-md-2 control-label" for="resourceType">{{:: 'authz-resource-type' | translate}} <span class="required">*</span></label>
<div class="col-md-6">
- <input class="form-control" type="text" id="policy.resourceType" name="policy.resourceType" data-ng-model="policy.resourceType" data-ng-required="applyToResourceTypeFlag">
+ <input class="form-control" type="text" id="resourceType" name="policy.resourceType" data-ng-model="policy.resourceType" data-ng-required="applyToResourceTypeFlag">
</div>
<kc-tooltip>{{:: 'authz-permission-resource-type.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix">
- <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-policy-apply-policy' | translate}} <span class="required">*</span></label>
+ <label class="col-md-2 control-label" for="policies">{{:: 'authz-policy-apply-policy' | translate}} <span class="required">*</span></label>
<div class="col-md-6">
- <input type="hidden" ui-select2="policiesUiSelect" id="reqActions" data-ng-model="selectedPolicies" data-placeholder="{{:: 'authz-select-a-policy' | translate}}..." multiple required />
+ <input type="hidden" ui-select2="policiesUiSelect" id="policies" data-ng-model="selectedPolicies" data-placeholder="{{:: 'authz-select-a-policy' | translate}}..." multiple required />
</div>
<kc-tooltip>{{:: 'authz-policy-apply-policy.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix">
- <label class="col-md-2 control-label" for="policy.decisionStrategy">{{:: 'authz-policy-decision-strategy' | translate}}</label>
+ <label class="col-md-2 control-label" for="decisionStrategy">{{:: 'authz-policy-decision-strategy' | translate}}</label>
<div class="col-sm-2">
- <select class="form-control" id="policy.decisionStrategy"
+ <select class="form-control" id="decisionStrategy"
data-ng-model="policy.decisionStrategy"
ng-change="selectDecisionStrategy()">
<option value="UNANIMOUS">{{:: 'authz-policy-decision-strategy-unanimous' | translate}}</option>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html
index 3c761a5..2101643 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html
@@ -50,6 +50,7 @@
<div class="pull-right">
<select class="form-control" ng-model="policyType"
ng-options="p.name for p in policyProviders track by p.type"
+ id="create-permission"
data-ng-change="addPolicy(policyType);">
<option value="" disabled selected>{{:: 'authz-create-permission' | translate}}...</option>
</select>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html
index adb586b..4af440b 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html
@@ -31,10 +31,10 @@
<kc-tooltip>{{:: 'authz-policy-description.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix">
- <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-policy-apply-policy' | translate}} <span class="required">*</span></label>
+ <label class="col-md-2 control-label" for="policies">{{:: 'authz-policy-apply-policy' | translate}} <span class="required">*</span></label>
<div class="col-md-6">
- <input type="hidden" ui-select2="policiesUiSelect" id="reqActions" data-ng-model="selectedPolicies" data-placeholder="{{:: 'authz-select-a-policy' | translate}}..." multiple required />
+ <input type="hidden" ui-select2="policiesUiSelect" id="policies" data-ng-model="selectedPolicies" data-placeholder="{{:: 'authz-select-a-policy' | translate}}..." multiple required />
</div>
<kc-tooltip>{{:: 'authz-policy-apply-policy.tooltip' | translate}}</kc-tooltip>
</div>
@@ -54,10 +54,10 @@
<kc-tooltip>{{:: 'authz-policy-decision-strategy.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" name="logic"
data-ng-model="policy.logic">
<option value="POSITIVE">{{:: 'authz-policy-logic-positive' | translate}}</option>
<option value="NEGATIVE">{{:: 'authz-policy-logic-negative' | translate}}</option>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html
index 6e39515..679c15a 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html
@@ -33,17 +33,17 @@
<kc-tooltip>{{:: 'authz-policy-description.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
- <label class="col-md-2 control-label" for="description">{{:: 'authz-policy-js-code' | translate}} </label>
+ <label class="col-md-2 control-label" for="code">{{:: 'authz-policy-js-code' | translate}} </label>
<div class="col-sm-6">
- <div ui-ace="{ onLoad : initEditor }" data-ng-model="policy.code"></div>
+ <div ui-ace="{ onLoad : initEditor }" id="code" data-ng-model="policy.code"></div>
</div>
<kc-tooltip>{{:: 'authz-policy-js-code.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>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-role-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-role-detail.html
index f9c2aca..47e563a 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-role-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-role-detail.html
@@ -63,7 +63,7 @@
<div class="form-group clearfix" style="margin-top: -15px;">
<label class="col-md-2 control-label"></label>
<div class="col-sm-4" data-ng-show="hasRealmRole()">
- <table class="table table-striped table-bordered">
+ <table class="table table-striped table-bordered" id="selected-realm-roles">
<thead>
<tr>
<th class="col-sm-5">{{:: 'name' | translate}}</th>
@@ -114,7 +114,7 @@
<div class="form-group clearfix" style="margin-top: -15px;">
<label class="col-md-2 control-label"></label>
<div class="col-sm-4" data-ng-show="hasClientRole()">
- <table class="table table-striped table-bordered">
+ <table class="table table-striped table-bordered" id="selected-client-roles">
<thead>
<tr>
<th class="col-sm-5">{{:: 'name' | translate}}</th>
@@ -140,10 +140,10 @@
</div>
</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>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html
index e265804..81793d5 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html
@@ -34,18 +34,18 @@
<kc-tooltip>{{:: 'authz-policy-description.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
- <label class="col-md-2 control-label" for="policy.notBefore">{{:: 'not-before' | translate}}</label>
+ <label class="col-md-2 control-label" for="notBefore">{{:: 'not-before' | translate}}</label>
<div class="col-md-6 time-selector">
- <input class="form-control" style="width: 150px" type="text" id="policy.notBefore" name="notBefore" data-ng-model="policy.notBefore" placeholder="yyyy-MM-dd hh:mm:ss" data-ng-required="isRequired()">
+ <input class="form-control" style="width: 150px" type="text" id="notBefore" name="notBefore" data-ng-model="policy.notBefore" placeholder="yyyy-MM-dd hh:mm:ss" data-ng-required="isRequired()">
</div>
<kc-tooltip>{{:: 'authz-policy-time-not-before.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
- <label class="col-md-2 control-label" for="policy.notOnOrAfter">{{:: 'authz-policy-time-not-on-after' | translate}}</label>
+ <label class="col-md-2 control-label" for="notOnOrAfter">{{:: 'authz-policy-time-not-on-after' | translate}}</label>
<div class="col-md-6 time-selector">
- <input class="form-control" style="width: 150px" type="text" id="policy.notOnOrAfter" name="policy.notOnOrAfter" data-ng-model="policy.notOnOrAfter" placeholder="yyyy-MM-dd hh:mm:ss" data-ng-required="isRequired()">
+ <input class="form-control" style="width: 150px" type="text" id="notOnOrAfter" name="notOnOrAfter" data-ng-model="policy.notOnOrAfter" placeholder="yyyy-MM-dd hh:mm:ss" data-ng-required="isRequired()">
</div>
<kc-tooltip>{{:: 'authz-policy-time-not-on-after.tooltip' | translate}}</kc-tooltip>
</div>
@@ -90,10 +90,10 @@
<kc-tooltip>{{:: 'authz-policy-time-minute.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>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-user-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-user-detail.html
index 2a3b019..c619910 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-user-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-user-detail.html
@@ -42,7 +42,7 @@
<div class="form-group clearfix" style="margin-top: -15px;">
<label class="col-md-2 control-label"></label>
<div class="col-sm-3">
- <table class="table table-striped table-bordered">
+ <table class="table table-striped table-bordered" id="selected-users">
<thead>
<tr data-ng-hide="!selectedUsers.length">
<th>{{:: 'username' | translate}}</th>
@@ -64,10 +64,10 @@
</div>
</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>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html
index 999eb9f..f4e0e89 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html
@@ -50,7 +50,7 @@
<div class="pull-right">
<a id="hideDetails" data-ng-show="showDetailsFlag" class="btn btn-default" data-ng-click="showDetailsFlag = !showDetailsFlag;showDetails();" href="">{{:: 'authz-hide-details' | translate}}</a>
<a id="showDetails" data-ng-hide="showDetailsFlag" class="btn btn-default" data-ng-click="showDetailsFlag = !showDetailsFlag;showDetails();" href="">{{:: 'authz-show-details' | translate}}</a>
- <select class="form-control" ng-model="policyType"
+ <select id="create-policy" class="form-control" ng-model="policyType"
ng-options="p.name for p in policyProviders track by p.type"
data-ng-change="addPolicy(policyType);">
<option value="" disabled selected>{{:: 'authz-create-policy' | translate}}...</option>