From eba47b3c8961e668d08b9a206fdf07bccfee6617 Mon Sep 17 00:00:00 2001 From: pedroigor Date: Mon, 11 Dec 2017 18:45:59 -0200 Subject: [PATCH] [KEYCLOAK-5806] - Create policy button to Aggregated Policies --- .../authorization/policy/AggregatePolicy.java | 8 +- .../policy/AggregatePolicyForm.java | 37 +++- .../authorization/policy/ClientPolicy.java | 2 +- .../policy/ClientPolicyForm.java | 6 +- .../authorization/policy/GroupPolicy.java | 3 +- .../authorization/policy/GroupPolicyForm.java | 6 +- .../authorization/policy/JSPolicy.java | 3 +- .../authorization/policy/JSPolicyForm.java | 6 +- .../authorization/policy/Policies.java | 38 ++-- .../authorization/policy/RolePolicy.java | 2 +- .../authorization/policy/RolePolicyForm.java | 6 +- .../authorization/policy/RulePolicy.java | 2 +- .../authorization/policy/RulePolicyForm.java | 6 +- .../authorization/policy/TimePolicy.java | 2 +- .../authorization/policy/TimePolicyForm.java | 6 +- .../authorization/policy/UserPolicy.java | 2 +- .../authorization/policy/UserPolicyForm.java | 6 +- .../AggregatePolicyManagementTest.java | 81 ++++++++ .../messages/admin-messages_en.properties | 4 +- .../resources/js/authz/authz-controller.js | 195 +++++++++++++++--- .../resources/js/authz/authz-services.js | 8 +- ...source-server-policy-aggregate-detail.html | 26 ++- .../resource-server-policy-client-detail.html | 2 + .../resource-server-policy-drools-detail.html | 2 + .../resource-server-policy-group-detail.html | 2 + .../resource-server-policy-js-detail.html | 2 + .../resource-server-policy-role-detail.html | 2 + .../resource-server-policy-time-detail.html | 2 + .../resource-server-policy-user-detail.html | 2 + 29 files changed, 385 insertions(+), 84 deletions(-) diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicy.java index 3a27d2b448..e87e27c587 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicy.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicy.java @@ -17,8 +17,8 @@ package org.keycloak.testsuite.console.page.clients.authorization.policy; import org.jboss.arquillian.graphene.page.Page; +import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation; import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation; -import org.keycloak.representations.idm.authorization.UserPolicyRepresentation; /** * @author Pedro Igor @@ -37,6 +37,10 @@ public class AggregatePolicy implements PolicyTypeUI { } public void update(AggregatePolicyRepresentation 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/policy/AggregatePolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicyForm.java index 12c4289d59..956e1ae26d 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicyForm.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/AggregatePolicyForm.java @@ -16,10 +16,15 @@ */ package org.keycloak.testsuite.console.page.clients.authorization.policy; +import static org.keycloak.testsuite.util.UIUtils.performOperationWithPageReload; + import java.util.Set; +import org.jboss.arquillian.graphene.page.Page; +import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation; import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation; import org.keycloak.representations.idm.authorization.Logic; +import org.keycloak.representations.idm.authorization.RolePolicyRepresentation; import org.keycloak.testsuite.console.page.fragment.ModalDialog; import org.keycloak.testsuite.console.page.fragment.MultipleStringSelect2; import org.keycloak.testsuite.page.Form; @@ -50,7 +55,16 @@ public class AggregatePolicyForm extends Form { @FindBy(xpath = "//div[@class='modal-dialog']") protected ModalDialog modalDialog; - public void populate(AggregatePolicyRepresentation expected) { + @FindBy(id = "create-policy-btn") + private WebElement createPolicyBtn; + + @FindBy(id = "create-policy") + private Select createPolicySelect; + + @Page + private RolePolicy rolePolicy; + + public void populate(AggregatePolicyRepresentation expected, boolean save) { setInputValue(name, expected.getName()); setInputValue(description, expected.getDescription()); logic.selectByValue(expected.getLogic().name()); @@ -58,9 +72,11 @@ public class AggregatePolicyForm extends Form { Set selectedPolicies = policySelect.getSelected(); Set policies = expected.getPolicies(); - for (String policy : policies) { - if (!selectedPolicies.contains(policy)) { - policySelect.select(policy); + if (policies != null) { + for (String policy : policies) { + if (!selectedPolicies.contains(policy)) { + policySelect.select(policy); + } } } @@ -79,7 +95,9 @@ public class AggregatePolicyForm extends Form { } } - save(); + if (save) { + save(); + } } public void delete() { @@ -97,4 +115,13 @@ public class AggregatePolicyForm extends Form { return representation; } + + public void createPolicy(AbstractPolicyRepresentation expected) { + createPolicyBtn.click(); + performOperationWithPageReload(() -> createPolicySelect.selectByValue(expected.getType())); + + if ("role".equals(expected.getType())) { + rolePolicy.form().populate((RolePolicyRepresentation) 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/ClientPolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicy.java index fe85623928..1b582ce767 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicy.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicy.java @@ -36,6 +36,6 @@ public class ClientPolicy implements PolicyTypeUI { } public void update(ClientPolicyRepresentation expected) { - form().populate(expected); + form().populate(expected, true); } } diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicyForm.java index cedaceeca8..ad74d60446 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicyForm.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicyForm.java @@ -56,14 +56,16 @@ public class ClientPolicyForm extends Form { @FindBy(xpath = "//div[@class='modal-dialog']") protected ModalDialog modalDialog; - public void populate(ClientPolicyRepresentation expected) { + public void populate(ClientPolicyRepresentation expected, boolean save) { setInputValue(name, expected.getName()); setInputValue(description, expected.getDescription()); logic.selectByValue(expected.getLogic().name()); clientsInput.update(expected.getClients()); - save(); + if (save) { + save(); + } } public void delete() { diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicy.java index 2fd68f4fcf..39703a5328 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicy.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicy.java @@ -18,7 +18,6 @@ package org.keycloak.testsuite.console.page.clients.authorization.policy; import org.jboss.arquillian.graphene.page.Page; import org.keycloak.representations.idm.authorization.GroupPolicyRepresentation; -import org.keycloak.representations.idm.authorization.RolePolicyRepresentation; /** * @author Pedro Igor @@ -37,6 +36,6 @@ public class GroupPolicy implements PolicyTypeUI { } public void update(GroupPolicyRepresentation expected) { - form().populate(expected); + form().populate(expected, true); } } diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicyForm.java index e3591e3318..3ca088e051 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicyForm.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicyForm.java @@ -63,7 +63,7 @@ public class GroupPolicyForm extends Form { @Drone private WebDriver driver; - public void populate(GroupPolicyRepresentation expected) { + public void populate(GroupPolicyRepresentation expected, boolean save) { setInputValue(name, expected.getName()); setInputValue(description, expected.getDescription()); setInputValue(groupsClaim, expected.getGroupsClaim()); @@ -109,7 +109,9 @@ public class GroupPolicyForm extends Form { }); } - save(); + if (save) { + save(); + } } private void unselect(String path) { diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicy.java index 94fbb08473..3f66ff36cc 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicy.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicy.java @@ -17,7 +17,6 @@ package org.keycloak.testsuite.console.page.clients.authorization.policy; import org.jboss.arquillian.graphene.page.Page; -import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation; import org.keycloak.representations.idm.authorization.JSPolicyRepresentation; /** @@ -37,6 +36,6 @@ public class JSPolicy implements PolicyTypeUI { } public void update(JSPolicyRepresentation expected) { - form().populate(expected); + form().populate(expected, true); } } diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicyForm.java index 9c1c1eaa8f..cb987a91ef 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicyForm.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/JSPolicyForm.java @@ -45,7 +45,7 @@ public class JSPolicyForm extends Form { @FindBy(xpath = "//div[@class='modal-dialog']") protected ModalDialog modalDialog; - public void populate(JSPolicyRepresentation expected) { + public void populate(JSPolicyRepresentation expected, boolean save) { setInputValue(name, expected.getName()); setInputValue(description, expected.getDescription()); logic.selectByValue(expected.getLogic().name()); @@ -54,7 +54,9 @@ public class JSPolicyForm extends Form { scriptExecutor.executeScript("angular.element(document.getElementById('code')).scope().policy.code = '" + expected.getCode() + "'"); - save(); + if (save) { + save(); + } } public void delete() { diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java index 12e2fd4c1d..31c5b993bd 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java @@ -79,40 +79,44 @@ public class Policies extends Form { return table; } - public

P create(AbstractPolicyRepresentation expected) { + public

P create(AbstractPolicyRepresentation expected, boolean save) { String type = expected.getType(); performOperationWithPageReload(() -> createSelect.selectByValue(type)); if ("role".equals(type)) { - rolePolicy.form().populate((RolePolicyRepresentation) expected); + rolePolicy.form().populate((RolePolicyRepresentation) expected, save); return (P) rolePolicy; } else if ("user".equals(type)) { - userPolicy.form().populate((UserPolicyRepresentation) expected); + userPolicy.form().populate((UserPolicyRepresentation) expected, save); return (P) userPolicy; } else if ("aggregate".equals(type)) { - aggregatePolicy.form().populate((AggregatePolicyRepresentation) expected); + aggregatePolicy.form().populate((AggregatePolicyRepresentation) expected, save); return (P) aggregatePolicy; } else if ("js".equals(type)) { - jsPolicy.form().populate((JSPolicyRepresentation) expected); + jsPolicy.form().populate((JSPolicyRepresentation) expected, save); return (P) jsPolicy; } else if ("time".equals(type)) { - timePolicy.form().populate((TimePolicyRepresentation) expected); + timePolicy.form().populate((TimePolicyRepresentation) expected, save); return (P) timePolicy; } else if ("rules".equals(type)) { - rulePolicy.form().populate((RulePolicyRepresentation) expected); + rulePolicy.form().populate((RulePolicyRepresentation) expected, save); return (P) rulePolicy; } else if ("client".equals(type)) { - clientPolicy.form().populate((ClientPolicyRepresentation) expected); + clientPolicy.form().populate((ClientPolicyRepresentation) expected, save); return (P) clientPolicy; } else if ("group".equals(type)) { - groupPolicy.form().populate((GroupPolicyRepresentation) expected); + groupPolicy.form().populate((GroupPolicyRepresentation) expected, save); return (P) groupPolicy; } return null; } + public

P create(AbstractPolicyRepresentation expected) { + return create(expected, true); + } + public void update(String name, AbstractPolicyRepresentation representation) { for (WebElement row : policies().rows()) { PolicyRepresentation actual = policies().toRepresentation(row); @@ -121,21 +125,21 @@ public class Policies extends Form { String type = representation.getType(); if ("role".equals(type)) { - rolePolicy.form().populate((RolePolicyRepresentation) representation); + rolePolicy.form().populate((RolePolicyRepresentation) representation, true); } else if ("user".equals(type)) { - userPolicy.form().populate((UserPolicyRepresentation) representation); + userPolicy.form().populate((UserPolicyRepresentation) representation, true); } else if ("aggregate".equals(type)) { - aggregatePolicy.form().populate((AggregatePolicyRepresentation) representation); + aggregatePolicy.form().populate((AggregatePolicyRepresentation) representation, true); } else if ("js".equals(type)) { - jsPolicy.form().populate((JSPolicyRepresentation) representation); + jsPolicy.form().populate((JSPolicyRepresentation) representation, true); } else if ("time".equals(type)) { - timePolicy.form().populate((TimePolicyRepresentation) representation); + timePolicy.form().populate((TimePolicyRepresentation) representation, true); } else if ("rules".equals(type)) { - rulePolicy.form().populate((RulePolicyRepresentation) representation); + rulePolicy.form().populate((RulePolicyRepresentation) representation, true); } else if ("client".equals(type)) { - clientPolicy.form().populate((ClientPolicyRepresentation) representation); + clientPolicy.form().populate((ClientPolicyRepresentation) representation, true); } else if ("group".equals(type)) { - groupPolicy.form().populate((GroupPolicyRepresentation) representation); + groupPolicy.form().populate((GroupPolicyRepresentation) representation, true); } return; diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicy.java index 8d4be910b0..e726fa9fc2 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicy.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicy.java @@ -36,6 +36,6 @@ public class RolePolicy implements PolicyTypeUI { } public void update(RolePolicyRepresentation expected) { - form().populate(expected); + form().populate(expected, true); } } diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicyForm.java index f917678b28..2a866df484 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicyForm.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RolePolicyForm.java @@ -64,7 +64,7 @@ public class RolePolicyForm extends Form { @FindBy(xpath = "//div[@class='modal-dialog']") protected ModalDialog modalDialog; - public void populate(RolePolicyRepresentation expected) { + public void populate(RolePolicyRepresentation expected, boolean save) { setInputValue(name, expected.getName()); setInputValue(description, expected.getDescription()); logic.selectByValue(expected.getLogic().name()); @@ -88,7 +88,9 @@ public class RolePolicyForm extends Form { unSelect(roles, realmRoleSelect.getSelected()); unSelect(roles, clientRoleSelect.getSelected()); - save(); + if (save) { + save(); + } } private void unSelect(Set roles, Set selection) { diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RulePolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RulePolicy.java index 6d463477b3..706b2bf3a1 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RulePolicy.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RulePolicy.java @@ -36,6 +36,6 @@ public class RulePolicy implements PolicyTypeUI { } public void update(RulePolicyRepresentation expected) { - form().populate(expected); + form().populate(expected, true); } } diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RulePolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RulePolicyForm.java index a990bc42a3..0103aafdfb 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RulePolicyForm.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RulePolicyForm.java @@ -75,7 +75,7 @@ public class RulePolicyForm extends Form { @FindBy(id = "resolveModule") private WebElement resolveModuleButton; - public void populate(RulePolicyRepresentation expected) { + public void populate(RulePolicyRepresentation expected, boolean save) { setInputValue(name, expected.getName()); setInputValue(description, expected.getDescription()); setInputValue(artifactGroupId, expected.getArtifactGroupId()); @@ -94,7 +94,9 @@ public class RulePolicyForm extends Form { scannerPeriodUnit.selectByVisibleText(expected.getScannerPeriodUnit()); logic.selectByValue(expected.getLogic().name()); - save(); + if (save) { + save(); + } } public void delete() { diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicy.java index ce2a20a8d0..0d74aa1a6e 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicy.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicy.java @@ -36,6 +36,6 @@ public class TimePolicy implements PolicyTypeUI { } public void update(TimePolicyRepresentation expected) { - form().populate(expected); + form().populate(expected, true); } } diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicyForm.java index 47be24d8f6..9a9f16a15d 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicyForm.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/TimePolicyForm.java @@ -81,7 +81,7 @@ public class TimePolicyForm extends Form { @FindBy(xpath = "//div[@class='modal-dialog']") protected ModalDialog modalDialog; - public void populate(TimePolicyRepresentation expected) { + public void populate(TimePolicyRepresentation expected, boolean save) { setInputValue(name, expected.getName()); setInputValue(description, expected.getDescription()); logic.selectByValue(expected.getLogic().name()); @@ -98,7 +98,9 @@ public class TimePolicyForm extends Form { setInputValue(minute, expected.getMinute()); setInputValue(minuteEnd, expected.getMinuteEnd()); - save(); + if (save) { + save(); + } } public void delete() { diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicy.java index cd5b8ebb2e..9371ad50e7 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicy.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicy.java @@ -36,6 +36,6 @@ public class UserPolicy implements PolicyTypeUI { } public void update(UserPolicyRepresentation expected) { - form().populate(expected); + form().populate(expected, true); } } diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicyForm.java index ec24ace72a..172d5ab845 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicyForm.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/UserPolicyForm.java @@ -56,14 +56,16 @@ public class UserPolicyForm extends Form { @FindBy(xpath = "//div[@class='modal-dialog']") protected ModalDialog modalDialog; - public void populate(UserPolicyRepresentation expected) { + public void populate(UserPolicyRepresentation expected, boolean save) { setInputValue(name, expected.getName()); setInputValue(description, expected.getDescription()); logic.selectByValue(expected.getLogic().name()); usersInput.update(expected.getUsers()); - save(); + if (save) { + save(); + } } public void delete() { diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AggregatePolicyManagementTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AggregatePolicyManagementTest.java index be2a984c25..52ae14c8a2 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AggregatePolicyManagementTest.java +++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AggregatePolicyManagementTest.java @@ -138,6 +138,87 @@ public class AggregatePolicyManagementTest extends AbstractAuthorizationSettings assertNull(authorizationPage.authorizationTabs().policies().policies().findByName(expected.getName())); } + @Test + public void testCreateWithChild() { + AggregatePolicyRepresentation expected = new AggregatePolicyRepresentation(); + + expected.setName("Test Child Create Aggregate Policy"); + expected.setDescription("description"); + + AggregatePolicy policy = authorizationPage.authorizationTabs().policies().create(expected, false); + + RolePolicyRepresentation childPolicy = new RolePolicyRepresentation(); + + childPolicy.setName("Child Role Policy"); + childPolicy.addRole("Role A"); + + policy.createPolicy(childPolicy); + policy.form().save(); + + assertAlertSuccess(); + + expected.addPolicy(childPolicy.getName()); + + authorizationPage.navigateTo(); + AggregatePolicy actual = authorizationPage.authorizationTabs().policies().name(expected.getName()); + assertPolicy(expected, actual); + } + + @Test + public void testCreateWithChildAndSelectedPolicy() { + AggregatePolicyRepresentation expected = new AggregatePolicyRepresentation(); + + expected.setName("Test Child Create Aggregate Policy"); + expected.setDescription("description"); + expected.addPolicy("Policy C"); + + AggregatePolicy policy = authorizationPage.authorizationTabs().policies().create(expected, false); + + RolePolicyRepresentation childPolicy = new RolePolicyRepresentation(); + + childPolicy.setName("Child Role Policy"); + childPolicy.addRole("Role A"); + + policy.createPolicy(childPolicy); + policy.form().save(); + + assertAlertSuccess(); + + expected.addPolicy(childPolicy.getName()); + + authorizationPage.navigateTo(); + AggregatePolicy actual = authorizationPage.authorizationTabs().policies().name(expected.getName()); + assertPolicy(expected, actual); + } + + @Test + public void testUpdateWithChild() { + AggregatePolicyRepresentation expected = new AggregatePolicyRepresentation(); + + expected.setName("Test Child Update Aggregate Policy"); + expected.setDescription("description"); + expected.addPolicy("Policy C"); + + AggregatePolicy policy = authorizationPage.authorizationTabs().policies().create(expected); + assertAlertSuccess(); + assertPolicy(expected, policy); + + RolePolicyRepresentation childPolicy = new RolePolicyRepresentation(); + + childPolicy.setName("Child Role Policy"); + childPolicy.addRole("Role A"); + + policy.createPolicy(childPolicy); + + policy.form().save(); + + expected.addPolicy(childPolicy.getName()); + + authorizationPage.navigateTo(); + AggregatePolicy actual = authorizationPage.authorizationTabs().policies().name(expected.getName()); + assertPolicy(expected, actual); + } + private AggregatePolicyRepresentation createPolicy(AggregatePolicyRepresentation expected) { AggregatePolicy policy = authorizationPage.authorizationTabs().policies().create(expected); assertAlertSuccess(); diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties index ca2c23f837..78a84dd2fa 100644 --- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties +++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties @@ -1153,7 +1153,7 @@ authz-no-type-defined=No type defined. authz-no-uri-defined=No URI defined. authz-no-permission-assigned=No permission assigned. authz-no-policy-assigned=No policy assigned. -authz-create-permission=Create permission +authz-create-permission=Create Permission # Authz Resource Detail authz-add-resource=Add Resource @@ -1172,7 +1172,7 @@ authz-scope-name.tooltip=An unique name for this scope. The name can be used to # Authz Policy List authz-all-types=All types -authz-create-policy=Create policy +authz-create-policy=Create Policy authz-no-policies-available=No policies available. # Authz Policy Detail diff --git a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js index 116c12458e..4bd0525d1e 100644 --- a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js +++ b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js @@ -1814,7 +1814,7 @@ module.controller('ResourceServerPolicyGroupDetailCtrl', function($scope, $route if (!angular.equals($scope.selectedGroups, selectedGroups)) { $scope.changed = true; } else { - $scope.changed = false; + $scope.changed = PolicyController.isNewAssociatedPolicy(); } }, true); }, @@ -1956,7 +1956,7 @@ module.controller('ResourceServerPolicyTimeDetailCtrl', function($scope, $route, } }); -module.controller('ResourceServerPolicyAggregateDetailCtrl', function($scope, $route, $location, realm, PolicyController, ResourceServerPolicy, client) { +module.controller('ResourceServerPolicyAggregateDetailCtrl', function($scope, $route, $location, realm, PolicyController, ResourceServerPolicy, client, PolicyProvider, policyState) { PolicyController.onInit({ getPolicyType : function() { return "aggregate"; @@ -1991,26 +1991,68 @@ module.controller('ResourceServerPolicyAggregateDetailCtrl', function($scope, $r return object.name; } }; + + $scope.policyProviders = []; + + PolicyProvider.query({ + realm : $route.current.params.realm, + client : client.id + }, function (data) { + for (i = 0; i < data.length; i++) { + if (data[i].type != 'resource' && data[i].type != 'scope') { + $scope.policyProviders.push(data[i]); + } + } + }); }, onInitUpdate : function(policy) { - ResourceServerPolicy.associatedPolicies({ - realm : $route.current.params.realm, - client : client.id, - id : policy.id - }, function(policies) { - $scope.selectedPolicies = []; - for (i = 0; i < policies.length; i++) { - policies[i].text = policies[i].name; - $scope.selectedPolicies.push(policies[i]); + if (PolicyController.isBackNewAssociatedPolicy()) { + policy.name = policyState.state.name; + policy.description = policyState.state.description; + policy.decisionStrategy = policyState.state.decisionStrategy; + policy.logic = policyState.state.logic; + $scope.selectedPolicies = policyState.state.selectedPolicies; + + if (!$scope.selectedPolicies) { + $scope.selectedPolicies = []; } - var copy = angular.copy($scope.selectedPolicies); - $scope.$watch('selectedPolicies', function() { - if (!angular.equals($scope.selectedPolicies, copy)) { - $scope.changed = true; + + $scope.changed = true; + ResourceServerPolicy.query({ + realm: realm.realm, + client : client.id, + permission: false, + name: policyState.state.newPolicyName, + max : 20, + first : 0 + }, function(response) { + for (i = 0; i < response.length; i++) { + if (response[i].name == policyState.state.newPolicyName) { + response[i].text = response[i].name; + $scope.selectedPolicies.push(response[i]); + } } - }, true); - }); + }); + } else { + ResourceServerPolicy.associatedPolicies({ + realm : $route.current.params.realm, + client : client.id, + id : policy.id + }, function(policies) { + $scope.selectedPolicies = []; + for (i = 0; i < policies.length; i++) { + policies[i].text = policies[i].name; + $scope.selectedPolicies.push(policies[i]); + } + var copy = angular.copy($scope.selectedPolicies); + $scope.$watch('selectedPolicies', function() { + if (!angular.equals($scope.selectedPolicies, copy)) { + $scope.changed = true; + } + }, true); + }); + } }, onUpdate : function() { @@ -2025,7 +2067,37 @@ module.controller('ResourceServerPolicyAggregateDetailCtrl', function($scope, $r }, onInitCreate : function(newPolicy) { - newPolicy.decisionStrategy = 'UNANIMOUS'; + policyState.previousPage.name = 'authz-add-aggregated-policy'; + if (PolicyController.isBackNewAssociatedPolicy()) { + newPolicy.name = policyState.state.name; + newPolicy.description = policyState.state.description; + newPolicy.decisionStrategy = policyState.state.decisionStrategy; + newPolicy.logic = policyState.state.logic; + $scope.selectedPolicies = policyState.state.selectedPolicies; + + if (!$scope.selectedPolicies) { + $scope.selectedPolicies = []; + } + + $scope.changed = true; + ResourceServerPolicy.query({ + realm: realm.realm, + client : client.id, + permission: false, + name: policyState.state.newPolicyName, + max : 20, + first : 0 + }, function(response) { + for (i = 0; i < response.length; i++) { + if (response[i].name == policyState.state.newPolicyName) { + response[i].text = response[i].name; + $scope.selectedPolicies.push(response[i]); + } + } + }); + } else { + newPolicy.decisionStrategy = 'UNANIMOUS'; + } }, onCreate : function() { @@ -2041,11 +2113,49 @@ module.controller('ResourceServerPolicyAggregateDetailCtrl', function($scope, $r }, realm, client, $scope); }); -module.service("PolicyController", function($http, $route, $location, ResourceServer, ResourceServerPolicy, ResourceServerPermission, AuthzDialog, Notifications) { +module.service("PolicyController", function($http, $route, $location, ResourceServer, ResourceServerPolicy, ResourceServerPermission, AuthzDialog, Notifications, policyState) { var PolicyController = {}; + PolicyController.isNewAssociatedPolicy = function() { + return $route.current.params['new_policy'] != null; + } + + PolicyController.isBackNewAssociatedPolicy = function() { + return $route.current.params['back'] != null; + } + PolicyController.onInit = function(delegate, realm, client, $scope) { + if (!policyState.previousPage) { + policyState.previousPage = {}; + } + + $scope.policyState = policyState; + + $scope.addPolicy = function(policyType) { + policyState.state = $scope.policy; + if ($scope.selectedPolicies) { + policyState.state.selectedPolicies = $scope.selectedPolicies; + } + var previousUrl = window.location.href.substring(window.location.href.indexOf('/realms')); + + if (previousUrl.indexOf('back=true') == -1) { + previousUrl = previousUrl + '?back=true'; + } + policyState.state.previousUrl = previousUrl; + $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/policy/" + policyType.type + "/create?new_policy=true"); + } + + $scope.createNewPolicy = function() { + $scope.showNewPolicy = true; + } + + $scope.cancelCreateNewPolicy = function() { + $scope.showNewPolicy = false; + } + + $scope.historyBackOnSaveOrCancel = PolicyController.isNewAssociatedPolicy(); + if (!delegate.isPermission) { delegate.isPermission = function () { return false; @@ -2078,7 +2188,6 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe if (!policyId) { $scope.create = true; - $scope.changed = false; var policy = {}; @@ -2090,6 +2199,8 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe delegate.onInitCreate(policy); } + $scope.changed = $scope.historyBackOnSaveOrCancel || PolicyController.isBackNewAssociatedPolicy(); + $scope.policy = angular.copy(policy); $scope.$watch('policy', function() { @@ -2105,10 +2216,20 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe } service.save({realm : realm.realm, client : client.id, type: $scope.policy.type}, $scope.policy, function(data) { if (delegate.isPermission()) { - $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/permission/" + $scope.policy.type + "/" + data.id); + if ($scope.historyBackOnSaveOrCancel) { + policyState.state.newPolicyName = $scope.policy.name; + $location.url(policyState.state.previousUrl); + } else { + $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/permission/" + $scope.policy.type + "/" + data.id); + } Notifications.success("The permission has been created."); } else { - $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/policy/" + $scope.policy.type + "/" + data.id); + if ($scope.historyBackOnSaveOrCancel) { + policyState.state.newPolicyName = $scope.policy.name; + $location.url(policyState.state.previousUrl); + } else { + $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/policy/" + $scope.policy.type + "/" + data.id); + } Notifications.success("The policy has been created."); } }); @@ -2117,9 +2238,17 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe $scope.reset = function() { if (delegate.isPermission()) { - $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/permission/"); + if ($scope.historyBackOnSaveOrCancel) { + $location.url(policyState.state.previousUrl); + } else { + $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/permission/"); + } } else { - $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/policy/"); + if ($scope.historyBackOnSaveOrCancel) { + $location.url(policyState.state.previousUrl); + } else { + $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/policy/"); + } } } } else { @@ -2137,7 +2266,7 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe } $scope.policy = angular.copy(policy); - $scope.changed = false; + $scope.changed = $scope.historyBackOnSaveOrCancel || PolicyController.isBackNewAssociatedPolicy(); $scope.$watch('policy', function() { if (!angular.equals($scope.policy, policy)) { @@ -2162,14 +2291,18 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe } $scope.reset = function() { - var freshPolicy = angular.copy(data); + if ($scope.historyBackOnSaveOrCancel) { + $location.url(policyState.state.previousUrl); + } else { + var freshPolicy = angular.copy(data); - if (delegate.onInitUpdate) { - delegate.onInitUpdate(freshPolicy); + if (delegate.onInitUpdate) { + delegate.onInitUpdate(freshPolicy); + } + + $scope.policy = angular.copy(freshPolicy); + $scope.changed = false; } - - $scope.policy = angular.copy(freshPolicy); - $scope.changed = false; } }); diff --git a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-services.js b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-services.js index 12315ed04c..12ca4305a5 100644 --- a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-services.js +++ b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-services.js @@ -200,5 +200,11 @@ module.factory('GroupManagementPermissions', function($resource) { }); }); - +module.factory('policyState', [function () { + return { + model: { + state: {} + } + }; +}]); diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html index 11d08270e5..eff6f8533b 100644 --- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html +++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html @@ -5,6 +5,8 @@

  • {{client.clientId}}
  • {{:: 'authz-authorization' | translate}}
  • {{:: 'authz-policies' | translate}}
  • +
  • {{policyState.state.name}}
  • +
  • {{policyState.previousPage.name}}
  • {{:: 'authz-add-aggregated-policy' | translate}}
  • {{:: 'authz-aggregated' | translate}}
  • {{originalPolicy.name}}
  • @@ -32,12 +34,30 @@
    - -
    - +
    +
    {{:: 'authz-policy-apply-policy.tooltip' | translate}}
    +
    + +
    +
    +
    + +
    + +
    + +
    +
    +
    +
    diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-client-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-client-detail.html index de2da055fa..62232dd9b5 100644 --- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-client-detail.html +++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-client-detail.html @@ -5,6 +5,8 @@
  • {{client.clientId}}
  • {{:: 'authz-authorization' | translate}}
  • {{:: 'authz-policies' | translate}}
  • +
  • {{policyState.state.name}}
  • +
  • {{policyState.previousPage.name}}
  • {{:: 'authz-add-client-policy' | translate}}
  • {{:: 'client' | translate}}
  • {{originalPolicy.name}}
  • diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-drools-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-drools-detail.html index 612a8a4db2..829fb5701d 100644 --- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-drools-detail.html +++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-drools-detail.html @@ -5,6 +5,8 @@
  • {{client.clientId}}
  • {{:: 'authz-authorization' | translate}}
  • {{:: 'authz-policies' | translate}}
  • +
  • {{policyState.state.name}}
  • +
  • {{policyState.previousPage.name}}
  • {{:: 'authz-add-drools-policy' | translate}}
  • Rules
  • {{originalPolicy.name}}
  • diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-group-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-group-detail.html index 61af0f157d..a7fe00290b 100644 --- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-group-detail.html +++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-group-detail.html @@ -22,6 +22,8 @@
  • {{client.clientId}}
  • {{:: 'authz-authorization' | translate}}
  • {{:: 'authz-policies' | translate}}
  • +
  • {{policyState.state.name}}
  • +
  • {{policyState.previousPage.name}}
  • {{:: 'authz-add-group-policy' | translate}}
  • {{:: 'groups' | translate}}
  • {{originalPolicy.name}}
  • diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html index 679c15a789..2cbfabe5a5 100644 --- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html +++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html @@ -8,6 +8,8 @@
  • {{client.clientId}}
  • {{:: 'authz-authorization' | translate}}
  • {{:: 'authz-policies' | translate}}
  • +
  • {{policyState.state.name}}
  • +
  • {{policyState.previousPage.name}}
  • {{:: 'authz-add-js-policy' | translate}}
  • JavaScript
  • {{originalPolicy.name}}
  • diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-role-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-role-detail.html index 47e563a236..f0465c6fd0 100644 --- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-role-detail.html +++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-role-detail.html @@ -23,6 +23,8 @@
  • {{client.clientId}}
  • {{:: 'authz-authorization' | translate}}
  • {{:: 'authz-policies' | translate}}
  • +
  • {{policyState.state.name}}
  • +
  • {{:: policyState.previousPage.name | translate}}
  • {{:: 'authz-add-role-policy' | translate}}
  • {{:: 'roles' | translate}}
  • {{originalPolicy.name}}
  • diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html index 81793d5d47..8f356ede4c 100644 --- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html +++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html @@ -8,6 +8,8 @@
  • {{client.clientId}}
  • {{:: 'authz-authorization' | translate}}
  • {{:: 'authz-policies' | translate}}
  • +
  • {{policyState.state.name}}
  • +
  • {{policyState.previousPage.name}}
  • {{:: 'authz-add-time-policy' | translate}}
  • {{:: 'time' | translate}}
  • {{originalPolicy.name}}
  • diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-user-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-user-detail.html index c619910e37..d04c3190a4 100644 --- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-user-detail.html +++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-user-detail.html @@ -5,6 +5,8 @@
  • {{client.clientId}}
  • {{:: 'authz-authorization' | translate}}
  • {{:: 'authz-policies' | translate}}
  • +
  • {{policyState.state.name}}
  • +
  • {{policyState.previousPage.name}}
  • {{:: 'authz-add-user-policy' | translate}}
  • {{:: 'user' | translate}}
  • {{originalPolicy.name}}