keycloak-uncached

Changes

Details

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 fcb5b8c..2872658 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
@@ -56,16 +56,16 @@ public class Permissions extends Form {
         return table;
     }
 
-    public <P extends PolicyTypeUI> P create(AbstractPolicyRepresentation expected) {
+    public <P extends PolicyTypeUI> P create(AbstractPolicyRepresentation expected, boolean save) {
         String type = expected.getType();
 
         createSelect.selectByValue(type);
 
         if ("resource".equals(type)) {
-            resourcePermission.form().populate((ResourcePermissionRepresentation) expected);
+            resourcePermission.form().populate((ResourcePermissionRepresentation) expected, save);
             return (P) resourcePermission;
         } else if ("scope".equals(type)) {
-            scopePermission.form().populate((ScopePermissionRepresentation) expected);
+            scopePermission.form().populate((ScopePermissionRepresentation) expected, save);
             return (P) scopePermission;
         }
 
@@ -73,6 +73,10 @@ public class Permissions extends Form {
     }
 
     public void update(String name, AbstractPolicyRepresentation representation) {
+        update(name, representation, true);
+    }
+
+    public void update(String name, AbstractPolicyRepresentation representation, boolean save) {
         for (WebElement row : permissions().rows()) {
             PolicyRepresentation actual = permissions().toRepresentation(row);
             if (actual.getName().equalsIgnoreCase(name)) {
@@ -81,9 +85,9 @@ public class Permissions extends Form {
                 String type = representation.getType();
 
                 if ("resource".equals(type)) {
-                    resourcePermission.form().populate((ResourcePermissionRepresentation) representation);
+                    resourcePermission.form().populate((ResourcePermissionRepresentation) representation, save);
                 } else if ("scope".equals(type)) {
-                    scopePermission.form().populate((ScopePermissionRepresentation) representation);
+                    scopePermission.form().populate((ScopePermissionRepresentation) representation, save);
                 }
 
                 return;
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ResourcePermission.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ResourcePermission.java
index d6c4f3a..ba5302d 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ResourcePermission.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ResourcePermission.java
@@ -17,7 +17,7 @@
 package org.keycloak.testsuite.console.page.clients.authorization.permission;
 
 import org.jboss.arquillian.graphene.page.Page;
-import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
 import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
 import org.keycloak.testsuite.console.page.clients.authorization.policy.PolicyTypeUI;
 
@@ -38,6 +38,10 @@ public class ResourcePermission implements PolicyTypeUI {
     }
 
     public void update(ResourcePermissionRepresentation expected) {
-        form().populate(expected);
+        form().populate(expected, true);
+    }
+
+    public void createPolicy(AbstractPolicyRepresentation expected) {
+        form().createPolicy(expected);
     }
 }
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ResourcePermissionForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/ResourcePermissionForm.java
index d53f820..b473044 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,8 +16,27 @@
  */
 package org.keycloak.testsuite.console.page.clients.authorization.permission;
 
+import static org.keycloak.testsuite.util.UIUtils.performOperationWithPageReload;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
 import org.keycloak.representations.idm.authorization.DecisionStrategy;
+import org.keycloak.representations.idm.authorization.GroupPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
 import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
+import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.RulePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.TimePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.ClientPolicy;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.GroupPolicy;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.JSPolicy;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.PolicySelect;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.RolePolicy;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.RulePolicy;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.TimePolicy;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.UserPolicy;
 import org.keycloak.testsuite.console.page.fragment.ModalDialog;
 import org.keycloak.testsuite.console.page.fragment.MultipleStringSelect2;
 import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
@@ -53,12 +72,36 @@ public class ResourcePermissionForm extends Form {
     protected ModalDialog modalDialog;
 
     @FindBy(id = "s2id_policies")
-    private MultipleStringSelect2 policySelect;
+    private PolicySelect policySelect;
 
     @FindBy(id = "s2id_resources")
     private MultipleStringSelect2 resourceSelect;
 
-    public void populate(ResourcePermissionRepresentation expected) {
+    @FindBy(id = "create-policy")
+    private Select createPolicySelect;
+
+    @Page
+    private RolePolicy rolePolicy;
+
+    @Page
+    private UserPolicy userPolicy;
+
+    @Page
+    private ClientPolicy clientPolicy;
+
+    @Page
+    private JSPolicy jsPolicy;
+
+    @Page
+    private TimePolicy timePolicy;
+
+    @Page
+    private RulePolicy rulePolicy;
+
+    @Page
+    private GroupPolicy groupPolicy;
+
+    public void populate(ResourcePermissionRepresentation expected, boolean save) {
         setInputValue(name, expected.getName());
         setInputValue(description, expected.getDescription());
         decisionStrategy.selectByValue(expected.getDecisionStrategy().name());
@@ -76,7 +119,9 @@ public class ResourcePermissionForm extends Form {
             policySelect.update(expected.getPolicies());
         }
 
-        save();
+        if (save) {
+            save();
+        }
     }
 
     public void delete() {
@@ -101,4 +146,24 @@ public class ResourcePermissionForm extends Form {
 
         return representation;
     }
+
+    public void createPolicy(AbstractPolicyRepresentation expected) {
+        performOperationWithPageReload(() -> createPolicySelect.selectByValue(expected.getType()));
+
+        if ("role".equals(expected.getType())) {
+            rolePolicy.form().populate((RolePolicyRepresentation) expected, true);
+        } else if ("user".equalsIgnoreCase(expected.getType())) {
+            userPolicy.form().populate((UserPolicyRepresentation) expected, true);
+        } else if ("client".equalsIgnoreCase(expected.getType())) {
+            clientPolicy.form().populate((ClientPolicyRepresentation) expected, true);
+        } else if ("js".equalsIgnoreCase(expected.getType())) {
+            jsPolicy.form().populate((JSPolicyRepresentation) expected, true);
+        } else if ("time".equalsIgnoreCase(expected.getType())) {
+            timePolicy.form().populate((TimePolicyRepresentation) expected, true);
+        } else if ("rules".equalsIgnoreCase(expected.getType())) {
+            rulePolicy.form().populate((RulePolicyRepresentation) expected, true);
+        } else if ("group".equalsIgnoreCase(expected.getType())) {
+            groupPolicy.form().populate((GroupPolicyRepresentation) expected, true);
+        }
+    }
 }
\ 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
index 5b392ad..cfeba8e 100644
--- 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
@@ -17,7 +17,7 @@
 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.AbstractPolicyRepresentation;
 import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation;
 import org.keycloak.testsuite.console.page.clients.authorization.policy.PolicyTypeUI;
 
@@ -38,6 +38,14 @@ public class ScopePermission implements PolicyTypeUI {
     }
 
     public void update(ScopePermissionRepresentation expected) {
-        form().populate(expected);
+        update(expected, true);
+    }
+
+    public void update(ScopePermissionRepresentation expected, boolean save) {
+        form().populate(expected, save);
+    }
+
+    public void createPolicy(AbstractPolicyRepresentation expected) {
+        form().createPolicy(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
index 696ff22..4172843 100644
--- 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
@@ -16,11 +16,30 @@
  */
 package org.keycloak.testsuite.console.page.clients.authorization.permission;
 
+import static org.keycloak.testsuite.util.UIUtils.performOperationWithPageReload;
+
 import java.util.Set;
 import java.util.function.Function;
 
+import org.jboss.arquillian.graphene.page.Page;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
 import org.keycloak.representations.idm.authorization.DecisionStrategy;
+import org.keycloak.representations.idm.authorization.GroupPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.RulePolicyRepresentation;
 import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation;
+import org.keycloak.representations.idm.authorization.TimePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.ClientPolicy;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.GroupPolicy;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.JSPolicy;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.PolicySelect;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.RolePolicy;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.RulePolicy;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.TimePolicy;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.UserPolicy;
 import org.keycloak.testsuite.console.page.fragment.ModalDialog;
 import org.keycloak.testsuite.console.page.fragment.MultipleStringSelect2;
 import org.keycloak.testsuite.console.page.fragment.SingleStringSelect2;
@@ -50,7 +69,7 @@ public class ScopePermissionForm extends Form {
     protected ModalDialog modalDialog;
 
     @FindBy(id = "s2id_policies")
-    private MultipleStringSelect2 policySelect;
+    private PolicySelect policySelect;
 
     @FindBy(id = "s2id_scopes")
     private MultipleStringSelect2 scopeSelect;
@@ -61,7 +80,31 @@ public class ScopePermissionForm extends Form {
     @FindBy(id = "s2id_resources")
     private ResourceSelect resourceSelect;
 
-    public void populate(ScopePermissionRepresentation expected) {
+    @FindBy(id = "create-policy")
+    private Select createPolicySelect;
+
+    @Page
+    private RolePolicy rolePolicy;
+
+    @Page
+    private UserPolicy userPolicy;
+
+    @Page
+    private ClientPolicy clientPolicy;
+
+    @Page
+    private JSPolicy jsPolicy;
+
+    @Page
+    private TimePolicy timePolicy;
+
+    @Page
+    private RulePolicy rulePolicy;
+
+    @Page
+    private GroupPolicy groupPolicy;
+
+    public void populate(ScopePermissionRepresentation expected, boolean save) {
         setInputValue(name, expected.getName());
         setInputValue(description, expected.getDescription());
         decisionStrategy.selectByValue(expected.getDecisionStrategy().name());
@@ -79,7 +122,9 @@ public class ScopePermissionForm extends Form {
             policySelect.update(expected.getPolicies());
         }
 
-        save();
+        if (save) {
+            save();
+        }
     }
 
     public void delete() {
@@ -107,4 +152,24 @@ public class ScopePermissionForm extends Form {
             return super.representation().andThen(s -> "".equals(s) || s.contains("Any resource...") ? null : s);
         }
     }
+
+    public void createPolicy(AbstractPolicyRepresentation expected) {
+        performOperationWithPageReload(() -> createPolicySelect.selectByValue(expected.getType()));
+
+        if ("role".equals(expected.getType())) {
+            rolePolicy.form().populate((RolePolicyRepresentation) expected, true);
+        } else if ("user".equalsIgnoreCase(expected.getType())) {
+            userPolicy.form().populate((UserPolicyRepresentation) expected, true);
+        } else if ("client".equalsIgnoreCase(expected.getType())) {
+            clientPolicy.form().populate((ClientPolicyRepresentation) expected, true);
+        } else if ("js".equalsIgnoreCase(expected.getType())) {
+            jsPolicy.form().populate((JSPolicyRepresentation) expected, true);
+        } else if ("time".equalsIgnoreCase(expected.getType())) {
+            timePolicy.form().populate((TimePolicyRepresentation) expected, true);
+        } else if ("rules".equalsIgnoreCase(expected.getType())) {
+            rulePolicy.form().populate((RulePolicyRepresentation) expected, true);
+        } else if ("group".equalsIgnoreCase(expected.getType())) {
+            groupPolicy.form().populate((GroupPolicyRepresentation) expected, true);
+        }
+    }
 }
\ 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 8ed8c39..732f820 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
@@ -17,13 +17,8 @@
 package org.keycloak.testsuite.console.page.clients.authorization.policy;
 
 import static org.keycloak.testsuite.util.UIUtils.performOperationWithPageReload;
-import static org.openqa.selenium.By.tagName;
 
-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.page.Page;
 import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
@@ -37,9 +32,7 @@ import org.keycloak.representations.idm.authorization.RulePolicyRepresentation;
 import org.keycloak.representations.idm.authorization.TimePolicyRepresentation;
 import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
 import org.keycloak.testsuite.console.page.fragment.ModalDialog;
-import org.keycloak.testsuite.console.page.fragment.MultipleStringSelect2;
 import org.keycloak.testsuite.page.Form;
-import org.openqa.selenium.By;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.FindBy;
 import org.openqa.selenium.support.ui.Select;
@@ -162,35 +155,4 @@ public class AggregatePolicyForm extends Form {
             groupPolicy.form().populate((GroupPolicyRepresentation) expected, true);
         }
     }
-
-    public class PolicySelect extends MultipleStringSelect2 {
-
-        @Override
-        protected List<WebElement> getSelectedElements() {
-            return getRoot().findElements(By.xpath("(//table[@id='selected-policies'])/tbody/tr")).stream()
-                    .filter(webElement -> webElement.findElements(tagName("td")).size() > 1)
-                    .collect(Collectors.toList());
-        }
-
-        @Override
-        protected BiFunction<WebElement, String, Boolean> deselect() {
-            return (webElement, name) -> {
-                List<WebElement> tds = webElement.findElements(tagName("td"));
-
-                if (!tds.get(0).getText().isEmpty()) {
-                    if (tds.get(0).getText().equals(name)) {
-                        tds.get(3).click();
-                        return true;
-                    }
-                }
-
-                return false;
-            };
-        }
-
-        @Override
-        protected Function<WebElement, String> 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/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/PolicySelect.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/PolicySelect.java
new file mode 100644
index 0000000..ffae31d
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/PolicySelect.java
@@ -0,0 +1,59 @@
+/*
+ * 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.clients.authorization.policy;
+
+import static org.openqa.selenium.By.tagName;
+
+import java.util.List;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.keycloak.testsuite.console.page.fragment.MultipleStringSelect2;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+public class PolicySelect extends MultipleStringSelect2 {
+
+    @Override
+    protected List<WebElement> getSelectedElements() {
+        return getRoot().findElements(By.xpath("(//table[@id='selected-policies'])/tbody/tr")).stream()
+                .filter(webElement -> webElement.findElements(tagName("td")).size() > 1)
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    protected BiFunction<WebElement, String, Boolean> deselect() {
+        return (webElement, name) -> {
+            List<WebElement> tds = webElement.findElements(tagName("td"));
+
+            if (!tds.get(0).getText().isEmpty()) {
+                if (tds.get(0).getText().equals(name)) {
+                    tds.get(3).click();
+                    return true;
+                }
+            }
+
+            return false;
+        };
+    }
+
+    @Override
+    protected Function<WebElement, String> representation() {
+        return webElement -> webElement.findElements(tagName("td")).get(0).getText();
+    }
+}
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 8ac8b3b..7c3597c 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
@@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import java.util.UUID;
 import java.util.stream.Collectors;
 
 import org.junit.Before;
@@ -30,12 +31,14 @@ 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.AggregatePolicyRepresentation;
 import org.keycloak.representations.idm.authorization.DecisionStrategy;
 import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
 import org.keycloak.representations.idm.authorization.ResourceRepresentation;
 import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
 import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
 import org.keycloak.testsuite.console.page.clients.authorization.permission.ResourcePermission;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.AggregatePolicy;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -207,8 +210,36 @@ public class ResourcePermissionManagementTest extends AbstractAuthorizationSetti
         assertNull(authorizationPage.authorizationTabs().permissions().permissions().findByName(expected.getName()));
     }
 
+    @Test
+    public void testCreateWithChild() {
+        ResourcePermissionRepresentation expected = new ResourcePermissionRepresentation();
+
+        expected.setName(UUID.randomUUID().toString());
+        expected.setDescription("description");
+        expected.addResource("Resource B");
+        expected.addPolicy("Policy C");
+
+        ResourcePermission policy = authorizationPage.authorizationTabs().permissions().create(expected, false);
+
+        RolePolicyRepresentation childPolicy = new RolePolicyRepresentation();
+
+        childPolicy.setName(UUID.randomUUID().toString());
+        childPolicy.addRole("Role A");
+
+        policy.createPolicy(childPolicy);
+        policy.form().save();
+
+        assertAlertSuccess();
+
+        expected.addPolicy(childPolicy.getName());
+
+        authorizationPage.navigateTo();
+        ResourcePermission actual = authorizationPage.authorizationTabs().permissions().name(expected.getName());
+        assertPolicy(expected, actual);
+    }
+
     private ResourcePermissionRepresentation createPermission(ResourcePermissionRepresentation expected) {
-        ResourcePermission policy = authorizationPage.authorizationTabs().permissions().create(expected);
+        ResourcePermission policy = authorizationPage.authorizationTabs().permissions().create(expected, true);
         assertAlertSuccess();
         return assertPolicy(expected, policy);
     }
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
index 7599537..2e2804f 100644
--- 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
@@ -20,6 +20,8 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import java.util.UUID;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.keycloak.admin.client.resource.AuthorizationResource;
@@ -29,11 +31,13 @@ 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.ResourcePermissionRepresentation;
 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;
 
 /**
@@ -210,8 +214,70 @@ public class ScopePermissionManagementTest extends AbstractAuthorizationSettings
         assertNull(authorizationPage.authorizationTabs().permissions().permissions().findByName(expected.getName()));
     }
 
+    @Test
+    public void testCreateUpdateWithChild() {
+        ScopePermissionRepresentation expected = new ScopePermissionRepresentation();
+
+        expected.setName(UUID.randomUUID().toString());
+        expected.setDescription("description");
+        expected.addScope("Scope C");
+        expected.addPolicy("Policy C");
+
+        ScopePermission policy = authorizationPage.authorizationTabs().permissions().create(expected, false);
+
+        RolePolicyRepresentation childPolicy = new RolePolicyRepresentation();
+
+        childPolicy.setName(UUID.randomUUID().toString());
+        childPolicy.addRole("Role A");
+
+        policy.createPolicy(childPolicy);
+        policy.form().save();
+        assertAlertSuccess();
+
+        expected.addPolicy(childPolicy.getName());
+
+        authorizationPage.navigateTo();
+        ScopePermission actual = authorizationPage.authorizationTabs().permissions().name(expected.getName());
+        assertPolicy(expected, actual);
+
+        RolePolicyRepresentation childPolicy2 = new RolePolicyRepresentation();
+
+        childPolicy2.setName(UUID.randomUUID().toString());
+        childPolicy2.addRole("Role A");
+
+        policy.createPolicy(childPolicy2);
+        policy.form().save();
+        assertAlertSuccess();
+        expected.addPolicy(childPolicy2.getName());
+
+        authorizationPage.navigateTo();
+        actual = authorizationPage.authorizationTabs().permissions().name(expected.getName());
+        assertPolicy(expected, actual);
+
+        expected.addResource("Resource B");
+        expected.getScopes().clear();
+        expected.addScope("Scope B", "Scope C");
+        expected.getScopes().remove("Policy C");
+
+        RolePolicyRepresentation childPolicy3 = new RolePolicyRepresentation();
+
+        childPolicy3.setName(UUID.randomUUID().toString());
+        childPolicy3.addRole("Role A");
+
+        policy.update(expected, false);
+
+        policy.createPolicy(childPolicy3);
+        policy.form().save();
+        assertAlertSuccess();
+        expected.addPolicy(childPolicy3.getName());
+
+        authorizationPage.navigateTo();
+        actual = authorizationPage.authorizationTabs().permissions().name(expected.getName());
+        assertPolicy(expected, actual);
+    }
+
     private ScopePermissionRepresentation createPermission(ScopePermissionRepresentation expected) {
-        ScopePermission policy = authorizationPage.authorizationTabs().permissions().create(expected);
+        ScopePermission policy = authorizationPage.authorizationTabs().permissions().create(expected, true);
         assertAlertSuccess();
         return assertPolicy(expected, policy);
     }
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html
index cbd06fd..5bba036 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html
@@ -82,7 +82,8 @@
                         </thead>
                         <tbody>
                         <tr ng-repeat="policy in selectedPolicies">
-                            <td><a href="" data-ng-click="detailPolicy(policy)">{{policy.name}}</a></td>
+                            <td data-ng-hide="historyBackOnSaveOrCancel"><a href="" data-ng-click="detailPolicy(policy)">{{policy.name}}</a></td>
+                            <td data-ng-show="historyBackOnSaveOrCancel">{{policy.name}}</td>
                             <td>{{policy.description}}</td>
                             <td class="kc-action-cell" ng-click="removePolicy(selectedPolicies, policy);">
                                 {{:: 'remove' | translate}}
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 4f469a2..37e8904 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
@@ -86,7 +86,8 @@
                         </thead>
                         <tbody>
                         <tr ng-repeat="policy in selectedPolicies">
-                            <td><a href="" data-ng-click="detailPolicy(policy)">{{policy.name}}</a></td>
+                            <td data-ng-hide="historyBackOnSaveOrCancel"><a href="" data-ng-click="detailPolicy(policy)">{{policy.name}}</a></td>
+                            <td data-ng-show="historyBackOnSaveOrCancel">{{policy.name}}</td>
                             <td>{{policy.description}}</td>
                             <td class="kc-action-cell" ng-click="removePolicy(selectedPolicies, policy);">
                                 {{:: 'remove' | translate}}