[KEYCLOAK-3135] - Scope permission UI tests and reusable ui-select2 component
This commit is contained in:
parent
5e57e84384
commit
49547ccfbc
18 changed files with 795 additions and 508 deletions
|
@ -118,6 +118,10 @@ public class AbstractPolicyRepresentation {
|
||||||
return scopes;
|
return scopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setScopes(Set<String> scopes) {
|
||||||
|
this.scopes = scopes;
|
||||||
|
}
|
||||||
|
|
||||||
public void addScope(String... id) {
|
public void addScope(String... id) {
|
||||||
if (this.scopes == null) {
|
if (this.scopes == null) {
|
||||||
this.scopes = new HashSet<>();
|
this.scopes = new HashSet<>();
|
||||||
|
|
|
@ -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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
*/
|
||||||
|
public abstract class AbstractMultipleSelect2<R> {
|
||||||
|
|
||||||
|
@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<WebElement> result;
|
||||||
|
|
||||||
|
public void update(Set<R> values) {
|
||||||
|
Set<R> 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<R, String> identity();
|
||||||
|
|
||||||
|
public Set<R> getSelected() {
|
||||||
|
Set<R> values = new HashSet<>();
|
||||||
|
|
||||||
|
for (WebElement selected : getSelectedElements()) {
|
||||||
|
R value = representation().apply(selected);
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
values.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract List<WebElement> getSelectedElements();
|
||||||
|
|
||||||
|
protected abstract Function<WebElement, R> 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<WebElement, R, Boolean> 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
*/
|
||||||
|
public class MultipleStringSelect2 extends AbstractMultipleSelect2<String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Function<String, String> identity() {
|
||||||
|
return r -> r.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<WebElement> getSelectedElements() {
|
||||||
|
return getRoot().findElements(By.xpath(".//li[contains(@class,'select2-search-choice')]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Function<WebElement, String> representation() {
|
||||||
|
return webElement -> {
|
||||||
|
List<WebElement> element = webElement.findElements(By.tagName("div"));
|
||||||
|
|
||||||
|
if (element.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String value = element.get(0).getText();
|
||||||
|
|
||||||
|
return "".equals(value) ? null : value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
*/
|
||||||
|
public class SingleStringSelect2 extends AbstractMultipleSelect2<String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Function<String, String> identity() {
|
||||||
|
return r -> r.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<WebElement> getSelectedElements() {
|
||||||
|
return getRoot().findElements(By.xpath(".//span[contains(@class,'select2-chosen')]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Function<WebElement, String> representation() {
|
||||||
|
return webElement -> {
|
||||||
|
String value = webElement.getText();
|
||||||
|
return "".equals(value) ? null : value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BiFunction<WebElement, String, Boolean> 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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ import org.jboss.arquillian.graphene.page.Page;
|
||||||
import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
|
import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
|
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.console.page.clients.authorization.policy.PolicyTypeUI;
|
||||||
import org.keycloak.testsuite.page.Form;
|
import org.keycloak.testsuite.page.Form;
|
||||||
import org.keycloak.testsuite.util.WaitUtils;
|
import org.keycloak.testsuite.util.WaitUtils;
|
||||||
|
@ -43,6 +44,9 @@ public class Permissions extends Form {
|
||||||
@Page
|
@Page
|
||||||
private ResourcePermission resourcePermission;
|
private ResourcePermission resourcePermission;
|
||||||
|
|
||||||
|
@Page
|
||||||
|
private ScopePermission scopePermission;
|
||||||
|
|
||||||
public PermissionsTable permissions() {
|
public PermissionsTable permissions() {
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +61,9 @@ public class Permissions extends Form {
|
||||||
resourcePermission.form().save();
|
resourcePermission.form().save();
|
||||||
return (P) resourcePermission;
|
return (P) resourcePermission;
|
||||||
} else if ("scope".equals(type)) {
|
} else if ("scope".equals(type)) {
|
||||||
return null;
|
scopePermission.form().populate((ScopePermissionRepresentation) expected);
|
||||||
|
scopePermission.form().save();
|
||||||
|
return (P) scopePermission;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -73,6 +79,8 @@ public class Permissions extends Form {
|
||||||
|
|
||||||
if ("resource".equals(type)) {
|
if ("resource".equals(type)) {
|
||||||
resourcePermission.form().populate((ResourcePermissionRepresentation) representation);
|
resourcePermission.form().populate((ResourcePermissionRepresentation) representation);
|
||||||
|
} else if ("scope".equals(type)) {
|
||||||
|
scopePermission.form().populate((ScopePermissionRepresentation) representation);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -89,6 +97,8 @@ public class Permissions extends Form {
|
||||||
String type = actual.getType();
|
String type = actual.getType();
|
||||||
if ("resource".equals(type)) {
|
if ("resource".equals(type)) {
|
||||||
return (P) resourcePermission;
|
return (P) resourcePermission;
|
||||||
|
} else if ("scope".equals(type)) {
|
||||||
|
return (P) scopePermission;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,6 +116,8 @@ public class Permissions extends Form {
|
||||||
|
|
||||||
if ("resource".equals(type)) {
|
if ("resource".equals(type)) {
|
||||||
resourcePermission.form().delete();
|
resourcePermission.form().delete();
|
||||||
|
} else if ("scope".equals(type)) {
|
||||||
|
scopePermission.form().delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -16,22 +16,12 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.testsuite.console.page.clients.authorization.permission;
|
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.DecisionStrategy;
|
||||||
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
|
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.console.page.fragment.OnOffSwitch;
|
||||||
import org.keycloak.testsuite.page.Form;
|
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.WebElement;
|
||||||
import org.openqa.selenium.interactions.Actions;
|
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
import org.openqa.selenium.support.ui.Select;
|
import org.openqa.selenium.support.ui.Select;
|
||||||
|
|
||||||
|
@ -62,10 +52,10 @@ public class ResourcePermissionForm extends Form {
|
||||||
private WebElement confirmDelete;
|
private WebElement confirmDelete;
|
||||||
|
|
||||||
@FindBy(id = "s2id_policies")
|
@FindBy(id = "s2id_policies")
|
||||||
private PolicyInput policyInput;
|
private MultipleStringSelect2 policySelect;
|
||||||
|
|
||||||
@FindBy(id = "s2id_resources")
|
@FindBy(id = "s2id_resources")
|
||||||
private ResourceInput resourceInput;
|
private MultipleStringSelect2 resourceSelect;
|
||||||
|
|
||||||
public void populate(ResourcePermissionRepresentation expected) {
|
public void populate(ResourcePermissionRepresentation expected) {
|
||||||
setInputValue(name, expected.getName());
|
setInputValue(name, expected.getName());
|
||||||
|
@ -78,56 +68,10 @@ public class ResourcePermissionForm extends Form {
|
||||||
setInputValue(resourceType, expected.getResourceType());
|
setInputValue(resourceType, expected.getResourceType());
|
||||||
} else {
|
} else {
|
||||||
resourceTypeSwitch.setOn(false);
|
resourceTypeSwitch.setOn(false);
|
||||||
Set<String> selectedResources = resourceInput.getSelected();
|
resourceSelect.update(expected.getResources());
|
||||||
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();
|
policySelect.update(expected.getPolicies());
|
||||||
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();
|
save();
|
||||||
}
|
}
|
||||||
|
@ -143,122 +87,15 @@ public class ResourcePermissionForm extends Form {
|
||||||
representation.setName(getInputValue(name));
|
representation.setName(getInputValue(name));
|
||||||
representation.setDescription(getInputValue(description));
|
representation.setDescription(getInputValue(description));
|
||||||
representation.setDecisionStrategy(DecisionStrategy.valueOf(decisionStrategy.getFirstSelectedOption().getText().toUpperCase()));
|
representation.setDecisionStrategy(DecisionStrategy.valueOf(decisionStrategy.getFirstSelectedOption().getText().toUpperCase()));
|
||||||
representation.setPolicies(policyInput.getSelected());
|
representation.setPolicies(policySelect.getSelected());
|
||||||
representation.setResources(resourceInput.getSelected());
|
String inputValue = getInputValue(resourceType);
|
||||||
|
|
||||||
|
if (!"".equals(inputValue)) {
|
||||||
|
representation.setResourceType(inputValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
representation.setResources(resourceSelect.getSelected());
|
||||||
|
|
||||||
return representation;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
*/
|
||||||
|
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<String> 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<WebElement, String> representation() {
|
||||||
|
return super.representation().andThen(s -> "".equals(s) || s.contains("Any resource...") ? null : s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,21 +16,13 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.testsuite.console.page.clients.authorization.policy;
|
package org.keycloak.testsuite.console.page.clients.authorization.policy;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jboss.arquillian.graphene.fragment.Root;
|
|
||||||
import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation;
|
import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.Logic;
|
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.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.WebElement;
|
||||||
import org.openqa.selenium.interactions.Actions;
|
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
import org.openqa.selenium.support.ui.Select;
|
import org.openqa.selenium.support.ui.Select;
|
||||||
|
|
||||||
|
@ -52,7 +44,7 @@ public class AggregatePolicyForm extends Form {
|
||||||
private WebElement deleteButton;
|
private WebElement deleteButton;
|
||||||
|
|
||||||
@FindBy(id = "s2id_policies")
|
@FindBy(id = "s2id_policies")
|
||||||
private PolicyInput policyInput;
|
private MultipleStringSelect2 policySelect;
|
||||||
|
|
||||||
@FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']")
|
@FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']")
|
||||||
private WebElement confirmDelete;
|
private WebElement confirmDelete;
|
||||||
|
@ -62,12 +54,12 @@ public class AggregatePolicyForm extends Form {
|
||||||
setInputValue(description, expected.getDescription());
|
setInputValue(description, expected.getDescription());
|
||||||
logic.selectByValue(expected.getLogic().name());
|
logic.selectByValue(expected.getLogic().name());
|
||||||
|
|
||||||
Set<String> selectedPolicies = policyInput.getSelected();
|
Set<String> selectedPolicies = policySelect.getSelected();
|
||||||
Set<String> policies = expected.getPolicies();
|
Set<String> policies = expected.getPolicies();
|
||||||
|
|
||||||
for (String policy : policies) {
|
for (String policy : policies) {
|
||||||
if (!selectedPolicies.contains(policy)) {
|
if (!selectedPolicies.contains(policy)) {
|
||||||
policyInput.select(policy, driver);
|
policySelect.select(policy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +74,7 @@ public class AggregatePolicyForm extends Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isSelected) {
|
if (!isSelected) {
|
||||||
policyInput.unSelect(selected, driver);
|
policySelect.deselect(selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,66 +92,8 @@ public class AggregatePolicyForm extends Form {
|
||||||
representation.setName(getInputValue(name));
|
representation.setName(getInputValue(name));
|
||||||
representation.setDescription(getInputValue(description));
|
representation.setDescription(getInputValue(description));
|
||||||
representation.setLogic(Logic.valueOf(logic.getFirstSelectedOption().getText().toUpperCase()));
|
representation.setLogic(Logic.valueOf(logic.getFirstSelectedOption().getText().toUpperCase()));
|
||||||
representation.setPolicies(policyInput.getSelected());
|
representation.setPolicies(policySelect.getSelected());
|
||||||
|
|
||||||
return representation;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -18,21 +18,19 @@ package org.keycloak.testsuite.console.page.clients.authorization.policy;
|
||||||
|
|
||||||
import static org.openqa.selenium.By.tagName;
|
import static org.openqa.selenium.By.tagName;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
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.Logic;
|
||||||
import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
|
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.page.Form;
|
||||||
import org.keycloak.testsuite.util.WaitUtils;
|
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.Keys;
|
|
||||||
import org.openqa.selenium.WebDriver;
|
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.interactions.Actions;
|
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
import org.openqa.selenium.support.ui.Select;
|
import org.openqa.selenium.support.ui.Select;
|
||||||
|
|
||||||
|
@ -54,13 +52,13 @@ public class RolePolicyForm extends Form {
|
||||||
private WebElement deleteButton;
|
private WebElement deleteButton;
|
||||||
|
|
||||||
@FindBy(id = "s2id_roles")
|
@FindBy(id = "s2id_roles")
|
||||||
private RolesInput realmRolesInput;
|
private RoleMultipleSelect2 realmRoleSelect;
|
||||||
|
|
||||||
@FindBy(id = "clients")
|
@FindBy(id = "clients")
|
||||||
private Select clientsSelect;
|
private Select clientsSelect;
|
||||||
|
|
||||||
@FindBy(id = "s2id_clientRoles")
|
@FindBy(id = "s2id_clientRoles")
|
||||||
private ClientRolesInput clientRolesInput;
|
private ClientRoleSelect clientRoleSelect;
|
||||||
|
|
||||||
@FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']")
|
@FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']")
|
||||||
private WebElement confirmDelete;
|
private WebElement confirmDelete;
|
||||||
|
@ -78,16 +76,16 @@ public class RolePolicyForm extends Form {
|
||||||
if (clientRole) {
|
if (clientRole) {
|
||||||
String[] parts = role.getId().split("/");
|
String[] parts = role.getId().split("/");
|
||||||
clientsSelect.selectByVisibleText(parts[0]);
|
clientsSelect.selectByVisibleText(parts[0]);
|
||||||
clientRolesInput.select(parts[1], driver);
|
clientRoleSelect.select(role);
|
||||||
clientRolesInput.setRequired(parts[1], role);
|
clientRoleSelect.setRequired(role);
|
||||||
} else {
|
} else {
|
||||||
realmRolesInput.select(role.getId(), driver);
|
realmRoleSelect.select(role);
|
||||||
realmRolesInput.setRequired(role.getId(), role);
|
realmRoleSelect.setRequired(role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unSelect(roles, realmRolesInput.getSelected());
|
unSelect(roles, realmRoleSelect.getSelected());
|
||||||
unSelect(roles, clientRolesInput.getSelected());
|
unSelect(roles, clientRoleSelect.getSelected());
|
||||||
|
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
@ -107,9 +105,9 @@ public class RolePolicyForm extends Form {
|
||||||
boolean clientRole = selected.getId().indexOf('/') != -1;
|
boolean clientRole = selected.getId().indexOf('/') != -1;
|
||||||
|
|
||||||
if (clientRole) {
|
if (clientRole) {
|
||||||
clientRolesInput.unSelect(selected.getId().split("/")[1], driver);
|
clientRoleSelect.deselect(selected);
|
||||||
} else {
|
} else {
|
||||||
realmRolesInput.unSelect(selected.getId(), driver);
|
realmRoleSelect.deselect(selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,144 +125,58 @@ public class RolePolicyForm extends Form {
|
||||||
representation.setDescription(getInputValue(description));
|
representation.setDescription(getInputValue(description));
|
||||||
representation.setLogic(Logic.valueOf(logic.getFirstSelectedOption().getText().toUpperCase()));
|
representation.setLogic(Logic.valueOf(logic.getFirstSelectedOption().getText().toUpperCase()));
|
||||||
|
|
||||||
Set<RolePolicyRepresentation.RoleDefinition> roles = realmRolesInput.getSelected();
|
Set<RolePolicyRepresentation.RoleDefinition> roles = realmRoleSelect.getSelected();
|
||||||
|
|
||||||
roles.addAll(clientRolesInput.getSelected());
|
roles.addAll(clientRoleSelect.getSelected());
|
||||||
|
|
||||||
representation.setRoles(roles);
|
representation.setRoles(roles);
|
||||||
|
|
||||||
return representation;
|
return representation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RolesInput extends AbstractRolesInput {
|
public class RoleMultipleSelect2 extends AbstractMultipleSelect2<RolePolicyRepresentation.RoleDefinition> {
|
||||||
@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
|
@Override
|
||||||
protected WebElement getRemoveButton(List<WebElement> tds) {
|
protected Function<RolePolicyRepresentation.RoleDefinition, String> identity() {
|
||||||
return tds.get(2);
|
return role -> {
|
||||||
|
String id = role.getId();
|
||||||
|
return id.indexOf('/') != -1 ? id.split("/")[1] : id;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<WebElement> getSelectedElements() {
|
protected List<WebElement> 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
|
@Override
|
||||||
protected WebElement getRequiredColumn(List<WebElement> tds) {
|
protected Function<WebElement, RolePolicyRepresentation.RoleDefinition> representation() {
|
||||||
return tds.get(1);
|
return webElement -> {
|
||||||
}
|
List<WebElement> tds = webElement.findElements(tagName("td"));
|
||||||
}
|
RolePolicyRepresentation.RoleDefinition selectedRole = new RolePolicyRepresentation.RoleDefinition();
|
||||||
|
boolean clientRole = tds.size() == 4;
|
||||||
|
|
||||||
public class ClientRolesInput extends AbstractRolesInput {
|
selectedRole.setId(clientRole ? tds.get(1).getText() + "/" + tds.get(0).getText() : tds.get(0).getText());
|
||||||
@Override
|
selectedRole.setRequired(tds.get(clientRole ? 2 : 1).findElement(By.tagName("input")).isSelected());
|
||||||
protected WebElement getRemoveButton(List<WebElement> tds) {
|
|
||||||
return tds.get(3);
|
return selectedRole;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setRequired(RolePolicyRepresentation.RoleDefinition role) {
|
||||||
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();
|
Iterator<WebElement> iterator = getSelectedElements().iterator();
|
||||||
|
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
WebElement realmRole = iterator.next();
|
WebElement realmRole = iterator.next();
|
||||||
List<WebElement> tds = realmRole.findElements(tagName("td"));
|
List<WebElement> 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 (!roleName.getText().isEmpty()) {
|
||||||
if (tds.get(0).getText().equals(name)) {
|
if (roleName.getText().equals(getRoleId(role, clientRole))) {
|
||||||
getRemoveButton(tds).findElement(By.tagName("button")).click();
|
WebElement required = tds.get(clientRole ? 2 : 1).findElement(By.tagName("input"));
|
||||||
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()) {
|
if (required.isSelected() && role.isRequired()) {
|
||||||
return;
|
return;
|
||||||
|
@ -279,6 +191,34 @@ public class RolePolicyForm extends Form {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract WebElement getRequiredColumn(List<WebElement> tds);
|
@Override
|
||||||
|
protected BiFunction<WebElement, RolePolicyRepresentation.RoleDefinition, Boolean> deselect() {
|
||||||
|
return (webElement, roleDefinition) -> {
|
||||||
|
List<WebElement> 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<WebElement> 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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,21 +18,17 @@ package org.keycloak.testsuite.console.page.clients.authorization.policy;
|
||||||
|
|
||||||
import static org.openqa.selenium.By.tagName;
|
import static org.openqa.selenium.By.tagName;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
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.Logic;
|
||||||
import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
|
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.page.Form;
|
||||||
import org.keycloak.testsuite.util.WaitUtils;
|
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.Keys;
|
|
||||||
import org.openqa.selenium.WebDriver;
|
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.interactions.Actions;
|
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
import org.openqa.selenium.support.ui.Select;
|
import org.openqa.selenium.support.ui.Select;
|
||||||
|
|
||||||
|
@ -54,7 +50,7 @@ public class UserPolicyForm extends Form {
|
||||||
private WebElement deleteButton;
|
private WebElement deleteButton;
|
||||||
|
|
||||||
@FindBy(id = "s2id_users")
|
@FindBy(id = "s2id_users")
|
||||||
private UsersInput usersInput;
|
private UserSelect usersInput;
|
||||||
|
|
||||||
@FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']")
|
@FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']")
|
||||||
private WebElement confirmDelete;
|
private WebElement confirmDelete;
|
||||||
|
@ -64,34 +60,11 @@ public class UserPolicyForm extends Form {
|
||||||
setInputValue(description, expected.getDescription());
|
setInputValue(description, expected.getDescription());
|
||||||
logic.selectByValue(expected.getLogic().name());
|
logic.selectByValue(expected.getLogic().name());
|
||||||
|
|
||||||
Set<String> users = expected.getUsers();
|
usersInput.update(expected.getUsers());
|
||||||
|
|
||||||
for (String user : users) {
|
|
||||||
usersInput.select(user, driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
unSelect(users, usersInput.getSelected());
|
|
||||||
|
|
||||||
save();
|
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() {
|
public void delete() {
|
||||||
deleteButton.click();
|
deleteButton.click();
|
||||||
confirmDelete.click();
|
confirmDelete.click();
|
||||||
|
@ -108,83 +81,34 @@ public class UserPolicyForm extends Form {
|
||||||
return representation;
|
return representation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UsersInput extends AbstractUserInput {
|
public class UserSelect extends MultipleStringSelect2 {
|
||||||
@Override
|
|
||||||
protected WebElement getRemoveButton(List<WebElement> tds) {
|
|
||||||
return tds.get(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<WebElement> getSelectedElements() {
|
protected List<WebElement> getSelectedElements() {
|
||||||
return root.findElements(By.xpath("(//table[@id='selected-users'])/tbody/tr"));
|
return getRoot().findElements(By.xpath("(//table[@id='selected-users'])/tbody/tr")).stream()
|
||||||
}
|
.filter(webElement -> webElement.findElements(tagName("td")).size() > 1)
|
||||||
}
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
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() {
|
@Override
|
||||||
List<WebElement> users = getSelectedElements();
|
protected BiFunction<WebElement, String, Boolean> deselect() {
|
||||||
Set<String> values = new HashSet<>();
|
return (webElement, name) -> {
|
||||||
|
List<WebElement> tds = webElement.findElements(tagName("td"));
|
||||||
|
|
||||||
for (WebElement user : users) {
|
if (!tds.get(0).getText().isEmpty()) {
|
||||||
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)) {
|
if (tds.get(0).getText().equals(name)) {
|
||||||
getRemoveButton(tds).findElement(By.tagName("button")).click();
|
tds.get(1).findElement(By.tagName("button")).click();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract WebElement getRemoveButton(List<WebElement> tds);
|
@Override
|
||||||
|
protected Function<WebElement, String> representation() {
|
||||||
|
return webElement -> webElement.findElements(tagName("td")).get(0).getText();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -79,7 +79,7 @@ public class AggregatePolicyManagementTest extends AbstractAuthorizationSettings
|
||||||
authorizationPage.navigateTo();
|
authorizationPage.navigateTo();
|
||||||
AggregatePolicyRepresentation expected = new AggregatePolicyRepresentation();
|
AggregatePolicyRepresentation expected = new AggregatePolicyRepresentation();
|
||||||
|
|
||||||
expected.setName("Test Aggregate Policy");
|
expected.setName("Test Update Aggregate Policy");
|
||||||
expected.setDescription("description");
|
expected.setDescription("description");
|
||||||
expected.addPolicy("Policy A");
|
expected.addPolicy("Policy A");
|
||||||
expected.addPolicy("Policy B");
|
expected.addPolicy("Policy B");
|
||||||
|
@ -89,11 +89,11 @@ public class AggregatePolicyManagementTest extends AbstractAuthorizationSettings
|
||||||
|
|
||||||
String previousName = expected.getName();
|
String previousName = expected.getName();
|
||||||
|
|
||||||
expected.setName("Changed Test Aggregate Policy");
|
expected.setName("Changed Test Update Aggregate Policy");
|
||||||
expected.setDescription("Changed description");
|
expected.setDescription("Changed description");
|
||||||
expected.setLogic(Logic.NEGATIVE);
|
expected.setLogic(Logic.NEGATIVE);
|
||||||
|
expected.getPolicies().clear();
|
||||||
expected.setPolicies(expected.getPolicies().stream().filter(policy -> !policy.equals("Policy B")).collect(Collectors.toSet()));
|
expected.addPolicy("Policy A", "Policy C");
|
||||||
|
|
||||||
authorizationPage.navigateTo();
|
authorizationPage.navigateTo();
|
||||||
authorizationPage.authorizationTabs().policies().update(previousName, expected);
|
authorizationPage.authorizationTabs().policies().update(previousName, expected);
|
||||||
|
@ -106,11 +106,11 @@ public class AggregatePolicyManagementTest extends AbstractAuthorizationSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeletePolicy() throws InterruptedException {
|
public void testDelete() throws InterruptedException {
|
||||||
authorizationPage.navigateTo();
|
authorizationPage.navigateTo();
|
||||||
AggregatePolicyRepresentation expected = new AggregatePolicyRepresentation();
|
AggregatePolicyRepresentation expected = new AggregatePolicyRepresentation();
|
||||||
|
|
||||||
expected.setName("Test Aggregate Policy");
|
expected.setName("Test Delete Aggregate Policy");
|
||||||
expected.setDescription("description");
|
expected.setDescription("description");
|
||||||
expected.addPolicy("Policy C");
|
expected.addPolicy("Policy C");
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ public class JSPolicyManagementTest extends AbstractAuthorizationSettingsTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeletePolicy() throws InterruptedException {
|
public void testDelete() throws InterruptedException {
|
||||||
authorizationPage.navigateTo();
|
authorizationPage.navigateTo();
|
||||||
JSPolicyRepresentation expected = new JSPolicyRepresentation();
|
JSPolicyRepresentation expected = new JSPolicyRepresentation();
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,8 @@ public class ResourcePermissionManagementTest extends AbstractAuthorizationSetti
|
||||||
expected.setDecisionStrategy(DecisionStrategy.CONSENSUS);
|
expected.setDecisionStrategy(DecisionStrategy.CONSENSUS);
|
||||||
expected.getResources().clear();
|
expected.getResources().clear();
|
||||||
expected.addResource("Resource B");
|
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.navigateTo();
|
||||||
authorizationPage.authorizationTabs().permissions().update(previousName, expected);
|
authorizationPage.authorizationTabs().permissions().update(previousName, expected);
|
||||||
|
@ -118,7 +119,7 @@ public class ResourcePermissionManagementTest extends AbstractAuthorizationSetti
|
||||||
authorizationPage.navigateTo();
|
authorizationPage.navigateTo();
|
||||||
ResourcePermissionRepresentation expected = new ResourcePermissionRepresentation();
|
ResourcePermissionRepresentation expected = new ResourcePermissionRepresentation();
|
||||||
|
|
||||||
expected.setName("Test Resource B Permission");
|
expected.setName("Test Resource B Type Permission");
|
||||||
expected.setDescription("description");
|
expected.setDescription("description");
|
||||||
expected.setResourceType("test-resource-type");
|
expected.setResourceType("test-resource-type");
|
||||||
expected.addPolicy("Policy A");
|
expected.addPolicy("Policy A");
|
||||||
|
@ -129,7 +130,7 @@ public class ResourcePermissionManagementTest extends AbstractAuthorizationSetti
|
||||||
|
|
||||||
String previousName = expected.getName();
|
String previousName = expected.getName();
|
||||||
|
|
||||||
expected.setName("Changed Test Resource B Permission");
|
expected.setName("Changed Test Resource B Type Permission");
|
||||||
expected.setDescription("Changed description");
|
expected.setDescription("Changed description");
|
||||||
expected.setDecisionStrategy(DecisionStrategy.CONSENSUS);
|
expected.setDecisionStrategy(DecisionStrategy.CONSENSUS);
|
||||||
|
|
||||||
|
@ -147,7 +148,7 @@ public class ResourcePermissionManagementTest extends AbstractAuthorizationSetti
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeletePolicy() throws InterruptedException {
|
public void testDelete() throws InterruptedException {
|
||||||
authorizationPage.navigateTo();
|
authorizationPage.navigateTo();
|
||||||
ResourcePermissionRepresentation expected = new ResourcePermissionRepresentation();
|
ResourcePermissionRepresentation expected = new ResourcePermissionRepresentation();
|
||||||
|
|
||||||
|
@ -175,7 +176,16 @@ public class ResourcePermissionManagementTest extends AbstractAuthorizationSetti
|
||||||
|
|
||||||
assertEquals(expected.getName(), actual.getName());
|
assertEquals(expected.getName(), actual.getName());
|
||||||
assertEquals(expected.getDescription(), actual.getDescription());
|
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;
|
return actual;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ public class RolePolicyManagementTest extends AbstractAuthorizationSettingsTest
|
||||||
authorizationPage.navigateTo();
|
authorizationPage.navigateTo();
|
||||||
RolePolicyRepresentation expected = new RolePolicyRepresentation();
|
RolePolicyRepresentation expected = new RolePolicyRepresentation();
|
||||||
|
|
||||||
expected.setName("Test Realm Role Policy");
|
expected.setName("Test Update Realm Role Policy");
|
||||||
expected.setDescription("description");
|
expected.setDescription("description");
|
||||||
expected.addRole("Realm Role A");
|
expected.addRole("Realm Role A");
|
||||||
expected.addRole("Realm Role B");
|
expected.addRole("Realm Role B");
|
||||||
|
@ -100,7 +100,7 @@ public class RolePolicyManagementTest extends AbstractAuthorizationSettingsTest
|
||||||
authorizationPage.navigateTo();
|
authorizationPage.navigateTo();
|
||||||
RolePolicyRepresentation expected = new RolePolicyRepresentation();
|
RolePolicyRepresentation expected = new RolePolicyRepresentation();
|
||||||
|
|
||||||
expected.setName("Test Client Role Policy");
|
expected.setName("Test Update Client Role Policy");
|
||||||
expected.setDescription("description");
|
expected.setDescription("description");
|
||||||
|
|
||||||
String clientId = newClient.getClientId();
|
String clientId = newClient.getClientId();
|
||||||
|
@ -113,7 +113,7 @@ public class RolePolicyManagementTest extends AbstractAuthorizationSettingsTest
|
||||||
|
|
||||||
String previousName = expected.getName();
|
String previousName = expected.getName();
|
||||||
|
|
||||||
expected.setName("Changed Test Client Role Policy");
|
expected.setName("Changed Test Update Client Role Policy");
|
||||||
expected.setDescription("Changed description");
|
expected.setDescription("Changed description");
|
||||||
|
|
||||||
expected.setRoles(expected.getRoles().stream().filter(roleDefinition -> !roleDefinition.getId().contains("Client Role B")).collect(Collectors.toSet()));
|
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
|
@Test
|
||||||
public void testDeletePolicy() throws InterruptedException {
|
public void testDelete() throws InterruptedException {
|
||||||
authorizationPage.navigateTo();
|
authorizationPage.navigateTo();
|
||||||
RolePolicyRepresentation expected = new RolePolicyRepresentation();
|
RolePolicyRepresentation expected = new RolePolicyRepresentation();
|
||||||
|
|
||||||
expected.setName("Test Realm Role Policy");
|
expected.setName("Test Delete Role Policy");
|
||||||
expected.setDescription("description");
|
expected.setDescription("description");
|
||||||
expected.addRole("Realm Role A");
|
expected.addRole("Realm Role A");
|
||||||
expected.addRole("Realm Role B");
|
expected.addRole("Realm Role B");
|
||||||
|
@ -224,7 +224,7 @@ public class RolePolicyManagementTest extends AbstractAuthorizationSettingsTest
|
||||||
assertNotNull(actual.getRoles());
|
assertNotNull(actual.getRoles());
|
||||||
assertEquals(expected.getRoles().size(), actual.getRoles().size());
|
assertEquals(expected.getRoles().size(), actual.getRoles().size());
|
||||||
assertEquals(0, actual.getRoles().stream().filter(actualDefinition -> !expected.getRoles().stream()
|
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())
|
.findFirst().isPresent())
|
||||||
.count());
|
.count());
|
||||||
return actual;
|
return actual;
|
||||||
|
|
|
@ -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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -82,7 +82,7 @@ public class TimePolicyManagementTest extends AbstractAuthorizationSettingsTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeletePolicy() throws InterruptedException {
|
public void testDelete() throws InterruptedException {
|
||||||
authorizationPage.navigateTo();
|
authorizationPage.navigateTo();
|
||||||
TimePolicyRepresentation expected = new TimePolicyRepresentation();
|
TimePolicyRepresentation expected = new TimePolicyRepresentation();
|
||||||
|
|
||||||
|
|
|
@ -29,18 +29,18 @@
|
||||||
<kc-tooltip>{{:: 'authz-permission-description.tooltip' | translate}}</kc-tooltip>
|
<kc-tooltip>{{:: 'authz-permission-description.tooltip' | translate}}</kc-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group clearfix">
|
<div class="form-group clearfix">
|
||||||
<label class="col-md-2 control-label" for="reqActions">{{:: 'authz-resource' | translate}}</label>
|
<label class="col-md-2 control-label" for="resources">{{:: 'authz-resource' | translate}}</label>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<input type="hidden" ui-select2="resourcesUiSelect" data-ng-change="selectResource()" id="reqActions" data-ng-model="selectedResource" data-placeholder="{{:: 'authz-any-resource' | translate}}..." />
|
<input type="hidden" ui-select2="resourcesUiSelect" data-ng-change="selectResource()" id="resources" data-ng-model="selectedResource" data-placeholder="{{:: 'authz-any-resource' | translate}}..." />
|
||||||
</div>
|
</div>
|
||||||
<kc-tooltip>{{:: 'authz-permission-scope-resource.tooltip' | translate}}</kc-tooltip>
|
<kc-tooltip>{{:: 'authz-permission-scope-resource.tooltip' | translate}}</kc-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group clearfix" data-ng-show="selectedResource">
|
<div class="form-group clearfix" data-ng-show="selectedResource">
|
||||||
<label class="col-md-2 control-label" for="reqActions">{{:: 'authz-scopes' | translate}} <span class="required">*</span></label>
|
<label class="col-md-2 control-label" for="resourceScopes">{{:: 'authz-scopes' | translate}} <span class="required">*</span></label>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<select ui-select2 id="reqActions2"
|
<select ui-select2 id="resourceScopes"
|
||||||
data-ng-model="selectedScopes"
|
data-ng-model="selectedScopes"
|
||||||
data-placeholder="{{:: 'authz-any-scope' | translate}}..." multiple
|
data-placeholder="{{:: 'authz-any-scope' | translate}}..." multiple
|
||||||
data-ng-required="selectedResource != null">
|
data-ng-required="selectedResource != null">
|
||||||
|
@ -50,27 +50,27 @@
|
||||||
<kc-tooltip>{{:: 'authz-permission-scope-scope.tooltip' | translate}}</kc-tooltip>
|
<kc-tooltip>{{:: 'authz-permission-scope-scope.tooltip' | translate}}</kc-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group clearfix" data-ng-show="!selectedResource">
|
<div class="form-group clearfix" data-ng-show="!selectedResource">
|
||||||
<label class="col-md-2 control-label" for="reqActions">{{:: 'authz-scopes' | translate}} <span class="required">*</span></label>
|
<label class="col-md-2 control-label" for="scopes">{{:: 'authz-scopes' | translate}} <span class="required">*</span></label>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<input type="hidden" ui-select2="scopesUiSelect" id="reqActions" data-ng-model="selectedScopes" data-placeholder="{{:: 'authz-any-scope' | translate}}..." multiple data-ng-required="selectedResource == null" />
|
<input type="hidden" ui-select2="scopesUiSelect" id="scopes" data-ng-model="selectedScopes" data-placeholder="{{:: 'authz-any-scope' | translate}}..." multiple data-ng-required="selectedResource == null" />
|
||||||
</div>
|
</div>
|
||||||
<kc-tooltip>{{:: 'authz-permission-scope-scope.tooltip' | translate}}</kc-tooltip>
|
<kc-tooltip>{{:: 'authz-permission-scope-scope.tooltip' | translate}}</kc-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group clearfix">
|
<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">
|
<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>
|
</div>
|
||||||
|
|
||||||
<kc-tooltip>{{:: 'authz-policy-apply-policy.tooltip' | translate}}</kc-tooltip>
|
<kc-tooltip>{{:: 'authz-policy-apply-policy.tooltip' | translate}}</kc-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group clearfix">
|
<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">
|
<div class="col-sm-2">
|
||||||
<select class="form-control" id="policy.decisionStrategy"
|
<select class="form-control" id="decisionStrategy"
|
||||||
data-ng-model="policy.decisionStrategy"
|
data-ng-model="policy.decisionStrategy"
|
||||||
ng-change="selectDecisionStrategy()">
|
ng-change="selectDecisionStrategy()">
|
||||||
<option value="UNANIMOUS">{{:: 'authz-policy-decision-strategy-unanimous' | translate}}</option>
|
<option value="UNANIMOUS">{{:: 'authz-policy-decision-strategy-unanimous' | translate}}</option>
|
||||||
|
|
Loading…
Reference in a new issue