You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by fm...@apache.org on 2017/06/29 15:26:23 UTC

syncope git commit: [SYNCOPE-1135] provides dynamicac reload of groups and memberships if the realm changes

Repository: syncope
Updated Branches:
  refs/heads/2_0_X 132d4156d -> a25b7c6fb


[SYNCOPE-1135] provides dynamicac reload of groups and memberships if the realm changes


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/a25b7c6f
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/a25b7c6f
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/a25b7c6f

Branch: refs/heads/2_0_X
Commit: a25b7c6fb40d1444f50feb3bebad33d0d6f7c966
Parents: 132d415
Author: fmartelli <fa...@gmail.com>
Authored: Thu Jun 29 17:26:04 2017 +0200
Committer: fmartelli <fa...@gmail.com>
Committed: Thu Jun 29 17:26:04 2017 +0200

----------------------------------------------------------------------
 .../syncope/client/console/pages/Realms.java    |   4 +
 .../client/console/panels/RealmChoicePanel.java |  26 +-
 .../client/console/wizards/any/Details.java     |  15 +-
 .../client/console/wizards/any/Groups.java      | 236 +++++++++++++------
 4 files changed, 197 insertions(+), 84 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/a25b7c6f/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
index d1c204c..0a8e9ad 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
@@ -254,4 +254,8 @@ public class Realms extends BasePage {
         });
         return content;
     }
+
+    public RealmChoicePanel getRealmChoicePanel() {
+        return realmChoicePanel;
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a25b7c6f/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java
index 4f0bbde..4a0ee0a 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java
@@ -76,6 +76,8 @@ public class RealmChoicePanel extends Panel {
 
     private final Map<String, Pair<RealmTO, List<RealmTO>>> tree;
 
+    private final List<AbstractLink> links = new ArrayList<>();
+
     public RealmChoicePanel(final String id, final PageReference pageRef) {
         super(id);
         this.pageRef = pageRef;
@@ -172,11 +174,11 @@ public class RealmChoicePanel extends Panel {
 
             @Override
             protected List<AbstractLink> newSubMenuButtons(final String buttonMarkupId) {
-                List<AbstractLink> links = new ArrayList<>();
+                RealmChoicePanel.this.links.clear();
 
-                links.add(new BootstrapAjaxLink<String>(
+                RealmChoicePanel.this.links.add(new BootstrapAjaxLink<RealmTO>(
                         ButtonList.getButtonMarkupId(),
-                        new Model<String>(),
+                        new Model<RealmTO>(),
                         Buttons.Type.Link,
                         new ResourceModel("realms", "Realms")) {
 
@@ -201,9 +203,9 @@ public class RealmChoicePanel extends Panel {
 
                 for (Pair<String, RealmTO> link : realmTree.getObject()) {
                     final RealmTO realmTO = link.getValue();
-                    links.add(new BootstrapAjaxLink<String>(
+                    RealmChoicePanel.this.links.add(new BootstrapAjaxLink<RealmTO>(
                             ButtonList.getButtonMarkupId(),
-                            new Model<String>(),
+                            Model.of(realmTO),
                             Buttons.Type.Link,
                             new Model<>(link.getKey())) {
 
@@ -232,9 +234,9 @@ public class RealmChoicePanel extends Panel {
                 }
 
                 if (!dynRealmTree.getObject().isEmpty()) {
-                    links.add(new BootstrapAjaxLink<String>(
+                    RealmChoicePanel.this.links.add(new BootstrapAjaxLink<RealmTO>(
                             ButtonList.getButtonMarkupId(),
-                            new Model<String>(),
+                            new Model<RealmTO>(),
                             Buttons.Type.Link,
                             new ResourceModel("dynrealms", "Dynamic Realms")) {
 
@@ -263,9 +265,9 @@ public class RealmChoicePanel extends Panel {
                         realmTO.setName(dynRealmTO.getKey());
                         realmTO.setFullPath(dynRealmTO.getKey());
 
-                        links.add(new BootstrapAjaxLink<String>(
+                        RealmChoicePanel.this.links.add(new BootstrapAjaxLink<RealmTO>(
                                 ButtonList.getButtonMarkupId(),
-                                new Model<String>(),
+                                new Model<RealmTO>(),
                                 Buttons.Type.Link,
                                 new Model<>(realmTO.getKey())) {
 
@@ -295,7 +297,7 @@ public class RealmChoicePanel extends Panel {
                     }
                 }
 
-                return links;
+                return RealmChoicePanel.this.links;
             }
         };
         realms.setOutputMarkupId(true);
@@ -404,4 +406,8 @@ public class RealmChoicePanel extends Panel {
             return target;
         }
     }
+
+    public List<AbstractLink> getLinks() {
+        return links;
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a25b7c6f/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java
index 61e4884..e5a92d2 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java
@@ -19,9 +19,10 @@
 package org.apache.syncope.client.console.wizards.any;
 
 import java.util.ArrayList;
+import java.util.List;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Transformer;
-import org.apache.syncope.client.console.rest.RealmRestClient;
+import org.apache.syncope.client.console.pages.Realms;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
@@ -29,6 +30,7 @@ import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.extensions.wizard.WizardStep;
+import org.apache.wicket.markup.html.link.AbstractLink;
 import org.apache.wicket.model.PropertyModel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -58,11 +60,20 @@ public class Details<T extends AnyTO> extends WizardStep {
                     "destinationRealm", "destinationRealm", new PropertyModel<String>(inner, "realm"), false);
             AjaxTextFieldPanel.class.cast(realm).enableJexlHelp();
         } else {
+            final List<AbstractLink> realmLinks = Realms.class.cast(pageRef.getPage()).getRealmChoicePanel().getLinks();
+            final List<RealmTO> realms = new ArrayList<>();
+            for (AbstractLink link : realmLinks) {
+                Object obj = link.getDefaultModelObject();
+                if (obj instanceof RealmTO) {
+                    realms.add((RealmTO) obj);
+                }
+            }
+
             realm = new AjaxDropDownChoicePanel<>(
                     "destinationRealm", "destinationRealm", new PropertyModel<String>(inner, "realm"), false);
 
             ((AjaxDropDownChoicePanel<String>) realm).setChoices(CollectionUtils.collect(
-                    new RealmRestClient().list(),
+                    realms,
                     new Transformer<RealmTO, String>() {
 
                 @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/a25b7c6f/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
index 0ea89e5..8e640fd 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
@@ -19,7 +19,9 @@
 package org.apache.syncope.client.console.wizards.any;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.ListUtils;
@@ -62,15 +64,19 @@ public class Groups extends WizardStep implements ICondition {
 
     private final List<DynRealmTO> allDynRealms = new DynRealmRestClient().list();
 
-    private List<GroupTO> allGroups;
+    private GroupsModel groupsModel;
 
     private final AnyTO anyTO;
 
+    private boolean templateMode;
+
     public <T extends AnyTO> Groups(final AnyWrapper<T> modelObject, final boolean templateMode) {
         super();
+        this.templateMode = templateMode;
 
         this.anyTO = modelObject.getInnerObject();
-        final String realm = templateMode ? "/" : this.anyTO.getRealm();
+
+        groupsModel = new GroupsModel();
 
         // -----------------------------------------------------------------
         // Pre-Authorizations
@@ -127,47 +133,17 @@ public class Groups extends WizardStep implements ICondition {
                         }
                     });
 
-            allGroups = groupRestClient.search(
-                    realm,
-                    SyncopeClient.getGroupSearchConditionBuilder().isAssignable().query(),
-                    1,
-                    MAX_GROUP_LIST_CARDINALITY,
-                    new SortParam<>("name", true),
-                    null);
-
-            // ---------------------------------
-            // Retrieve group memberships
-            // ---------------------------------
-            // this is to be sure to have group names (required to see membership details in approval page)
-            GroupFiqlSearchConditionBuilder searchConditionBuilder = SyncopeClient.getGroupSearchConditionBuilder();
-
-            List<CompleteCondition> conditions = new ArrayList<>();
-            for (MembershipTO membershipTO : GroupableRelatableTO.class.cast(anyTO).getMemberships()) {
-                conditions.add(searchConditionBuilder.is("key").equalTo(membershipTO.getGroupKey()).wrap());
-            }
+            groupsContainer.add(builder.setAllowOrder(true).withFilter().build("groups",
+                    new ListModel<MembershipTO>() {
 
-            List<GroupTO> groups = new ArrayList<>();
-            if (!conditions.isEmpty()) {
-                groups.addAll(groupRestClient.search(
-                        "/",
-                        searchConditionBuilder.or(conditions).query(),
-                        -1,
-                        -1,
-                        new SortParam<>("name", true),
-                        null));
-            }
+                private static final long serialVersionUID = -2583290457773357445L;
 
-            // set group names in membership TOs
-            for (GroupTO group : groups) {
-                MembershipTO membership = GroupableRelatableTO.class.cast(anyTO).getMembership(group.getKey());
-                if (membership != null) {
-                    membership.setGroupName(group.getName());
+                @Override
+                public List<MembershipTO> getObject() {
+                    return Groups.this.groupsModel.getMemberships();
                 }
-            }
 
-            groupsContainer.add(builder.setAllowOrder(true).withFilter().build("groups",
-                    new ListModel<>(GroupableRelatableTO.class.cast(anyTO).getMemberships()),
-                    new AjaxPalettePanel.Builder.Query<MembershipTO>() {
+            }, new AjaxPalettePanel.Builder.Query<MembershipTO>() {
 
                 private static final long serialVersionUID = -7223078772249308813L;
 
@@ -175,11 +151,11 @@ public class Groups extends WizardStep implements ICondition {
                 public List<MembershipTO> execute(final String filter) {
                     return CollectionUtils.collect(
                             StringUtils.isEmpty(filter) || "*".equals(filter)
-                            ? allGroups
+                            ? groupsModel.getObject()
                             : groupRestClient.search(
-                                    realm,
+                                    anyTO.getRealm(),
                                     SyncopeClient.getGroupSearchConditionBuilder().
-                                            isAssignable().and().is("name").equalTo(filter).query(),
+                                    isAssignable().and().is("name").equalTo(filter).query(),
                                     1, MAX_GROUP_LIST_CARDINALITY,
                                     new SortParam<>("name", true),
                                     null),
@@ -194,38 +170,19 @@ public class Groups extends WizardStep implements ICondition {
                     }, new ArrayList<MembershipTO>());
                 }
             }).hideLabel().setOutputMarkupId(true));
-            // ---------------------------------
 
-            // ---------------------------------
-            // Retrieve dyn group memberships
-            // ---------------------------------
-            searchConditionBuilder = SyncopeClient.getGroupSearchConditionBuilder();
+            dyngroupsContainer.add(new AjaxPalettePanel.Builder<String>().setAllowOrder(true).build("dyngroups",
+                    new ListModel<String>() {
 
-            conditions = new ArrayList<>();
-            for (String groupKey : GroupableRelatableTO.class.cast(anyTO).getDynGroups()) {
-                conditions.add(searchConditionBuilder.is("key").equalTo(groupKey).wrap());
-            }
+                private static final long serialVersionUID = -2583290457773357445L;
 
-            groups = new ArrayList<>();
-            if (!conditions.isEmpty()) {
-                groups.addAll(groupRestClient.search(
-                        "/",
-                        searchConditionBuilder.or(conditions).query(),
-                        -1,
-                        -1,
-                        new SortParam<>("name", true),
-                        null));
-            }
-
-            dyngroupsContainer.add(new AjaxPalettePanel.Builder<String>().setAllowOrder(true).build("dyngroups",
-                    new ListModel<>(CollectionUtils.collect(groups, new Transformer<GroupTO, String>() {
+                @Override
+                public List<String> getObject() {
+                    return Groups.this.groupsModel.getDynMemberships();
+                }
 
-                        @Override
-                        public String transform(final GroupTO input) {
-                            return input.getName();
-                        }
-                    }, new ArrayList<String>())),
-                    new ListModel<>(CollectionUtils.collect(allGroups, new Transformer<GroupTO, String>() {
+            }, new ListModel<>(CollectionUtils.collect(groupsModel.getObject(),
+                            new Transformer<GroupTO, String>() {
 
                         @Override
                         public String transform(final GroupTO input) {
@@ -264,8 +221,143 @@ public class Groups extends WizardStep implements ICondition {
     public boolean evaluate() {
         return ((anyTO instanceof GroupTO)
                 ? CollectionUtils.isNotEmpty(allDynRealms)
-                : CollectionUtils.isNotEmpty(allDynRealms) || CollectionUtils.isNotEmpty(allGroups))
+                : CollectionUtils.isNotEmpty(allDynRealms) || CollectionUtils.isNotEmpty(groupsModel.getObject()))
                 && SyncopeConsoleApplication.get().getSecuritySettings().getAuthorizationStrategy().
-                        isActionAuthorized(this, RENDER);
+                isActionAuthorized(this, RENDER);
+    }
+
+    private class GroupsModel extends ListModel<GroupTO> {
+
+        private static final long serialVersionUID = -4541954630939063927L;
+
+        private List<GroupTO> groups;
+
+        private List<MembershipTO> memberships;
+
+        private List<String> dynMemberships;
+
+        private String realm;
+
+        @Override
+        public List<GroupTO> getObject() {
+            reload();
+            return groups;
+        }
+
+        /**
+         * Retrieve the first MAX_GROUP_LIST_CARDINALITY assignable.
+         */
+        private void reloadObject() {
+            groups = groupRestClient.search(
+                    realm,
+                    SyncopeClient.getGroupSearchConditionBuilder().isAssignable().query(),
+                    1,
+                    MAX_GROUP_LIST_CARDINALITY,
+                    new SortParam<>("name", true),
+                    null);
+        }
+
+        public List<MembershipTO> getMemberships() {
+            reload();
+            return memberships;
+        }
+
+        /**
+         * Retrieve group memberships.
+         */
+        private void reloadMemberships() {
+            // this is to be sure to have group names (required to see membership details in approval page)
+            GroupFiqlSearchConditionBuilder searchConditionBuilder = SyncopeClient.getGroupSearchConditionBuilder();
+
+            List<CompleteCondition> conditions = new ArrayList<>();
+            for (MembershipTO membershipTO : GroupableRelatableTO.class.cast(anyTO).getMemberships()) {
+                conditions.add(searchConditionBuilder.is("key").equalTo(membershipTO.getGroupKey()).wrap());
+            }
+
+            Map<String, GroupTO> assignedGroups = new HashMap<>();
+            if (!conditions.isEmpty()) {
+                for (GroupTO group : groupRestClient.search(
+                        realm,
+                        searchConditionBuilder.isAssignable().and().or(conditions).query(),
+                        -1,
+                        -1,
+                        new SortParam<>("name", true),
+                        null)) {
+                    assignedGroups.put(group.getKey(), group);
+                }
+            }
+
+            // set group names in membership TOs and remove membership not assignable
+            List<MembershipTO> toBeRemoved = new ArrayList<>();
+            for (MembershipTO membership : GroupableRelatableTO.class.cast(anyTO).getMemberships()) {
+                if (assignedGroups.containsKey(membership.getRightKey())) {
+                    membership.setGroupName(assignedGroups.get(membership.getRightKey()).getName());
+                } else {
+                    toBeRemoved.add(membership);
+                }
+            }
+            GroupableRelatableTO.class.cast(anyTO).getMemberships().removeAll(toBeRemoved);
+
+            memberships = GroupableRelatableTO.class.cast(anyTO).getMemberships();
+        }
+
+        public List<String> getDynMemberships() {
+            reload();
+            return dynMemberships;
+        }
+
+        /**
+         * Retrieve dyn group memberships.
+         */
+        private void reloadDynMemberships() {
+            GroupFiqlSearchConditionBuilder searchConditionBuilder = SyncopeClient.getGroupSearchConditionBuilder();
+
+            ArrayList<CompleteCondition> conditions = new ArrayList<>();
+            for (String groupKey : GroupableRelatableTO.class.cast(anyTO).getDynGroups()) {
+                conditions.add(searchConditionBuilder.is("key").equalTo(groupKey).wrap());
+            }
+
+            Map<String, GroupTO> assignedGroups = new HashMap<>();
+            if (!conditions.isEmpty()) {
+                for (GroupTO group : groupRestClient.search(
+                        "/",
+                        searchConditionBuilder.or(conditions).query(),
+                        -1,
+                        -1,
+                        new SortParam<>("name", true),
+                        null)) {
+                    assignedGroups.put(group.getKey(), group);
+                }
+            }
+
+            dynMemberships = CollectionUtils.collect(assignedGroups.values(), new Transformer<GroupTO, String>() {
+
+                @Override
+                public String transform(final GroupTO input) {
+                    return input.getName();
+                }
+            }, new ArrayList<String>());
+        }
+
+        /**
+         * Reload data if the realm changes (see SYNCOPE-1135).
+         */
+        private void reload() {
+            boolean reload;
+
+            if (Groups.this.templateMode) {
+                reload = realm == null;
+                realm = "/";
+            } else {
+                reload = !Groups.this.anyTO.getRealm().equalsIgnoreCase(realm);
+                realm = Groups.this.anyTO.getRealm();
+            }
+
+            if (reload) {
+                reloadObject();
+                reloadMemberships();
+                reloadDynMemberships();
+            }
+        }
     }
 }