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 6d19a84373..ddac66dfc0 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 @@ -118,6 +118,10 @@ public class AbstractPolicyRepresentation { return scopes; } + public void setScopes(Set scopes) { + this.scopes = scopes; + } + public void addScope(String... id) { if (this.scopes == null) { this.scopes = new HashSet<>(); diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/AbstractMultipleSelect2.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/AbstractMultipleSelect2.java new file mode 100644 index 0000000000..3c4dda8d19 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/AbstractMultipleSelect2.java @@ -0,0 +1,154 @@ +/* + * 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.fragment; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Function; + +import org.jboss.arquillian.drone.api.annotation.Drone; +import org.jboss.arquillian.graphene.fragment.Root; +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; + +/** + * @author Pedro Igor + */ +public abstract class AbstractMultipleSelect2 { + + @Root + private WebElement root; + + @Drone + private WebDriver driver; + + @FindBy(xpath = ".//input[contains(@class,'select2-input')]") + private WebElement search; + + @FindBy(xpath = "//div[contains(@class,'select2-result-label')]") + private List result; + + public void update(Set values) { + Set selection = getSelected(); + + for (R value : values) { + if (!selection.contains(value)) { + select(value); + } + } + + for (R selected : selection) { + boolean isSelected = false; + + for (R value : values) { + if (selected.equals(value)) { + isSelected = true; + break; + } + } + + if (!isSelected) { + deselect(selected); + } + } + } + + public void select(R value) { + root.click(); + WaitUtils.pause(500); + + String id = identity().apply(value); + + Actions actions = new Actions(driver); + actions.sendKeys(id).perform(); + WaitUtils.pause(500); + + if (result.isEmpty()) { + actions.sendKeys(Keys.ESCAPE).perform(); + return; + } + + for (WebElement result : result) { + if (result.getText().equalsIgnoreCase(id)) { + result.click(); + return; + } + } + } + + protected abstract Function identity(); + + public Set getSelected() { + Set values = new HashSet<>(); + + for (WebElement selected : getSelectedElements()) { + R value = representation().apply(selected); + + if (value != null) { + values.add(value); + } + } + + return values; + } + + protected abstract List getSelectedElements(); + + protected abstract Function representation(); + + public void deselect(R value) { + onDeselect(value); + } + + protected void onDeselect(R value) { + for (WebElement selected : getSelectedElements()) { + if (deselect().apply(selected, value)) { + return; + } + } + } + + protected BiFunction deselect() { + return (selected, value) -> { + WebElement selection = selected.findElements(By.tagName("div")).get(0); + if (identity().apply(value).equals(selection.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(500); + return true; + } + return false; + }; + } + + protected WebElement getRoot() { + return root; + } + + protected WebDriver getDriver() { + return driver; + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/MultipleStringSelect2.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/MultipleStringSelect2.java new file mode 100644 index 0000000000..89582c8354 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/MultipleStringSelect2.java @@ -0,0 +1,54 @@ +/* + * Copyright 2017 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.fragment; + +import java.util.List; +import java.util.function.Function; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +/** + * @author Pedro Igor + */ +public class MultipleStringSelect2 extends AbstractMultipleSelect2 { + + @Override + protected Function identity() { + return r -> r.toString(); + } + + @Override + protected List getSelectedElements() { + return getRoot().findElements(By.xpath(".//li[contains(@class,'select2-search-choice')]")); + } + + @Override + protected Function representation() { + return webElement -> { + List element = webElement.findElements(By.tagName("div")); + + if (element.isEmpty()) { + return null; + } + + String value = element.get(0).getText(); + + return "".equals(value) ? null : value; + }; + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/SingleStringSelect2.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/SingleStringSelect2.java new file mode 100644 index 0000000000..6621622f32 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/SingleStringSelect2.java @@ -0,0 +1,64 @@ +/* + * 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.fragment; + +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Function; + +import org.keycloak.testsuite.util.WaitUtils; +import org.openqa.selenium.By; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.WebElement; + +/** + * @author Pedro Igor + */ +public class SingleStringSelect2 extends AbstractMultipleSelect2 { + + @Override + protected Function identity() { + return r -> r.toString(); + } + + @Override + protected List getSelectedElements() { + return getRoot().findElements(By.xpath(".//span[contains(@class,'select2-chosen')]")); + } + + @Override + protected Function representation() { + return webElement -> { + String value = webElement.getText(); + return "".equals(value) ? null : value; + }; + } + + @Override + protected BiFunction deselect() { + return (selected, value) -> { + if (identity().apply(value).equals(selected.getText())) { + WebElement element = selected.findElement(By.xpath(".//a[contains(@class,'select2-search-choice-close')]")); + JavascriptExecutor executor = (JavascriptExecutor) getDriver(); + executor.executeScript("arguments[0].click();", element); + WaitUtils.pause(500); + return true; + } + return false; + }; + } +} 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 9900247a86..a6c95276d8 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 @@ -22,6 +22,7 @@ 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.representations.idm.authorization.ScopePermissionRepresentation; import org.keycloak.testsuite.console.page.clients.authorization.policy.PolicyTypeUI; import org.keycloak.testsuite.page.Form; import org.keycloak.testsuite.util.WaitUtils; @@ -43,6 +44,9 @@ public class Permissions extends Form { @Page private ResourcePermission resourcePermission; + @Page + private ScopePermission scopePermission; + public PermissionsTable permissions() { return table; } @@ -57,7 +61,9 @@ public class Permissions extends Form { resourcePermission.form().save(); return (P) resourcePermission; } else if ("scope".equals(type)) { - return null; + scopePermission.form().populate((ScopePermissionRepresentation) expected); + scopePermission.form().save(); + return (P) scopePermission; } return null; @@ -73,6 +79,8 @@ public class Permissions extends Form { if ("resource".equals(type)) { resourcePermission.form().populate((ResourcePermissionRepresentation) representation); + } else if ("scope".equals(type)) { + scopePermission.form().populate((ScopePermissionRepresentation) representation); } return; @@ -89,6 +97,8 @@ public class Permissions extends Form { String type = actual.getType(); if ("resource".equals(type)) { return (P) resourcePermission; + } else if ("scope".equals(type)) { + return (P) scopePermission; } } } @@ -106,6 +116,8 @@ public class Permissions extends Form { if ("resource".equals(type)) { resourcePermission.form().delete(); + } else if ("scope".equals(type)) { + scopePermission.form().delete(); } return; 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 index 87facb3494..cf39523b21 100644 --- 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 @@ -16,22 +16,12 @@ */ 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.MultipleStringSelect2; 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; @@ -62,10 +52,10 @@ public class ResourcePermissionForm extends Form { private WebElement confirmDelete; @FindBy(id = "s2id_policies") - private PolicyInput policyInput; + private MultipleStringSelect2 policySelect; @FindBy(id = "s2id_resources") - private ResourceInput resourceInput; + private MultipleStringSelect2 resourceSelect; public void populate(ResourcePermissionRepresentation expected) { setInputValue(name, expected.getName()); @@ -78,56 +68,10 @@ public class ResourcePermissionForm extends Form { setInputValue(resourceType, expected.getResourceType()); } else { resourceTypeSwitch.setOn(false); - Set selectedResources = resourceInput.getSelected(); - Set 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); - } - } + resourceSelect.update(expected.getResources()); } - Set selectedPolicies = policyInput.getSelected(); - Set 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); + policySelect.update(expected.getPolicies()); save(); } @@ -143,122 +87,15 @@ public class ResourcePermissionForm extends Form { representation.setName(getInputValue(name)); representation.setDescription(getInputValue(description)); representation.setDecisionStrategy(DecisionStrategy.valueOf(decisionStrategy.getFirstSelectedOption().getText().toUpperCase())); - representation.setPolicies(policyInput.getSelected()); - representation.setResources(resourceInput.getSelected()); + representation.setPolicies(policySelect.getSelected()); + String inputValue = getInputValue(resourceType); + + if (!"".equals(inputValue)) { + representation.setResourceType(inputValue); + } + + representation.setResources(resourceSelect.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 result; - - @FindBy(xpath = "//li[contains(@class,'select2-search-choice')]") - private List 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 getSelected() { - HashSet 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 result; - - @FindBy(xpath = "//li[contains(@class,'select2-search-choice')]") - private List 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 getSelected() { - HashSet 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/permission/ScopePermission.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ScopePermission.java new file mode 100644 index 0000000000..5b392adf4c --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ScopePermission.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.ResourcePermissionRepresentation; +import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation; +import org.keycloak.testsuite.console.page.clients.authorization.policy.PolicyTypeUI; + +/** + * @author Pedro Igor + */ +public class ScopePermission implements PolicyTypeUI { + + @Page + private ScopePermissionForm form; + + public ScopePermissionForm form() { + return form; + } + + public ScopePermissionRepresentation toRepresentation() { + return form.toRepresentation(); + } + + public void update(ScopePermissionRepresentation expected) { + form().populate(expected); + } +} diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ScopePermissionForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ScopePermissionForm.java new file mode 100644 index 0000000000..f16cd5c55f --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ScopePermissionForm.java @@ -0,0 +1,107 @@ +/* + * 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.Set; +import java.util.function.Function; + +import org.keycloak.representations.idm.authorization.DecisionStrategy; +import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation; +import org.keycloak.testsuite.console.page.fragment.MultipleStringSelect2; +import org.keycloak.testsuite.console.page.fragment.SingleStringSelect2; +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 Pedro Igor + */ +public class ScopePermissionForm extends Form { + + @FindBy(id = "name") + private WebElement name; + + @FindBy(id = "description") + private WebElement description; + + @FindBy(id = "decisionStrategy") + private Select decisionStrategy; + + @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 MultipleStringSelect2 policySelect; + + @FindBy(id = "s2id_scopes") + private MultipleStringSelect2 scopeSelect; + + @FindBy(id = "s2id_resourceScopes") + private MultipleStringSelect2 resourceScopeSelect; + + @FindBy(id = "s2id_resources") + private ResourceSelect resourceSelect; + + public void populate(ScopePermissionRepresentation expected) { + setInputValue(name, expected.getName()); + setInputValue(description, expected.getDescription()); + decisionStrategy.selectByValue(expected.getDecisionStrategy().name()); + + Set resources = expected.getResources(); + + if (resources != null && !resources.isEmpty()) { + resourceSelect.update(resources); + resourceScopeSelect.update(expected.getScopes()); + } else { + scopeSelect.update(expected.getScopes()); + } + + policySelect.update(expected.getPolicies()); + + save(); + } + + public void delete() { + deleteButton.click(); + confirmDelete.click(); + } + + public ScopePermissionRepresentation toRepresentation() { + ScopePermissionRepresentation representation = new ScopePermissionRepresentation(); + + representation.setName(getInputValue(name)); + representation.setDescription(getInputValue(description)); + representation.setDecisionStrategy(DecisionStrategy.valueOf(decisionStrategy.getFirstSelectedOption().getText().toUpperCase())); + representation.setPolicies(policySelect.getSelected()); + representation.setResources(resourceSelect.getSelected()); + representation.setScopes(scopeSelect.getSelected()); + representation.getScopes().addAll(resourceScopeSelect.getSelected()); + + return representation; + } + + public class ResourceSelect extends SingleStringSelect2 { + @Override + protected Function representation() { + return super.representation().andThen(s -> "".equals(s) || s.contains("Any resource...") ? null : s); + } + } +} \ 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/AggregatePolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicyForm.java index c1d5f212b6..5e7170d6df 100644 --- 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 @@ -16,21 +16,13 @@ */ 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.console.page.fragment.MultipleStringSelect2; 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; @@ -52,7 +44,7 @@ public class AggregatePolicyForm extends Form { private WebElement deleteButton; @FindBy(id = "s2id_policies") - private PolicyInput policyInput; + private MultipleStringSelect2 policySelect; @FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']") private WebElement confirmDelete; @@ -62,12 +54,12 @@ public class AggregatePolicyForm extends Form { setInputValue(description, expected.getDescription()); logic.selectByValue(expected.getLogic().name()); - Set selectedPolicies = policyInput.getSelected(); + Set selectedPolicies = policySelect.getSelected(); Set policies = expected.getPolicies(); for (String policy : policies) { if (!selectedPolicies.contains(policy)) { - policyInput.select(policy, driver); + policySelect.select(policy); } } @@ -82,7 +74,7 @@ public class AggregatePolicyForm extends Form { } if (!isSelected) { - policyInput.unSelect(selected, driver); + policySelect.deselect(selected); } } @@ -100,66 +92,8 @@ public class AggregatePolicyForm extends Form { representation.setName(getInputValue(name)); representation.setDescription(getInputValue(description)); representation.setLogic(Logic.valueOf(logic.getFirstSelectedOption().getText().toUpperCase())); - representation.setPolicies(policyInput.getSelected()); + representation.setPolicies(policySelect.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 result; - - @FindBy(xpath = "//li[contains(@class,'select2-search-choice')]") - private List 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 getSelected() { - HashSet 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/RolePolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicyForm.java index 29ae5355ce..8b6f114765 100644 --- 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 @@ -18,21 +18,19 @@ 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 java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; -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.console.page.fragment.AbstractMultipleSelect2; 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; @@ -54,13 +52,13 @@ public class RolePolicyForm extends Form { private WebElement deleteButton; @FindBy(id = "s2id_roles") - private RolesInput realmRolesInput; + private RoleMultipleSelect2 realmRoleSelect; @FindBy(id = "clients") private Select clientsSelect; @FindBy(id = "s2id_clientRoles") - private ClientRolesInput clientRolesInput; + private ClientRoleSelect clientRoleSelect; @FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']") private WebElement confirmDelete; @@ -78,16 +76,16 @@ public class RolePolicyForm extends Form { if (clientRole) { String[] parts = role.getId().split("/"); clientsSelect.selectByVisibleText(parts[0]); - clientRolesInput.select(parts[1], driver); - clientRolesInput.setRequired(parts[1], role); + clientRoleSelect.select(role); + clientRoleSelect.setRequired(role); } else { - realmRolesInput.select(role.getId(), driver); - realmRolesInput.setRequired(role.getId(), role); + realmRoleSelect.select(role); + realmRoleSelect.setRequired(role); } } - unSelect(roles, realmRolesInput.getSelected()); - unSelect(roles, clientRolesInput.getSelected()); + unSelect(roles, realmRoleSelect.getSelected()); + unSelect(roles, clientRoleSelect.getSelected()); save(); } @@ -107,9 +105,9 @@ public class RolePolicyForm extends Form { boolean clientRole = selected.getId().indexOf('/') != -1; if (clientRole) { - clientRolesInput.unSelect(selected.getId().split("/")[1], driver); + clientRoleSelect.deselect(selected); } else { - realmRolesInput.unSelect(selected.getId(), driver); + realmRoleSelect.deselect(selected); } } } @@ -127,144 +125,58 @@ public class RolePolicyForm extends Form { representation.setDescription(getInputValue(description)); representation.setLogic(Logic.valueOf(logic.getFirstSelectedOption().getText().toUpperCase())); - Set roles = realmRolesInput.getSelected(); + Set roles = realmRoleSelect.getSelected(); - roles.addAll(clientRolesInput.getSelected()); + roles.addAll(clientRoleSelect.getSelected()); representation.setRoles(roles); return representation; } - public class RolesInput extends AbstractRolesInput { - @Override - protected RolePolicyRepresentation.RoleDefinition getSelectedRoles(List 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; - } + public class RoleMultipleSelect2 extends AbstractMultipleSelect2 { @Override - protected WebElement getRemoveButton(List tds) { - return tds.get(2); + protected Function identity() { + return role -> { + String id = role.getId(); + return id.indexOf('/') != -1 ? id.split("/")[1] : id; + }; } @Override protected List getSelectedElements() { - return root.findElements(By.xpath("(//table[@id='selected-realm-roles'])/tbody/tr")); + return getRoot().findElements(By.xpath("(//table[@id='selected-realm-roles'])/tbody/tr")).stream() + .filter(webElement -> webElement.findElements(tagName("td")).size() > 1) + .collect(Collectors.toList()); } @Override - protected WebElement getRequiredColumn(List tds) { - return tds.get(1); - } - } + protected Function representation() { + return webElement -> { + List tds = webElement.findElements(tagName("td")); + RolePolicyRepresentation.RoleDefinition selectedRole = new RolePolicyRepresentation.RoleDefinition(); + boolean clientRole = tds.size() == 4; - public class ClientRolesInput extends AbstractRolesInput { - @Override - protected WebElement getRemoveButton(List tds) { - return tds.get(3); + selectedRole.setId(clientRole ? tds.get(1).getText() + "/" + tds.get(0).getText() : tds.get(0).getText()); + selectedRole.setRequired(tds.get(clientRole ? 2 : 1).findElement(By.tagName("input")).isSelected()); + + return selectedRole; + }; } - @Override - protected RolePolicyRepresentation.RoleDefinition getSelectedRoles(List 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 getSelectedElements() { - return root.findElements(By.xpath("(//table[@id='selected-client-roles'])/tbody/tr")); - } - - @Override - protected WebElement getRequiredColumn(List tds) { - return tds.get(2); - } - } - - public abstract class AbstractRolesInput { - - @Root - protected WebElement root; - - @FindBy(xpath = "//div[contains(@class,'select2-result-label')]") - private List result; - - @FindBy(xpath = "//li[contains(@class,'select2-search-choice')]") - private List 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 getSelected() { - List realmRoles = getSelectedElements(); - Set values = new HashSet<>(); - - for (WebElement realmRole : realmRoles) { - List 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 tds); - - protected abstract List getSelectedElements(); - - public void unSelect(String name, WebDriver driver) { + public void setRequired(RolePolicyRepresentation.RoleDefinition role) { Iterator iterator = getSelectedElements().iterator(); while (iterator.hasNext()) { WebElement realmRole = iterator.next(); List tds = realmRole.findElements(tagName("td")); + boolean clientRole = role.getId().indexOf("/") != -1; + WebElement roleName = tds.get(0); - 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 tds); - - public void setRequired(String name, RolePolicyRepresentation.RoleDefinition role) { - Iterator iterator = getSelectedElements().iterator(); - - while (iterator.hasNext()) { - WebElement realmRole = iterator.next(); - List 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 (!roleName.getText().isEmpty()) { + if (roleName.getText().equals(getRoleId(role, clientRole))) { + WebElement required = tds.get(clientRole ? 2 : 1).findElement(By.tagName("input")); if (required.isSelected() && role.isRequired()) { return; @@ -279,6 +191,34 @@ public class RolePolicyForm extends Form { } } - protected abstract WebElement getRequiredColumn(List tds); + @Override + protected BiFunction deselect() { + return (webElement, roleDefinition) -> { + List tds = webElement.findElements(tagName("td")); + boolean clientRole = tds.size() == 4; + + if (!tds.get(0).getText().isEmpty()) { + if (tds.get(0).getText().equals(getRoleId(roleDefinition, clientRole))) { + tds.get(clientRole ? 3 : 2).findElement(By.tagName("button")).click(); + return true; + } + } + + return false; + }; + } + + private String getRoleId(RolePolicyRepresentation.RoleDefinition roleDefinition, boolean clientRole) { + return clientRole ? roleDefinition.getId().split("/")[1] : roleDefinition.getId(); + } + } + + public class ClientRoleSelect extends RoleMultipleSelect2 { + @Override + protected List getSelectedElements() { + return getRoot().findElements(By.xpath("(//table[@id='selected-client-roles'])/tbody/tr")).stream() + .filter(webElement -> webElement.findElements(tagName("td")).size() > 1) + .collect(Collectors.toList()); + } } } \ 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/UserPolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicyForm.java index 46caad04a9..e403d1b8b2 100644 --- 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 @@ -18,21 +18,17 @@ 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 java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; -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.console.page.fragment.MultipleStringSelect2; 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; @@ -54,7 +50,7 @@ public class UserPolicyForm extends Form { private WebElement deleteButton; @FindBy(id = "s2id_users") - private UsersInput usersInput; + private UserSelect usersInput; @FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']") private WebElement confirmDelete; @@ -64,34 +60,11 @@ public class UserPolicyForm extends Form { setInputValue(description, expected.getDescription()); logic.selectByValue(expected.getLogic().name()); - Set users = expected.getUsers(); - - for (String user : users) { - usersInput.select(user, driver); - } - - unSelect(users, usersInput.getSelected()); + usersInput.update(expected.getUsers()); save(); } - private void unSelect(Set users, Set 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(); @@ -108,83 +81,34 @@ public class UserPolicyForm extends Form { return representation; } - public class UsersInput extends AbstractUserInput { - @Override - protected WebElement getRemoveButton(List tds) { - return tds.get(1); - } + public class UserSelect extends MultipleStringSelect2 { @Override protected List 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 result; - - @FindBy(xpath = "//li[contains(@class,'select2-search-choice')]") - private List 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; - } - } + return getRoot().findElements(By.xpath("(//table[@id='selected-users'])/tbody/tr")).stream() + .filter(webElement -> webElement.findElements(tagName("td")).size() > 1) + .collect(Collectors.toList()); } - public Set getSelected() { - List users = getSelectedElements(); - Set values = new HashSet<>(); + @Override + protected BiFunction deselect() { + return (webElement, name) -> { + List tds = webElement.findElements(tagName("td")); - for (WebElement user : users) { - List tds = user.findElements(tagName("td")); - if (!(tds.isEmpty() || tds.get(0).getText().isEmpty())) { - values.add(tds.get(0).getText()); - } - } - - return values; - } - - protected abstract List getSelectedElements(); - - public void unSelect(String name, WebDriver driver) { - Iterator iterator = getSelectedElements().iterator(); - - while (iterator.hasNext()) { - WebElement realmRole = iterator.next(); - List tds = realmRole.findElements(tagName("td")); - - if (!(tds.isEmpty() || tds.get(0).getText().isEmpty())) { + if (!tds.get(0).getText().isEmpty()) { if (tds.get(0).getText().equals(name)) { - getRemoveButton(tds).findElement(By.tagName("button")).click(); - return; + tds.get(1).findElement(By.tagName("button")).click(); + return true; } } - } + + return false; + }; } - protected abstract WebElement getRemoveButton(List tds); + @Override + protected Function representation() { + return webElement -> webElement.findElements(tagName("td")).get(0).getText(); + } } } \ No newline at end of file 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 index 2051ac3919..2299200307 100644 --- 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 @@ -79,7 +79,7 @@ public class AggregatePolicyManagementTest extends AbstractAuthorizationSettings authorizationPage.navigateTo(); AggregatePolicyRepresentation expected = new AggregatePolicyRepresentation(); - expected.setName("Test Aggregate Policy"); + expected.setName("Test Update Aggregate Policy"); expected.setDescription("description"); expected.addPolicy("Policy A"); expected.addPolicy("Policy B"); @@ -89,11 +89,11 @@ public class AggregatePolicyManagementTest extends AbstractAuthorizationSettings String previousName = expected.getName(); - expected.setName("Changed Test Aggregate Policy"); + expected.setName("Changed Test Update Aggregate Policy"); expected.setDescription("Changed description"); expected.setLogic(Logic.NEGATIVE); - - expected.setPolicies(expected.getPolicies().stream().filter(policy -> !policy.equals("Policy B")).collect(Collectors.toSet())); + expected.getPolicies().clear(); + expected.addPolicy("Policy A", "Policy C"); authorizationPage.navigateTo(); authorizationPage.authorizationTabs().policies().update(previousName, expected); @@ -106,11 +106,11 @@ public class AggregatePolicyManagementTest extends AbstractAuthorizationSettings } @Test - public void testDeletePolicy() throws InterruptedException { + public void testDelete() throws InterruptedException { authorizationPage.navigateTo(); AggregatePolicyRepresentation expected = new AggregatePolicyRepresentation(); - expected.setName("Test Aggregate Policy"); + expected.setName("Test Delete Aggregate Policy"); expected.setDescription("description"); expected.addPolicy("Policy C"); 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 index fffce15f9b..0b9113c9b3 100644 --- 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 @@ -58,7 +58,7 @@ public class JSPolicyManagementTest extends AbstractAuthorizationSettingsTest { } @Test - public void testDeletePolicy() throws InterruptedException { + public void testDelete() throws InterruptedException { authorizationPage.navigateTo(); JSPolicyRepresentation expected = new JSPolicyRepresentation(); 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 index a4ab7ef91a..7eb6a944b7 100644 --- 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 @@ -101,7 +101,8 @@ public class ResourcePermissionManagementTest extends AbstractAuthorizationSetti 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())); + expected.getPolicies().clear(); + expected.addPolicy("Policy A", "Policy C"); authorizationPage.navigateTo(); authorizationPage.authorizationTabs().permissions().update(previousName, expected); @@ -118,7 +119,7 @@ public class ResourcePermissionManagementTest extends AbstractAuthorizationSetti authorizationPage.navigateTo(); ResourcePermissionRepresentation expected = new ResourcePermissionRepresentation(); - expected.setName("Test Resource B Permission"); + expected.setName("Test Resource B Type Permission"); expected.setDescription("description"); expected.setResourceType("test-resource-type"); expected.addPolicy("Policy A"); @@ -129,7 +130,7 @@ public class ResourcePermissionManagementTest extends AbstractAuthorizationSetti String previousName = expected.getName(); - expected.setName("Changed Test Resource B Permission"); + expected.setName("Changed Test Resource B Type Permission"); expected.setDescription("Changed description"); expected.setDecisionStrategy(DecisionStrategy.CONSENSUS); @@ -147,7 +148,7 @@ public class ResourcePermissionManagementTest extends AbstractAuthorizationSetti } @Test - public void testDeletePolicy() throws InterruptedException { + public void testDelete() throws InterruptedException { authorizationPage.navigateTo(); ResourcePermissionRepresentation expected = new ResourcePermissionRepresentation(); @@ -175,7 +176,16 @@ public class ResourcePermissionManagementTest extends AbstractAuthorizationSetti assertEquals(expected.getName(), actual.getName()); assertEquals(expected.getDescription(), actual.getDescription()); - assertEquals(expected.getLogic(), actual.getLogic()); + assertEquals(expected.getDecisionStrategy(), actual.getDecisionStrategy()); + assertEquals(expected.getResourceType(), actual.getResourceType()); + assertEquals(0, actual.getPolicies().stream().filter(actualPolicy -> !expected.getPolicies().stream() + .filter(expectedPolicy -> actualPolicy.equals(expectedPolicy)) + .findFirst().isPresent()) + .count()); + assertEquals(0, actual.getResources().stream().filter(actualResource -> !expected.getResources().stream() + .filter(expectedResource -> actualResource.equals(expectedResource)) + .findFirst().isPresent()) + .count()); 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 index 713b93ae1e..44e4f70919 100644 --- 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 @@ -55,7 +55,7 @@ public class RolePolicyManagementTest extends AbstractAuthorizationSettingsTest authorizationPage.navigateTo(); RolePolicyRepresentation expected = new RolePolicyRepresentation(); - expected.setName("Test Realm Role Policy"); + expected.setName("Test Update Realm Role Policy"); expected.setDescription("description"); expected.addRole("Realm Role A"); expected.addRole("Realm Role B"); @@ -100,7 +100,7 @@ public class RolePolicyManagementTest extends AbstractAuthorizationSettingsTest authorizationPage.navigateTo(); RolePolicyRepresentation expected = new RolePolicyRepresentation(); - expected.setName("Test Client Role Policy"); + expected.setName("Test Update Client Role Policy"); expected.setDescription("description"); String clientId = newClient.getClientId(); @@ -113,7 +113,7 @@ public class RolePolicyManagementTest extends AbstractAuthorizationSettingsTest String previousName = expected.getName(); - expected.setName("Changed Test Client Role Policy"); + expected.setName("Changed Test Update Client Role Policy"); expected.setDescription("Changed description"); expected.setRoles(expected.getRoles().stream().filter(roleDefinition -> !roleDefinition.getId().contains("Client Role B")).collect(Collectors.toSet())); @@ -190,11 +190,11 @@ public class RolePolicyManagementTest extends AbstractAuthorizationSettingsTest } @Test - public void testDeletePolicy() throws InterruptedException { + public void testDelete() throws InterruptedException { authorizationPage.navigateTo(); RolePolicyRepresentation expected = new RolePolicyRepresentation(); - expected.setName("Test Realm Role Policy"); + expected.setName("Test Delete Role Policy"); expected.setDescription("description"); expected.addRole("Realm Role A"); expected.addRole("Realm Role B"); @@ -224,7 +224,7 @@ public class RolePolicyManagementTest extends AbstractAuthorizationSettingsTest 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()) + .filter(roleDefinition -> actualDefinition.getId().contains(roleDefinition.getId().indexOf("/") != -1 ? roleDefinition.getId().split("/")[1] : 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/ScopePermissionManagementTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ScopePermissionManagementTest.java new file mode 100644 index 0000000000..7852c20b5f --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ScopePermissionManagementTest.java @@ -0,0 +1,204 @@ +/* + * 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.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.ResourceRepresentation; +import org.keycloak.representations.idm.authorization.RolePolicyRepresentation; +import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation; +import org.keycloak.representations.idm.authorization.ScopeRepresentation; +import org.keycloak.representations.idm.authorization.UserPolicyRepresentation; +import org.keycloak.testsuite.console.page.clients.authorization.permission.ResourcePermission; +import org.keycloak.testsuite.console.page.clients.authorization.permission.ScopePermission; + +/** + * @author Pedro Igor + */ +public class ScopePermissionManagementTest 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); + + authorization.scopes().create(new ScopeRepresentation("Scope A")); + authorization.scopes().create(new ScopeRepresentation("Scope B")); + authorization.scopes().create(new ScopeRepresentation("Scope C")); + + ResourcesResource resources = authorization.resources(); + + resources.create(new ResourceRepresentation("Resource A", "Scope A")); + resources.create(new ResourceRepresentation("Resource B", "Scope B", "Scope C")); + } + + @Test + public void testUpdateScopeOnly() throws InterruptedException { + authorizationPage.navigateTo(); + ScopePermissionRepresentation expected = new ScopePermissionRepresentation(); + + expected.setName("Test Scope Only Permission"); + expected.setDescription("description"); + expected.addScope("Scope C", "Scope A", "Scope B"); + expected.addPolicy("Policy C", "Policy A", "Policy B"); + + expected = createPermission(expected); + + String previousName = expected.getName(); + + expected.setName(previousName + "Changed"); + expected.setDescription("changed"); + expected.setDecisionStrategy(DecisionStrategy.CONSENSUS); + expected.getScopes().clear(); + expected.addScope("Scope B"); + expected.getPolicies().clear(); + expected.addPolicy("Policy C"); + + authorizationPage.navigateTo(); + authorizationPage.authorizationTabs().permissions().update(previousName, expected); + assertAlertSuccess(); + + authorizationPage.navigateTo(); + ScopePermission actual = authorizationPage.authorizationTabs().permissions().name(expected.getName()); + assertPolicy(expected, actual); + } + + @Test + public void testUpdateResourceScope() throws InterruptedException { + authorizationPage.navigateTo(); + ScopePermissionRepresentation expected = new ScopePermissionRepresentation(); + + expected.setName("Test Resource Scope Permission"); + expected.setDescription("description"); + expected.addResource("Resource A"); + expected.addScope("Scope A"); + expected.addPolicy("Policy C", "Policy A", "Policy B"); + + expected = createPermission(expected); + + String previousName = expected.getName(); + + expected.setName(previousName + "Changed"); + expected.setDescription("changed"); + expected.setDecisionStrategy(DecisionStrategy.CONSENSUS); + expected.getResources().clear(); + expected.addResource("Resource B"); + expected.getScopes().clear(); + expected.addScope("Scope B", "Scope C"); + expected.getPolicies().clear(); + expected.addPolicy("Policy C"); + + authorizationPage.navigateTo(); + authorizationPage.authorizationTabs().permissions().update(previousName, expected); + assertAlertSuccess(); + + authorizationPage.navigateTo(); + ScopePermission actual = authorizationPage.authorizationTabs().permissions().name(expected.getName()); + assertPolicy(expected, actual); + } + + @Test + public void testDelete() throws InterruptedException { + authorizationPage.navigateTo(); + ScopePermissionRepresentation expected = new ScopePermissionRepresentation(); + + expected.setName("Test Delete Scope Permission"); + expected.setDescription("description"); + expected.addScope("Scope C"); + 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 ScopePermissionRepresentation createPermission(ScopePermissionRepresentation expected) { + ScopePermission policy = authorizationPage.authorizationTabs().permissions().create(expected); + assertAlertSuccess(); + return assertPolicy(expected, policy); + } + + private ScopePermissionRepresentation assertPolicy(ScopePermissionRepresentation expected, ScopePermission policy) { + ScopePermissionRepresentation actual = policy.toRepresentation(); + + assertEquals(expected.getName(), actual.getName()); + assertEquals(expected.getDescription(), actual.getDescription()); + assertEquals(expected.getDecisionStrategy(), actual.getDecisionStrategy()); + + 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()); + + if (expected.getResources() != null) { + assertEquals(expected.getResources().size(), actual.getResources().size()); + assertEquals(0, actual.getResources().stream().filter(actualResource -> !expected.getResources().stream() + .filter(expectedResource -> actualResource.equals(expectedResource)) + .findFirst().isPresent()) + .count()); + } + + assertEquals(expected.getScopes().size(), actual.getScopes().size()); + assertEquals(0, actual.getScopes().stream().filter(actualScope -> !expected.getScopes().stream() + .filter(expectedScope -> actualScope.equals(expectedScope)) + .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 index 9e9d2e8479..6242c77be6 100644 --- 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 @@ -82,7 +82,7 @@ public class TimePolicyManagementTest extends AbstractAuthorizationSettingsTest } @Test - public void testDeletePolicy() throws InterruptedException { + public void testDelete() throws InterruptedException { authorizationPage.navigateTo(); TimePolicyRepresentation expected = new TimePolicyRepresentation(); diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-scope-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-scope-detail.html index 5da3a12798..cce7e2496e 100644 --- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-scope-detail.html +++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-scope-detail.html @@ -29,18 +29,18 @@ {{:: 'authz-permission-description.tooltip' | translate}}
- +
- +
{{:: 'authz-permission-scope-resource.tooltip' | translate}}
- +
- +
{{:: 'authz-permission-scope-scope.tooltip' | translate}}
- +
- +
{{:: 'authz-policy-apply-policy.tooltip' | translate}}
- +
-