[SYNCOPE-1360] Reworking DynRealms-based delegated administration from Admin Console
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/4fec32be Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/4fec32be Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/4fec32be Branch: refs/heads/master Commit: 4fec32be0708252585f4cbfbc9dd25b5670d37ff Parents: d7f034a Author: Francesco Chicchiriccò <ilgro...@apache.org> Authored: Mon Sep 3 17:28:05 2018 +0200 Committer: Francesco Chicchiriccò <ilgro...@apache.org> Committed: Mon Sep 3 17:28:14 2018 +0200 ---------------------------------------------------------------------- .../client/console/SyncopeConsoleSession.java | 33 +++++++++++++++----- .../console/panels/AnyDirectoryPanel.java | 13 +++++++- .../console/panels/AnyObjectDirectoryPanel.java | 4 +-- .../syncope/client/console/panels/AnyPanel.java | 6 ++-- .../console/panels/GroupDirectoryPanel.java | 9 +++--- .../console/panels/UserDirectoryPanel.java | 16 ++++++---- .../console/wicket/markup/html/form/Action.java | 24 +++++++++++--- .../wicket/markup/html/form/ActionPanel.java | 2 +- .../java/data/UserDataBinderImpl.java | 6 ++-- .../reference-guide/concepts/roles.adoc | 1 + 10 files changed, 81 insertions(+), 33 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/4fec32be/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java index bfde815..2f952ee 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java @@ -20,8 +20,10 @@ package org.apache.syncope.client.console; import java.text.DateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -32,6 +34,7 @@ import java.util.concurrent.Future; import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.MediaType; import org.apache.commons.collections4.list.SetUniqueList; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.FastDateFormat; import org.apache.commons.lang3.tuple.Pair; @@ -224,19 +227,33 @@ public class SyncopeConsoleSession extends AuthenticatedWebSession { return sortable; } - public boolean owns(final String entitlements) { - return owns(entitlements, SyncopeConstants.ROOT_REALM); - } - - public boolean owns(final String entitlements, final String realm) { + public boolean owns(final String entitlements, final String... realms) { if (StringUtils.isEmpty(entitlements)) { return true; } + if (auth == null) { + return false; + } + + Set<String> requested = ArrayUtils.isEmpty(realms) + ? Collections.singleton(SyncopeConstants.ROOT_REALM) + : new HashSet<>(Arrays.asList(realms)); + for (String entitlement : entitlements.split(",")) { - if (auth != null && auth.containsKey(entitlement) && (realm == null - || auth.get(entitlement).stream().anyMatch(ownedRealm -> realm.startsWith(ownedRealm)))) { - return true; + if (auth.containsKey(entitlement)) { + boolean owns = false; + + Set<String> owned = auth.get(entitlement); + for (String realm : requested) { + if (realm.startsWith(SyncopeConstants.ROOT_REALM)) { + owns |= owned.stream().anyMatch(ownedRealm -> realm.startsWith(ownedRealm)); + } else { + owns |= owned.contains(realm); + } + } + + return owns; } } http://git-wip-us.apache.org/repos/asf/syncope/blob/4fec32be/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java index 8fdc994..ec8a995 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java @@ -101,7 +101,11 @@ public abstract class AnyDirectoryPanel<A extends AnyTO, E extends AbstractAnyRe } else { MetaDataRoleAuthorizationStrategy.unauthorizeAll(addAjaxLink, RENDER); } - setReadOnly(!SyncopeConsoleSession.get().owns(String.format("%s_UPDATE", builder.type), builder.realm)); + if (builder.dynRealm == null) { + setReadOnly(!SyncopeConsoleSession.get().owns(String.format("%s_UPDATE", builder.type), builder.realm)); + } else { + setReadOnly(!SyncopeConsoleSession.get().owns(String.format("%s_UPDATE", builder.type), builder.dynRealm)); + } this.realm = builder.realm; this.type = builder.type; @@ -243,6 +247,8 @@ public abstract class AnyDirectoryPanel<A extends AnyTO, E extends AbstractAnyRe */ protected String realm = SyncopeConstants.ROOT_REALM; + protected String dynRealm = null; + /** * Any type related to current panel. */ @@ -266,6 +272,11 @@ public abstract class AnyDirectoryPanel<A extends AnyTO, E extends AbstractAnyRe return this; } + public Builder<A, E> setDynRealm(final String dynRealm) { + this.dynRealm = dynRealm; + return this; + } + @Override public List<AnyTypeClassTO> getAnyTypeClassTOs() { return this.anyTypeClassTOs; http://git-wip-us.apache.org/repos/asf/syncope/blob/4fec32be/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java index 7a642dc..34eeed5 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java @@ -111,7 +111,7 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO, AnyO } }, ActionType.EDIT, String.format("%s,%s", AnyEntitlement.READ.getFor(type), AnyEntitlement.UPDATE.getFor(type))). - setRealm(realm); + setRealms(realm, model.getObject().getDynRealms()); panel.add(new ActionLink<AnyObjectTO>() { @@ -156,7 +156,7 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO, AnyO } }, ActionType.MANAGE_RESOURCES, String.format("%s,%s", AnyEntitlement.READ.getFor(type), AnyEntitlement.UPDATE.getFor(type))). - setRealm(realm); + setRealms(realm, model.getObject().getDynRealms()); panel.add( new ActionLink<AnyObjectTO>() { http://git-wip-us.apache.org/repos/asf/syncope/blob/4fec32be/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java index 127471b..12ec331 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java @@ -250,7 +250,7 @@ public class AnyPanel extends Panel implements ModalPanel { panel = new UserDirectoryPanel.Builder( anyTypeClassRestClient.list(anyTypeTO.getClasses()), anyTypeTO.getKey(), - pageRef).setRealm(realm).setFiltered(true). + pageRef).setRealm(realm).setDynRealm(dynRealm).setFiltered(true). setFiql(fiql).setWizardInModal(true).addNewItemPanelBuilder(FormLayoutInfoUtils.instantiate( userTO, anyTypeTO.getClasses(), @@ -269,7 +269,7 @@ public class AnyPanel extends Panel implements ModalPanel { panel = new GroupDirectoryPanel.Builder( anyTypeClassRestClient.list(anyTypeTO.getClasses()), anyTypeTO.getKey(), - pageRef).setRealm(realm).setFiltered(true). + pageRef).setRealm(realm).setDynRealm(dynRealm).setFiltered(true). setFiql(fiql).setWizardInModal(true).addNewItemPanelBuilder(FormLayoutInfoUtils.instantiate( groupTO, anyTypeTO.getClasses(), @@ -291,7 +291,7 @@ public class AnyPanel extends Panel implements ModalPanel { panel = new AnyObjectDirectoryPanel.Builder( anyTypeClassRestClient.list(anyTypeTO.getClasses()), anyTypeTO.getKey(), - pageRef).setRealm(realm).setFiltered(true). + pageRef).setRealm(realm).setDynRealm(dynRealm).setFiltered(true). setFiql(fiql).setWizardInModal(true).addNewItemPanelBuilder(FormLayoutInfoUtils.instantiate( anyObjectTO, anyTypeTO.getClasses(), http://git-wip-us.apache.org/repos/asf/syncope/blob/4fec32be/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java index ac5663b..e7026c2 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java @@ -216,7 +216,7 @@ public class GroupDirectoryPanel extends AnyDirectoryPanel<GroupTO, GroupRestCli } }, ActionType.EDIT, String.format("%s,%s", StandardEntitlement.GROUP_READ, StandardEntitlement.GROUP_UPDATE)). - setRealm(realm); + setRealms(realm, model.getObject().getDynRealms()); panel.add(new ActionLink<GroupTO>() { @@ -247,7 +247,8 @@ public class GroupDirectoryPanel extends AnyDirectoryPanel<GroupTO, GroupRestCli typeExtensionsModal.header(new StringResourceModel("typeExtensions", model)); typeExtensionsModal.show(true); } - }, ActionType.TYPE_EXTENSIONS, StandardEntitlement.GROUP_UPDATE).setRealm(realm); + }, ActionType.TYPE_EXTENSIONS, StandardEntitlement.GROUP_UPDATE). + setRealms(realm, model.getObject().getDynRealms()); panel.add(new ActionLink<GroupTO>() { @@ -265,7 +266,7 @@ public class GroupDirectoryPanel extends AnyDirectoryPanel<GroupTO, GroupRestCli } }, ActionType.MEMBERS, String.format("%s,%s", StandardEntitlement.GROUP_READ, StandardEntitlement.GROUP_UPDATE)). - setRealm(realm); + setRealms(realm, model.getObject().getDynRealms()); panel.add(new ActionLink<GroupTO>() { @@ -333,7 +334,7 @@ public class GroupDirectoryPanel extends AnyDirectoryPanel<GroupTO, GroupRestCli } }, ActionType.MANAGE_RESOURCES, String.format("%s,%s", StandardEntitlement.GROUP_READ, StandardEntitlement.GROUP_UPDATE)). - setRealm(realm); + setRealms(realm, model.getObject().getDynRealms()); panel.add(new ActionLink<GroupTO>() { http://git-wip-us.apache.org/repos/asf/syncope/blob/4fec32be/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java index b0edf68..597a4f5 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java @@ -141,7 +141,7 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO, UserRestClient } }, ActionType.EDIT, String.format("%s,%s", StandardEntitlement.USER_READ, StandardEntitlement.USER_UPDATE)). - setRealm(realm); + setRealms(realm, model.getObject().getDynRealms()); panel.add(new ActionLink<UserTO>() { @@ -183,7 +183,8 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO, UserRestClient } ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); } - }, ActionType.MUSTCHANGEPASSWORD, StandardEntitlement.USER_UPDATE).setRealm(realm); + }, ActionType.MUSTCHANGEPASSWORD, StandardEntitlement.USER_UPDATE). + setRealms(realm, model.getObject().getDynRealms()); if (wizardInModal) { panel.add(new ActionLink<UserTO>() { @@ -206,7 +207,8 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO, UserRestClient displayAttributeModal.show(true); } - }, ActionType.PASSWORD_MANAGEMENT, StandardEntitlement.USER_UPDATE).setRealm(realm); + }, ActionType.PASSWORD_MANAGEMENT, StandardEntitlement.USER_UPDATE). + setRealms(realm, model.getObject().getDynRealms()); if (SyncopeConsoleSession.get().getPlatformInfo().isPwdResetAllowed() && !SyncopeConsoleSession.get().getPlatformInfo().isPwdResetRequiringSecurityQuestions()) { @@ -230,7 +232,8 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO, UserRestClient } ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); } - }, ActionType.REQUEST_PASSWORD_RESET, StandardEntitlement.USER_UPDATE).setRealm(realm); + }, ActionType.REQUEST_PASSWORD_RESET, StandardEntitlement.USER_UPDATE). + setRealms(realm, model.getObject().getDynRealms()); } panel.add(new ActionLink<UserTO>() { @@ -255,7 +258,8 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO, UserRestClient altDefaultModal.show(true); } - }, ActionType.ENABLE, StandardEntitlement.USER_UPDATE).setRealm(realm); + }, ActionType.ENABLE, StandardEntitlement.USER_UPDATE). + setRealms(realm, model.getObject().getDynRealms()); panel.add(new ActionLink<UserTO>() { @@ -281,7 +285,7 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO, UserRestClient } }, ActionType.MANAGE_RESOURCES, String.format("%s,%s", StandardEntitlement.USER_READ, StandardEntitlement.USER_UPDATE)). - setRealm(realm); + setRealms(realm, model.getObject().getDynRealms()); panel.add(new ActionLink<UserTO>() { http://git-wip-us.apache.org/repos/asf/syncope/blob/4fec32be/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/Action.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/Action.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/Action.java index 98d2556..f01a984 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/Action.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/Action.java @@ -19,6 +19,8 @@ package org.apache.syncope.client.console.wicket.markup.html.form; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import org.apache.commons.lang3.StringUtils; import org.apache.wicket.model.Model; @@ -31,7 +33,7 @@ public final class Action<T extends Serializable> implements Serializable { private static final long serialVersionUID = -7989237020377623993L; - private String realm = null; + private final List<String> realms = new ArrayList<>(); private final ActionLink<T> link; @@ -66,12 +68,24 @@ public final class Action<T extends Serializable> implements Serializable { this.indicator = true; } - public String getRealm() { - return realm; + public String[] getRealms() { + return realms.toArray(new String[realms.size()]); } public void setRealm(final String realm) { - this.realm = realm; + this.realms.clear(); + + if (realm != null) { + this.realms.add(realm); + } + } + + public void setRealms(final String realm, final List<String> dynRealms) { + setRealm(realm); + + if (dynRealms != null) { + this.realms.addAll(dynRealms); + } } public ActionLink<T> getLink() { @@ -104,7 +118,7 @@ public final class Action<T extends Serializable> implements Serializable { this.visibleLabel = false; return this; } - + public Action<T> showLabel() { this.visibleLabel = true; return this; http://git-wip-us.apache.org/repos/asf/syncope/blob/4fec32be/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionPanel.java index 91f83b9..6b98619 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionPanel.java @@ -130,7 +130,7 @@ public final class ActionPanel<T extends Serializable> extends Panel { }; } - if (SyncopeConsoleSession.get().owns(action.getEntitlements(), action.getRealm())) { + if (SyncopeConsoleSession.get().owns(action.getEntitlements(), action.getRealms())) { MetaDataRoleAuthorizationStrategy.authorizeAll(actionLink, RENDER); } else { MetaDataRoleAuthorizationStrategy.unauthorizeAll(actionLink, RENDER); http://git-wip-us.apache.org/repos/asf/syncope/blob/4fec32be/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java ---------------------------------------------------------------------- diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java index df2f270..d328c43 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java @@ -586,10 +586,10 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat userDAO.findAllResources(user), details); - if (details) { - // dynamic realms - userTO.getDynRealms().addAll(userDAO.findDynRealms(user.getKey())); + // dynamic realms + userTO.getDynRealms().addAll(userDAO.findDynRealms(user.getKey())); + if (details) { // roles userTO.getRoles().addAll(user.getRoles().stream().map(Entity::getKey).collect(Collectors.toList())); http://git-wip-us.apache.org/repos/asf/syncope/blob/4fec32be/src/main/asciidoc/reference-guide/concepts/roles.adoc ---------------------------------------------------------------------- diff --git a/src/main/asciidoc/reference-guide/concepts/roles.adoc b/src/main/asciidoc/reference-guide/concepts/roles.adoc index 28e00e7..af28661 100644 --- a/src/main/asciidoc/reference-guide/concepts/roles.adoc +++ b/src/main/asciidoc/reference-guide/concepts/roles.adoc @@ -104,4 +104,5 @@ For example, the following entitlements are normally required to be granted for . `USER_READ` . `ANYTYPE_READ` . `REALM_LIST` +. `GROUP_SEARCH` ====