[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/b9a5c5d1
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/b9a5c5d1
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/b9a5c5d1

Branch: refs/heads/2_0_X
Commit: b9a5c5d1ebc97d7f78afba8befda3c4c5fbe6f82
Parents: 865bd70
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:31:20 2018 +0200

----------------------------------------------------------------------
 .../client/console/SyncopeConsoleSession.java   | 45 ++++++++++++++------
 .../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      | 17 +++++---
 .../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, 87 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/b9a5c5d1/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 aa8a28c..bda14db 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;
@@ -33,6 +35,7 @@ import javax.ws.rs.core.MediaType;
 import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
 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;
@@ -213,25 +216,39 @@ 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 || 
IterableUtils.matchesAny(auth.get(entitlement), new Predicate<String>() {
-
-                        @Override
-                        public boolean evaluate(final String ownedRealm) {
-                            return realm.startsWith(ownedRealm);
-                        }
-                    }))) {
-                return true;
+            if (auth.containsKey(entitlement)) {
+                boolean owns = false;
+
+                Set<String> owned = auth.get(entitlement);
+                for (final String realm : requested) {
+                    if (realm.startsWith(SyncopeConstants.ROOT_REALM)) {
+                        owns |= IterableUtils.matchesAny(owned, new 
Predicate<String>() {
+
+                            @Override
+                            public boolean evaluate(final String ownedRealm) {
+                                return realm.startsWith(ownedRealm);
+                            }
+                        });
+                    } else {
+                        owns |= owned.contains(realm);
+                    }
+                }
+
+                return owns;
             }
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b9a5c5d1/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 c2b10fd..5eb6f82 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
@@ -104,7 +104,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;
@@ -251,6 +255,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.
          */
@@ -274,6 +280,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/b9a5c5d1/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/b9a5c5d1/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/b9a5c5d1/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 188e21a..c371cc7 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>() {
 
@@ -334,7 +335,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/b9a5c5d1/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 d9b89a5..9c42ecb 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
@@ -143,7 +143,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>() {
 
@@ -185,7 +185,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>() {
@@ -208,8 +209,8 @@ public class UserDirectoryPanel extends 
AnyDirectoryPanel<UserTO, UserRestClient
 
                     displayAttributeModal.show(true);
                 }
-            }, ActionType.PASSWORD_MANAGEMENT,
-                    new 
StringBuilder().append(StandardEntitlement.USER_UPDATE).toString()).setRealm(realm);
+            }, ActionType.PASSWORD_MANAGEMENT, 
StandardEntitlement.USER_UPDATE).
+                    setRealms(realm, model.getObject().getDynRealms());
 
             if 
(SyncopeConsoleSession.get().getPlatformInfo().isPwdResetAllowed()
                     && 
!SyncopeConsoleSession.get().getPlatformInfo().isPwdResetRequiringSecurityQuestions())
 {
@@ -233,7 +234,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>() {
@@ -258,7 +260,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>() {
 
@@ -284,7 +287,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/b9a5c5d1/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/b9a5c5d1/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/b9a5c5d1/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 04246bd..175375c 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
@@ -602,10 +602,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
             CollectionUtils.collect(user.getRoles(),
                     EntityUtils.<Role>keyTransformer(), userTO.getRoles());

http://git-wip-us.apache.org/repos/asf/syncope/blob/b9a5c5d1/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 ee23565..91401c9 100644
--- a/src/main/asciidoc/reference-guide/concepts/roles.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/roles.adoc
@@ -102,4 +102,5 @@ For example, the following entitlements are normally 
required to be granted for
 . `USER_READ`
 . `ANYTYPE_READ`
 . `REALM_LIST`
+. `GROUP_SEARCH`
 ====

Reply via email to