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 2016/06/15 18:06:12 UTC

syncope git commit: [SYNCOPE-859] provides bulk unassign/unlink/deprovision from resources

Repository: syncope
Updated Branches:
  refs/heads/master 36110c298 -> bc72d69a4


[SYNCOPE-859] provides bulk unassign/unlink/deprovision from resources


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

Branch: refs/heads/master
Commit: bc72d69a4a44f30199f332b211bdebc7a82b250d
Parents: 36110c2
Author: fmartelli <fa...@gmail.com>
Authored: Wed Jun 15 20:05:53 2016 +0200
Committer: fmartelli <fa...@gmail.com>
Committed: Wed Jun 15 20:05:53 2016 +0200

----------------------------------------------------------------------
 .../commons/ResourceStatusDataProvider.java     | 143 ++++++++++
 .../console/commons/status/StatusUtils.java     |   2 +-
 .../console/panels/AnyObjectDirectoryPanel.java |   4 +-
 .../console/panels/GroupDirectoryPanel.java     |   4 +-
 .../console/panels/UserDirectoryPanel.java      |   6 +-
 .../console/status/AnyStatusDirectoryPanel.java | 261 +++++++++++++++++++
 .../client/console/status/AnyStatusModal.java   |  49 ++++
 .../status/ResourceStatusDirectoryPanel.java    | 155 +++++++++++
 .../console/status/ResourceStatusModal.java     | 102 ++++++++
 .../console/status/StatusDirectoryPanel.java    | 260 ------------------
 .../client/console/status/StatusModal.java      |  23 +-
 .../console/topology/TopologyTogglePanel.java   |  17 ++
 .../client/console/wizards/any/StatusPanel.java |   8 +-
 .../client/console/status/AnyStatusModal.html   |  23 ++
 .../console/status/ResourceStatusModal.html     |  24 ++
 .../client/console/status/StatusModal.html      |   3 +
 .../console/status/StatusModal.properties       |   2 +
 .../console/status/StatusModal_it.properties    |   2 +
 .../console/status/StatusModal_pt_BR.properties |   2 +
 .../console/status/StatusModal_ru.properties    |   8 +-
 .../console/topology/TopologyTogglePanel.html   |   1 +
 .../topology/TopologyTogglePanel.properties     |   2 +
 .../topology/TopologyTogglePanel_it.properties  |   2 +
 .../TopologyTogglePanel_pt_BR.properties        |   2 +
 .../topology/TopologyTogglePanel_ru.properties  |   2 +
 .../syncope/fit/console/TopologyITCase.java     |  28 ++
 26 files changed, 856 insertions(+), 279 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/java/org/apache/syncope/client/console/commons/ResourceStatusDataProvider.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/ResourceStatusDataProvider.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/ResourceStatusDataProvider.java
new file mode 100644
index 0000000..53b5181
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/ResourceStatusDataProvider.java
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.status.ConnObjectWrapper;
+import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.console.commons.status.StatusUtils;
+import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
+import org.apache.syncope.client.console.rest.AnyObjectRestClient;
+import org.apache.syncope.client.console.rest.GroupRestClient;
+import org.apache.syncope.client.console.rest.UserRestClient;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.search.AbstractFiqlSearchConditionBuilder;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+
+public class ResourceStatusDataProvider extends DirectoryDataProvider<StatusBean> {
+
+    private static final long serialVersionUID = 6267494272884913376L;
+
+    private final StatusUtils statusUtils;
+
+    private final String resource;
+
+    private final SortableDataProviderComparator<StatusBean> comparator;
+
+    private final AbstractAnyRestClient<? extends AnyTO, ?> restClient;
+
+    protected String fiql;
+
+    private final String realm;
+
+    private final String type;
+
+    public ResourceStatusDataProvider(
+            final String type,
+            final String resource,
+            final int paginatorRows,
+            final String realm) {
+
+        super(paginatorRows);
+        statusUtils = new StatusUtils();
+        this.resource = resource;
+
+        AbstractFiqlSearchConditionBuilder bld;
+
+        if (StringUtils.isEmpty(type)) {
+            this.fiql = null;
+            restClient = null;
+        } else {
+            switch (type) {
+                case "USER":
+                    bld = SyncopeClient.getUserSearchConditionBuilder();
+                    restClient = new UserRestClient();
+                    break;
+                case "GROUP":
+                    bld = SyncopeClient.getGroupSearchConditionBuilder();
+                    restClient = new GroupRestClient();
+                    break;
+                default:
+                    bld = SyncopeClient.getAnyObjectSearchConditionBuilder(type);
+                    restClient = new AnyObjectRestClient();
+            }
+
+            this.fiql = bld.hasResources(resource).query();
+        }
+
+        setSort("connObjectLink", SortOrder.ASCENDING);
+
+        this.comparator = new SortableDataProviderComparator<StatusBean>(this);
+
+        this.realm = realm;
+        this.type = type;
+    }
+
+    @Override
+    public Iterator<StatusBean> iterator(final long first, final long count) {
+        if (fiql == null) {
+            return Collections.<StatusBean>emptyList().iterator();
+        }
+
+        final int page = ((int) first / paginatorRows);
+        List<? extends AnyTO> result
+                = restClient.search(realm, fiql, (page < 0 ? 0 : page) + 1, paginatorRows, getSort(), type);
+
+        List<StatusBean> res = CollectionUtils.collect(result, new Transformer<AnyTO, StatusBean>() {
+
+            @Override
+            public StatusBean transform(final AnyTO input) {
+                final List<ConnObjectWrapper> connObjects
+                        = statusUtils.getConnectorObjects(input, Collections.singletonList(resource));
+
+                return statusUtils.getStatusBean(
+                        input,
+                        resource,
+                        connObjects == null ? null : connObjects.iterator().next().getConnObjectTO(),
+                        input instanceof GroupTO);
+            }
+        }, new ArrayList<StatusBean>());
+
+        Collections.sort(res, comparator);
+        return res.iterator();
+    }
+
+    @Override
+    public long size() {
+        if (fiql == null) {
+            return 0;
+        }
+        return restClient.searchCount(realm, fiql, type);
+    }
+
+    @Override
+    public IModel<StatusBean> model(final StatusBean object) {
+        return new CompoundPropertyModel<>(object);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java
index 27e7dbc..d3d9558 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java
@@ -66,7 +66,7 @@ public class StatusUtils implements Serializable {
         return objects;
     }
 
-    private List<ConnObjectWrapper> getConnectorObjects(
+    public List<ConnObjectWrapper> getConnectorObjects(
             final AnyTO any, final Collection<String> resources) {
 
         final List<ConnObjectWrapper> objects = new ArrayList<>();

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/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 5473ee0..5e9c314 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
@@ -28,7 +28,7 @@ import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.notifications.NotificationTasks;
 import org.apache.syncope.client.console.rest.AnyObjectRestClient;
-import org.apache.syncope.client.console.status.StatusModal;
+import org.apache.syncope.client.console.status.AnyStatusModal;
 import org.apache.syncope.client.console.tasks.AnyPropagationTasks;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.AttrColumn;
@@ -172,7 +172,7 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO, AnyO
                                             model.getObject()));
                             altDefaultModal.setFormModel(formModel);
 
-                            target.add(altDefaultModal.setContent(new StatusModal<>(
+                            target.add(altDefaultModal.setContent(new AnyStatusModal<>(
                                     altDefaultModal, pageRef, formModel.getObject().getInnerObject(), false)));
 
                             altDefaultModal.header(new Model<>(

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/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 3da0f44..f960936 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
@@ -33,7 +33,7 @@ import org.apache.syncope.client.console.notifications.NotificationTasks;
 import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.rest.GroupRestClient;
-import org.apache.syncope.client.console.status.StatusModal;
+import org.apache.syncope.client.console.status.AnyStatusModal;
 import org.apache.syncope.client.console.tasks.AnyPropagationTasks;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.AttrColumn;
@@ -245,7 +245,7 @@ public class GroupDirectoryPanel extends AnyDirectoryPanel<GroupTO, GroupRestCli
                                 new AnyWrapper<>(model.getObject()));
                         altDefaultModal.setFormModel(formModel);
 
-                        target.add(altDefaultModal.setContent(new StatusModal<>(
+                        target.add(altDefaultModal.setContent(new AnyStatusModal<>(
                                 altDefaultModal, pageRef, formModel.getObject().getInnerObject(), false)));
 
                         altDefaultModal.header(new Model<>(

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/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 fed9254..2884049 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
@@ -29,7 +29,7 @@ import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.notifications.NotificationTasks;
 import org.apache.syncope.client.console.rest.UserRestClient;
-import org.apache.syncope.client.console.status.StatusModal;
+import org.apache.syncope.client.console.status.AnyStatusModal;
 import org.apache.syncope.client.console.tasks.AnyPropagationTasks;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.AttrColumn;
@@ -203,7 +203,7 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO, UserRestClient
                                     new AnyWrapper<>(model.getObject()));
                             altDefaultModal.setFormModel(formModel);
 
-                            target.add(altDefaultModal.setContent(new StatusModal<>(
+                            target.add(altDefaultModal.setContent(new AnyStatusModal<>(
                                     altDefaultModal, pageRef, formModel.getObject().getInnerObject(), false)));
 
                             altDefaultModal.header(new Model<>(
@@ -221,7 +221,7 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO, UserRestClient
                                     new AnyWrapper<>(model.getObject()));
                             altDefaultModal.setFormModel(formModel);
 
-                            target.add(altDefaultModal.setContent(new StatusModal<>(
+                            target.add(altDefaultModal.setContent(new AnyStatusModal<>(
                                     altDefaultModal, pageRef, formModel.getObject().getInnerObject(), true)));
 
                             altDefaultModal.header(new Model<>(

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusDirectoryPanel.java
new file mode 100644
index 0000000..89a9d65
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusDirectoryPanel.java
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.status;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.DirectoryDataProvider;
+import org.apache.syncope.client.console.commons.status.AbstractStatusBeanProvider;
+import org.apache.syncope.client.console.commons.status.ConnObjectWrapper;
+import org.apache.syncope.client.console.commons.status.Status;
+import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.console.commons.status.StatusUtils;
+import org.apache.syncope.client.console.panels.DirectoryPanel;
+import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
+import org.apache.syncope.client.console.panels.ModalPanel;
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
+import org.apache.syncope.client.console.rest.AnyObjectRestClient;
+import org.apache.syncope.client.console.rest.GroupRestClient;
+import org.apache.syncope.client.console.rest.ResourceRestClient;
+import org.apache.syncope.client.console.rest.UserRestClient;
+import org.apache.syncope.client.console.status.AnyStatusDirectoryPanel.AttributableStatusProvider;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.StringResourceModel;
+
+public class AnyStatusDirectoryPanel
+        extends DirectoryPanel<StatusBean, StatusBean, DirectoryDataProvider<StatusBean>, AbstractAnyRestClient<?, ?>>
+        implements ModalPanel {
+
+    private static final long serialVersionUID = -9148734710505211261L;
+
+    private final BaseModal<?> baseModal;
+
+    private final MultilevelPanel multiLevelPanelRef;
+
+    private final AnyTO anyTO;
+
+    private final boolean statusOnly;
+
+    public AnyStatusDirectoryPanel(
+            final BaseModal<?> baseModal,
+            final MultilevelPanel multiLevelPanelRef,
+            final PageReference pageRef,
+            final AnyTO anyTO) {
+
+        this(baseModal, multiLevelPanelRef, pageRef, anyTO, false);
+    }
+
+    public AnyStatusDirectoryPanel(
+            final BaseModal<?> baseModal,
+            final MultilevelPanel multiLevelPanelRef,
+            final PageReference pageRef,
+            final AnyTO anyTO,
+            final boolean statusOnly) {
+
+        super(MultilevelPanel.FIRST_LEVEL_ID, pageRef);
+        this.baseModal = baseModal;
+        this.multiLevelPanelRef = multiLevelPanelRef;
+        this.statusOnly = statusOnly;
+        this.anyTO = anyTO;
+        this.itemKeyFieldName = statusOnly ? "anyKey" : "resourceName";
+
+        if (anyTO instanceof UserTO) {
+            this.restClient = new UserRestClient();
+        } else if (anyTO instanceof GroupTO) {
+            this.restClient = new GroupRestClient();
+        } else {
+            this.restClient = new AnyObjectRestClient();
+        }
+
+        initResultTable();
+    }
+
+    @Override
+    protected void resultTableCustomChanges(final AjaxDataTablePanel.Builder<StatusBean, String> resultTableBuilder) {
+        resultTableBuilder.setMultiLevelPanel(baseModal, multiLevelPanelRef);
+    }
+
+    @Override
+    protected List<IColumn<StatusBean, String>> getColumns() {
+        final List<IColumn<StatusBean, String>> columns = new ArrayList<>();
+
+        columns.add(new AbstractColumn<StatusBean, String>(
+                new StringResourceModel("resourceName", this, null), "resourceName") {
+
+            private static final long serialVersionUID = 2054811145491901166L;
+
+            @Override
+            public void populateItem(
+                    final Item<ICellPopulator<StatusBean>> cellItem,
+                    final String componentId,
+                    final IModel<StatusBean> model) {
+
+                cellItem.add(new Label(componentId, model.getObject().getResourceName()) {
+
+                    private static final long serialVersionUID = 8432079838783825801L;
+
+                    @Override
+                    protected void onComponentTag(final ComponentTag tag) {
+                        if (model.getObject().isLinked()) {
+                            super.onComponentTag(tag);
+                        } else {
+                            tag.put("style", "color: #DDDDDD");
+                        }
+                    }
+                });
+            }
+        });
+
+        columns.add(new PropertyColumn<StatusBean, String>(
+                new StringResourceModel("connObjectLink", this, null), "connObjectLink", "connObjectLink"));
+
+        columns.add(new AbstractColumn<StatusBean, String>(new StringResourceModel("status", this, null)) {
+
+            private static final long serialVersionUID = -3503023501954863131L;
+
+            @Override
+            public void populateItem(
+                    final Item<ICellPopulator<StatusBean>> cellItem,
+                    final String componentId,
+                    final IModel<StatusBean> model) {
+
+                if (model.getObject().isLinked()) {
+                    cellItem.add(StatusUtils.getStatusImage(componentId, model.getObject().getStatus()));
+                } else {
+                    cellItem.add(new Label(componentId, ""));
+                }
+            }
+        });
+
+        return columns;
+    }
+
+    @Override
+    protected Collection<ActionLink.ActionType> getBulkActions() {
+        final List<ActionLink.ActionType> bulkActions = new ArrayList<>();
+        if (statusOnly) {
+            bulkActions.add(ActionLink.ActionType.SUSPEND);
+            bulkActions.add(ActionLink.ActionType.REACTIVATE);
+        } else {
+            bulkActions.add(ActionLink.ActionType.UNLINK);
+            bulkActions.add(ActionLink.ActionType.LINK);
+            bulkActions.add(ActionLink.ActionType.DEPROVISION);
+            bulkActions.add(ActionLink.ActionType.PROVISION);
+            bulkActions.add(ActionLink.ActionType.ASSIGN);
+            bulkActions.add(ActionLink.ActionType.UNASSIGN);
+
+        }
+        return bulkActions;
+    }
+
+    @Override
+    protected AttributableStatusProvider dataProvider() {
+        return new AttributableStatusProvider();
+    }
+
+    @Override
+    protected String paginatorRowsKey() {
+        return StringUtils.EMPTY;
+    }
+
+    public class AttributableStatusProvider extends AbstractStatusBeanProvider {
+
+        private static final long serialVersionUID = 4586969457669796621L;
+
+        private final StatusUtils statusUtils;
+
+        AttributableStatusProvider() {
+            super(statusOnly ? "resourceName" : "connObjectLink");
+            statusUtils = new StatusUtils();
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public List<StatusBean> getStatusBeans() {
+            // this is required to retrieve updated data by reloading table
+            final AnyTO actual = restClient.read(anyTO.getKey());
+
+            final List<String> resources = new ArrayList<>();
+            for (ResourceTO resourceTO : new ResourceRestClient().list()) {
+                resources.add(resourceTO.getKey());
+            }
+
+            final List<ConnObjectWrapper> connObjects = statusUtils.getConnectorObjects(actual);
+
+            final List<StatusBean> statusBeans = new ArrayList<>(connObjects.size() + 1);
+
+            for (ConnObjectWrapper entry : connObjects) {
+                final StatusBean statusBean = statusUtils.getStatusBean(actual,
+                        entry.getResourceName(),
+                        entry.getConnObjectTO(),
+                        actual instanceof GroupTO);
+
+                statusBeans.add(statusBean);
+                resources.remove(entry.getResourceName());
+            }
+
+            if (statusOnly) {
+                final StatusBean syncope = new StatusBean(actual, "Syncope");
+
+                syncope.setConnObjectLink(((UserTO) actual).getUsername());
+
+                Status syncopeStatus = Status.UNDEFINED;
+                if (((UserTO) actual).getStatus() != null) {
+                    try {
+                        syncopeStatus = Status.valueOf(((UserTO) actual).getStatus().toUpperCase());
+                    } catch (IllegalArgumentException e) {
+                        LOG.warn("Unexpected status found: {}", ((UserTO) actual).getStatus(), e);
+                    }
+                }
+                syncope.setStatus(syncopeStatus);
+
+                statusBeans.add(syncope);
+            } else {
+                for (String resource : resources) {
+                    final StatusBean statusBean = statusUtils.getStatusBean(actual,
+                            resource,
+                            null,
+                            actual instanceof GroupTO);
+
+                    statusBean.setLinked(false);
+                    statusBeans.add(statusBean);
+                }
+            }
+
+            return statusBeans;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusModal.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusModal.java b/client/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusModal.java
new file mode 100644
index 0000000..3af3bae
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusModal.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.status;
+
+import org.apache.syncope.client.console.commons.DirectoryDataProvider;
+import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.console.panels.DirectoryPanel;
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.wicket.PageReference;
+
+public class AnyStatusModal<T extends AnyTO> extends StatusModal<T> {
+
+    private static final long serialVersionUID = 1066124171682570080L;
+
+    public AnyStatusModal(
+            final BaseModal<?> baseModal, final PageReference pageReference, final T anyTO, final boolean statusOnly) {
+        super(baseModal, pageReference, anyTO, statusOnly);
+    }
+
+    @Override
+    protected DirectoryPanel<
+        StatusBean, StatusBean, DirectoryDataProvider<StatusBean>, AbstractAnyRestClient<?, ?>> getStatusDirectoryPanel(
+            final MultilevelPanel mlp,
+            final BaseModal<?> baseModal,
+            final PageReference pageReference,
+            final T entity,
+            final boolean statusOnly) {
+        return new AnyStatusDirectoryPanel(baseModal, mlp, pageReference, entity, statusOnly);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusDirectoryPanel.java
new file mode 100644
index 0000000..95bc50a
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusDirectoryPanel.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.status;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.DirectoryDataProvider;
+import org.apache.syncope.client.console.commons.ResourceStatusDataProvider;
+import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.console.commons.status.StatusUtils;
+import org.apache.syncope.client.console.panels.DirectoryPanel;
+import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
+import org.apache.syncope.client.console.panels.ModalPanel;
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
+import org.apache.syncope.client.console.rest.AnyObjectRestClient;
+import org.apache.syncope.client.console.rest.GroupRestClient;
+import org.apache.syncope.client.console.rest.UserRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.StringResourceModel;
+
+public class ResourceStatusDirectoryPanel
+        extends DirectoryPanel<StatusBean, StatusBean, DirectoryDataProvider<StatusBean>, AbstractAnyRestClient<?, ?>>
+        implements ModalPanel {
+
+    private static final long serialVersionUID = -9148734710505211261L;
+
+    private final BaseModal<?> baseModal;
+
+    private final MultilevelPanel multiLevelPanelRef;
+
+    private String type;
+
+    private final ResourceTO resourceTO;
+
+    public ResourceStatusDirectoryPanel(
+            final BaseModal<?> baseModal,
+            final MultilevelPanel multiLevelPanelRef,
+            final PageReference pageRef,
+            final String type,
+            final ResourceTO resourceTO) {
+
+        super(MultilevelPanel.FIRST_LEVEL_ID, pageRef);
+        this.baseModal = baseModal;
+        this.multiLevelPanelRef = multiLevelPanelRef;
+        this.type = type;
+        this.resourceTO = resourceTO;
+        this.itemKeyFieldName = "anyKey";
+
+        initResultTable();
+    }
+
+    @Override
+    protected void resultTableCustomChanges(final AjaxDataTablePanel.Builder<StatusBean, String> resultTableBuilder) {
+        resultTableBuilder.setMultiLevelPanel(baseModal, multiLevelPanelRef);
+    }
+
+    @Override
+    protected List<IColumn<StatusBean, String>> getColumns() {
+        final List<IColumn<StatusBean, String>> columns = new ArrayList<>();
+
+        columns.add(new PropertyColumn<StatusBean, String>(
+                new StringResourceModel("anyKey", this, null), "anyKey", "anyKey"));
+
+        columns.add(new PropertyColumn<StatusBean, String>(
+                new StringResourceModel("connObjectLink", this, null), "connObjectLink", "connObjectLink"));
+
+        columns.add(new AbstractColumn<StatusBean, String>(new StringResourceModel("status", this, null)) {
+
+            private static final long serialVersionUID = -3503023501954863131L;
+
+            @Override
+            public void populateItem(
+                    final Item<ICellPopulator<StatusBean>> cellItem,
+                    final String componentId,
+                    final IModel<StatusBean> model) {
+
+                if (model.getObject().isLinked()) {
+                    cellItem.add(StatusUtils.getStatusImage(componentId, model.getObject().getStatus()));
+                } else {
+                    cellItem.add(new Label(componentId, ""));
+                }
+            }
+        });
+
+        return columns;
+    }
+
+    public void updateResultTable(final String type, final AjaxRequestTarget target) {
+        this.type = type;
+
+        if (StringUtils.isNoneEmpty(type)) {
+            switch (type) {
+                case "USER":
+                    this.restClient = new UserRestClient();
+                    break;
+                case "GROUP":
+                    this.restClient = new GroupRestClient();
+                    break;
+                default:
+                    this.restClient = new AnyObjectRestClient();
+            }
+        }
+
+        super.updateResultTable(target);
+    }
+
+    @Override
+    protected Collection<ActionLink.ActionType> getBulkActions() {
+        final List<ActionLink.ActionType> bulkActions = new ArrayList<>();
+        bulkActions.add(ActionLink.ActionType.UNLINK);
+        bulkActions.add(ActionLink.ActionType.DEPROVISION);
+        bulkActions.add(ActionLink.ActionType.UNASSIGN);
+        return bulkActions;
+    }
+
+    @Override
+    protected ResourceStatusDataProvider dataProvider() {
+        return new ResourceStatusDataProvider(type, resourceTO.getKey(), rows, "/");
+    }
+
+    @Override
+    protected String paginatorRowsKey() {
+        return StringUtils.EMPTY;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusModal.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusModal.java b/client/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusModal.java
new file mode 100644
index 0000000..842a054
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusModal.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.status;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.DirectoryDataProvider;
+import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.console.panels.DirectoryPanel;
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
+import org.apache.syncope.client.console.rest.AnyTypeRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.Model;
+
+public class ResourceStatusModal extends StatusModal<ResourceTO> {
+
+    private static final long serialVersionUID = 1066124171682570080L;
+
+    private Model<String> typeModel = new Model<>();
+
+    public ResourceStatusModal(
+            final BaseModal<?> baseModal,
+            final PageReference pageReference,
+            final ResourceTO resourceTO,
+            final boolean statusOnly) {
+        super(baseModal, pageReference, resourceTO, statusOnly);
+
+        final LoadableDetachableModel<List<String>> types = new LoadableDetachableModel<List<String>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected List<String> load() {
+                List<String> res = CollectionUtils.collect(
+                        new AnyTypeRestClient().list(),
+                        new Transformer<AnyTypeTO, String>() {
+
+                    @Override
+                    public String transform(final AnyTypeTO input) {
+                        return input.getKey();
+                    }
+                }, new ArrayList<String>());
+                Collections.sort(res);
+                return res;
+            }
+        };
+
+        final AjaxDropDownChoicePanel<String> type = new AjaxDropDownChoicePanel<>("type", "type", typeModel);
+        type.setChoices(types);
+        add(type);
+
+        type.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                ResourceStatusDirectoryPanel.class.cast(directoryPanel).
+                        updateResultTable(typeModel.getObject(), target);
+            }
+        });
+    }
+
+    @Override
+    protected DirectoryPanel<
+        StatusBean, StatusBean, DirectoryDataProvider<StatusBean>, AbstractAnyRestClient<?, ?>> getStatusDirectoryPanel(
+            final MultilevelPanel mlp,
+            final BaseModal<?> baseModal,
+            final PageReference pageReference,
+            final ResourceTO entity,
+            final boolean statusOnly) {
+        return new ResourceStatusDirectoryPanel(baseModal, mlp, pageReference, null, entity);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/status/StatusDirectoryPanel.java
deleted file mode 100644
index 5cd2180..0000000
--- a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusDirectoryPanel.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.client.console.status;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.commons.status.AbstractStatusBeanProvider;
-import org.apache.syncope.client.console.commons.status.ConnObjectWrapper;
-import org.apache.syncope.client.console.commons.status.Status;
-import org.apache.syncope.client.console.commons.status.StatusBean;
-import org.apache.syncope.client.console.commons.status.StatusUtils;
-import org.apache.syncope.client.console.panels.DirectoryPanel;
-import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
-import org.apache.syncope.client.console.panels.ModalPanel;
-import org.apache.syncope.client.console.panels.MultilevelPanel;
-import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
-import org.apache.syncope.client.console.rest.AnyObjectRestClient;
-import org.apache.syncope.client.console.rest.GroupRestClient;
-import org.apache.syncope.client.console.rest.ResourceRestClient;
-import org.apache.syncope.client.console.rest.UserRestClient;
-import org.apache.syncope.client.console.status.StatusDirectoryPanel.AttributableStatusProvider;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.ResourceTO;
-import org.apache.syncope.common.lib.to.GroupTO;
-import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
-import org.apache.wicket.markup.ComponentTag;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.repeater.Item;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.StringResourceModel;
-
-public class StatusDirectoryPanel
-        extends DirectoryPanel<StatusBean, StatusBean, AttributableStatusProvider, AbstractAnyRestClient<?, ?>>
-        implements ModalPanel {
-
-    private static final long serialVersionUID = -9148734710505211261L;
-
-    private final BaseModal<?> baseModal;
-
-    private final MultilevelPanel multiLevelPanelRef;
-
-    private final AnyTO anyTO;
-
-    private final boolean statusOnly;
-
-    public StatusDirectoryPanel(
-            final BaseModal<?> baseModal,
-            final MultilevelPanel multiLevelPanelRef,
-            final PageReference pageRef,
-            final AnyTO anyTO) {
-
-        this(baseModal, multiLevelPanelRef, pageRef, anyTO, false);
-    }
-
-    public StatusDirectoryPanel(
-            final BaseModal<?> baseModal,
-            final MultilevelPanel multiLevelPanelRef,
-            final PageReference pageRef,
-            final AnyTO anyTO,
-            final boolean statusOnly) {
-
-        super(MultilevelPanel.FIRST_LEVEL_ID, pageRef);
-        this.baseModal = baseModal;
-        this.multiLevelPanelRef = multiLevelPanelRef;
-        this.statusOnly = statusOnly;
-        this.anyTO = anyTO;
-        this.itemKeyFieldName = statusOnly ? "anyKey" : "resourceName";
-
-        if (anyTO instanceof UserTO) {
-            this.restClient = new UserRestClient();
-        } else if (anyTO instanceof GroupTO) {
-            this.restClient = new GroupRestClient();
-        } else {
-            this.restClient = new AnyObjectRestClient();
-        }
-
-        initResultTable();
-    }
-
-    @Override
-    protected void resultTableCustomChanges(final AjaxDataTablePanel.Builder<StatusBean, String> resultTableBuilder) {
-        resultTableBuilder.setMultiLevelPanel(baseModal, multiLevelPanelRef);
-    }
-
-    @Override
-    protected List<IColumn<StatusBean, String>> getColumns() {
-        final List<IColumn<StatusBean, String>> columns = new ArrayList<>();
-
-        columns.add(new AbstractColumn<StatusBean, String>(
-                new StringResourceModel("resourceName", this, null), "resourceName") {
-
-            private static final long serialVersionUID = 2054811145491901166L;
-
-            @Override
-            public void populateItem(
-                    final Item<ICellPopulator<StatusBean>> cellItem,
-                    final String componentId,
-                    final IModel<StatusBean> model) {
-
-                cellItem.add(new Label(componentId, model.getObject().getResourceName()) {
-
-                    private static final long serialVersionUID = 8432079838783825801L;
-
-                    @Override
-                    protected void onComponentTag(final ComponentTag tag) {
-                        if (model.getObject().isLinked()) {
-                            super.onComponentTag(tag);
-                        } else {
-                            tag.put("style", "color: #DDDDDD");
-                        }
-                    }
-                });
-            }
-        });
-
-        columns.add(new PropertyColumn<StatusBean, String>(
-                new StringResourceModel("connObjectLink", this, null), "connObjectLink", "connObjectLink"));
-
-        columns.add(new AbstractColumn<StatusBean, String>(new StringResourceModel("status", this, null)) {
-
-            private static final long serialVersionUID = -3503023501954863131L;
-
-            @Override
-            public void populateItem(
-                    final Item<ICellPopulator<StatusBean>> cellItem,
-                    final String componentId,
-                    final IModel<StatusBean> model) {
-
-                if (model.getObject().isLinked()) {
-                    cellItem.add(StatusUtils.getStatusImage(componentId, model.getObject().getStatus()));
-                } else {
-                    cellItem.add(new Label(componentId, ""));
-                }
-            }
-        });
-
-        return columns;
-    }
-
-    @Override
-    protected Collection<ActionLink.ActionType> getBulkActions() {
-        final List<ActionLink.ActionType> bulkActions = new ArrayList<>();
-        if (statusOnly) {
-            bulkActions.add(ActionLink.ActionType.SUSPEND);
-            bulkActions.add(ActionLink.ActionType.REACTIVATE);
-        } else {
-            bulkActions.add(ActionLink.ActionType.UNLINK);
-            bulkActions.add(ActionLink.ActionType.LINK);
-            bulkActions.add(ActionLink.ActionType.DEPROVISION);
-            bulkActions.add(ActionLink.ActionType.PROVISION);
-            bulkActions.add(ActionLink.ActionType.ASSIGN);
-            bulkActions.add(ActionLink.ActionType.UNASSIGN);
-
-        }
-        return bulkActions;
-    }
-
-    @Override
-    protected AttributableStatusProvider dataProvider() {
-        return new AttributableStatusProvider();
-    }
-
-    @Override
-    protected String paginatorRowsKey() {
-        return StringUtils.EMPTY;
-    }
-
-    public class AttributableStatusProvider extends AbstractStatusBeanProvider {
-
-        private static final long serialVersionUID = 4586969457669796621L;
-
-        private final StatusUtils statusUtils;
-
-        AttributableStatusProvider() {
-            super(statusOnly ? "resourceName" : "connObjectLink");
-            statusUtils = new StatusUtils();
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public List<StatusBean> getStatusBeans() {
-            // this is required to retrieve updated data by reloading table
-            final AnyTO actual = restClient.read(anyTO.getKey());
-
-            final List<String> resources = new ArrayList<>();
-            for (ResourceTO resourceTO : new ResourceRestClient().list()) {
-                resources.add(resourceTO.getKey());
-            }
-
-            final List<ConnObjectWrapper> connObjects = statusUtils.getConnectorObjects(actual);
-
-            final List<StatusBean> statusBeans = new ArrayList<>(connObjects.size() + 1);
-
-            for (ConnObjectWrapper entry : connObjects) {
-                final StatusBean statusBean = statusUtils.getStatusBean(actual,
-                        entry.getResourceName(),
-                        entry.getConnObjectTO(),
-                        actual instanceof GroupTO);
-
-                statusBeans.add(statusBean);
-                resources.remove(entry.getResourceName());
-            }
-
-            if (statusOnly) {
-                final StatusBean syncope = new StatusBean(actual, "Syncope");
-
-                syncope.setConnObjectLink(((UserTO) actual).getUsername());
-
-                Status syncopeStatus = Status.UNDEFINED;
-                if (((UserTO) actual).getStatus() != null) {
-                    try {
-                        syncopeStatus = Status.valueOf(((UserTO) actual).getStatus().toUpperCase());
-                    } catch (IllegalArgumentException e) {
-                        LOG.warn("Unexpected status found: {}", ((UserTO) actual).getStatus(), e);
-                    }
-                }
-                syncope.setStatus(syncopeStatus);
-
-                statusBeans.add(syncope);
-            } else {
-                for (String resource : resources) {
-                    final StatusBean statusBean = statusUtils.getStatusBean(actual,
-                            resource,
-                            null,
-                            actual instanceof GroupTO);
-
-                    statusBean.setLinked(false);
-                    statusBeans.add(statusBean);
-                }
-            }
-
-            return statusBeans;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java b/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
index da05b49..e016d61 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
@@ -18,22 +18,37 @@
  */
 package org.apache.syncope.client.console.status;
 
+import java.io.Serializable;
+import org.apache.syncope.client.console.commons.DirectoryDataProvider;
+import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.console.panels.DirectoryPanel;
 import org.apache.syncope.client.console.panels.ModalPanel;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.markup.html.panel.Panel;
 
-public class StatusModal<T extends AnyTO> extends Panel implements ModalPanel {
+public abstract class StatusModal<T extends Serializable> extends Panel implements ModalPanel {
 
     private static final long serialVersionUID = 1066124171682570080L;
 
+    protected final DirectoryPanel<StatusBean, StatusBean, ?, ?> directoryPanel;
+
     public StatusModal(
-            final BaseModal<?> baseModal, final PageReference pageReference, final T anyTO, final boolean statusOnly) {
+            final BaseModal<?> baseModal, final PageReference pageReference, final T entity, final boolean statusOnly) {
         super(BaseModal.CONTENT_ID);
 
         final MultilevelPanel mlp = new MultilevelPanel("status");
-        add(mlp.setFirstLevel(new StatusDirectoryPanel(baseModal, mlp, pageReference, anyTO, statusOnly)));
+        this.directoryPanel = getStatusDirectoryPanel(mlp, baseModal, pageReference, entity, statusOnly);
+        add(mlp.setFirstLevel(this.directoryPanel));
     }
+
+    protected abstract DirectoryPanel<
+        StatusBean, StatusBean, DirectoryDataProvider<StatusBean>, AbstractAnyRestClient<?, ?>> getStatusDirectoryPanel(
+            final MultilevelPanel mlp,
+            final BaseModal<?> baseModal,
+            final PageReference pageReference,
+            final T entity,
+            final boolean statusOnly);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
index fc9649b..9177301 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyTogglePanel.java
@@ -30,6 +30,7 @@ import org.apache.syncope.client.console.wizards.resources.ResourceWizardBuilder
 import org.apache.syncope.client.console.panels.TogglePanel;
 import org.apache.syncope.client.console.rest.ConnectorRestClient;
 import org.apache.syncope.client.console.rest.ResourceRestClient;
+import org.apache.syncope.client.console.status.ResourceStatusModal;
 import org.apache.syncope.client.console.tasks.PropagationTasks;
 import org.apache.syncope.client.console.tasks.PushTasks;
 import org.apache.syncope.client.console.tasks.SchedTasks;
@@ -342,6 +343,22 @@ public class TopologyTogglePanel extends TogglePanel<Serializable> {
         MetaDataRoleAuthorizationStrategy.authorize(edit, ENABLE, StandardEntitlement.RESOURCE_UPDATE);
         fragment.add(edit);
 
+        AjaxLink<String> status = new IndicatingAjaxLink<String>("status") {
+
+            private static final long serialVersionUID = 3776750333491622263L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                ResourceTO modelObject = resourceRestClient.read(node.getKey().toString());
+                target.add(propTaskModal.setContent(
+                        new ResourceStatusModal(propTaskModal, pageRef, modelObject, false)));
+                propTaskModal.header(new ResourceModel("resource.provisioning.status", "Provisioning Status"));
+                propTaskModal.show(true);
+            }
+        };
+        MetaDataRoleAuthorizationStrategy.authorize(status, ENABLE, StandardEntitlement.USER_UPDATE);
+        fragment.add(status);
+
         AjaxLink<String> provision = new IndicatingAjaxLink<String>("provision") {
 
             private static final long serialVersionUID = 3776750333491622263L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/StatusPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/StatusPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/StatusPanel.java
index fab7ace..8594d91 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/StatusPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/StatusPanel.java
@@ -161,8 +161,8 @@ public class StatusPanel extends Panel {
 
             @Override
             protected boolean statusCondition(final StatusBean bean) {
-                final Pair<ConnObjectTO, ConnObjectTO> pair =
-                        getConnObjectTO(bean.getAnyKey(), bean.getResourceName(), connObjects);
+                final Pair<ConnObjectTO, ConnObjectTO> pair
+                        = getConnObjectTO(bean.getAnyKey(), bean.getResourceName(), connObjects);
 
                 return pair != null && pair.getRight() != null;
             }
@@ -204,8 +204,8 @@ public class StatusPanel extends Panel {
         private static final long serialVersionUID = 4303365227411467563L;
 
         public RemoteObjectPanel(final StatusBean bean, final List<Pair<ConnObjectTO, ConnObjectWrapper>> connObjects) {
-            final Pair<ConnObjectTO, ConnObjectTO> res =
-                    getConnObjectTO(bean.getAnyKey(), bean.getResourceName(), connObjects);
+            final Pair<ConnObjectTO, ConnObjectTO> res = getConnObjectTO(bean.getAnyKey(), bean.getResourceName(),
+                    connObjects);
             add(new ConnObjectPanel("remoteObject", res == null ? null : res));
         }
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/resources/org/apache/syncope/client/console/status/AnyStatusModal.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/status/AnyStatusModal.html b/client/console/src/main/resources/org/apache/syncope/client/console/status/AnyStatusModal.html
new file mode 100644
index 0000000..7f18503
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/status/AnyStatusModal.html
@@ -0,0 +1,23 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <head><title></title></head>
+  <wicket:extend>
+  </wicket:extend>
+</html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/resources/org/apache/syncope/client/console/status/ResourceStatusModal.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/status/ResourceStatusModal.html b/client/console/src/main/resources/org/apache/syncope/client/console/status/ResourceStatusModal.html
new file mode 100644
index 0000000..75a2e3a
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/status/ResourceStatusModal.html
@@ -0,0 +1,24 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <head><title></title></head>
+  <wicket:extend>
+    <span wicket:id="type"/>
+  </wicket:extend>
+</html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal.html b/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal.html
index 1b04b81..e942a9e 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal.html
@@ -19,6 +19,9 @@ under the License.
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
   <head><title></title></head>
   <wicket:panel>
+    <div class="box">
+      <wicket:child/>
+    </div>
     <span wicket:id="status">[Status]</span>
   </wicket:panel>
 </html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal.properties b/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal.properties
index ef1cdf0..0d74a9d 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal.properties
@@ -16,4 +16,6 @@
 # under the License.
 resourceName=Resource
 connObjectLink=Remote ID
+anyKey=Local ID
 status=Status
+type=Object type to be searched for

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_it.properties
index 948b49d..98b0787 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_it.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_it.properties
@@ -17,3 +17,5 @@
 resourceName=Risorsa
 connObjectLink=ID Remoto
 status=Stato
+anyKey=ID Locale
+type=Tipo di oggetto per il quale cercare

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_pt_BR.properties
index ef1cdf0..8be848c 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_pt_BR.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_pt_BR.properties
@@ -17,3 +17,5 @@
 resourceName=Resource
 connObjectLink=Remote ID
 status=Status
+anyKey=Local ID
+type=Object type to be searched for

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_ru.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_ru.properties b/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_ru.properties
index 85cfd2d..cb92e1c 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_ru.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/status/StatusModal_ru.properties
@@ -15,9 +15,11 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-# resourceName=\u0420\u0435\u0441\u0443\u0440\u0441
+# resourceName=\u00d0\u00a0\u00d0\u00b5\u00d1\u0081\u00d1\u0083\u00d1\u0080\u00d1\u0081
 resourceName=\u0420\u0435\u0441\u0443\u0440\u0441
-# connObjectLink=\u0423\u0447\u0435\u0442\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c
+# connObjectLink=\u00d0\u00a3\u00d1\u0087\u00d0\u00b5\u00d1\u0082\u00d0\u00bd\u00d0\u00b0\u00d1\u008f \u00d0\u00b7\u00d0\u00b0\u00d0\u00bf\u00d0\u00b8\u00d1\u0081\u00d1\u008c
 connObjectLink=\u0423\u0447\u0435\u0442\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c
-# status=\u0421\u0442\u0430\u0442\u0443\u0441
+# status=\u00d0\u00a1\u00d1\u0082\u00d0\u00b0\u00d1\u0082\u00d1\u0083\u00d1\u0081
 status=\u0421\u0442\u0430\u0442\u0443\u0441
+anyKey=Local ID
+type=Object type to be searched for

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.html
index c295894..dbd9d66 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.html
@@ -33,6 +33,7 @@ under the License.
     <wicket:fragment wicket:id="resourceActions">
       <ul class="menu">
         <li><i class="fa fa-pencil"></i><a href="#" wicket:id="edit"><wicket:message key="resource.menu.edit"/></a></li>
+        <li><i class="fa fa-list-ul"></i><a href="#" wicket:id="status"><wicket:message key="resource.menu.provisioning.status"/></a></li>
         <li><i class="fa fa-exchange"></i><a href="#" wicket:id="provision"><wicket:message key="resource.menu.provision"/></a></li>
         <li><i class="fa fa-eye"></i><a href="#" wicket:id="explore"><wicket:message key="resource.menu.explore"/></a></li>
         <li><i class="fa fa-arrow-right"></i><a href="#" wicket:id="propagation"><wicket:message key="task.propagation.list"/></a></li>

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.properties b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.properties
index e46c1ce..97d77f9 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel.properties
@@ -34,3 +34,5 @@ task.pull.list=Pull tasks
 task.push.list=Push tasks
 resource.explore.list=Explore ${key}
 connectors.reload=Reload all connectors
+resource.provisioning.status=Resource Provisioning Status
+resource.menu.provisioning.status=Resource provisioning status

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_it.properties
index 0482bd4..a6cbff2 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_it.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_it.properties
@@ -34,3 +34,5 @@ task.pull.list=Pull task
 task.push.list=Push task
 resource.explore.list=Esplora ${key}
 connectors.reload=Ricarica tutti i connettori
+resource.provisioning.status=Stato di provisioning sulla risorsa
+resource.menu.provisioning.status=Stato provisioning sulla risorsa

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_pt_BR.properties
index 753e230..305e1f5 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_pt_BR.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_pt_BR.properties
@@ -34,3 +34,5 @@ task.pull.list=Pull tasks
 task.push.list=Push tasks
 resource.explore.list=Explorar ${key}
 connectors.reload=Reload all connectors
+resource.provisioning.status=Resource Provisioning Status
+resource.menu.provisioning.status=Resource provisioning status

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_ru.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_ru.properties b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_ru.properties
index e400313..6cbb70c 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_ru.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/topology/TopologyTogglePanel_ru.properties
@@ -53,3 +53,5 @@ task.push.list=\u0417\u0430\u0434\u0430\u0447\u0438 \u043f\u0435\u0440\u0435\u04
 # resource.explore.list=\u00d0\u009f\u00d1\u0080\u00d0\u00be\u00d1\u0081\u00d0\u00bc\u00d0\u00be\u00d1\u0082\u00d1\u0080 ${key}
 resource.explore.list=\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 ${key}
 connectors.reload=Reload all connectors
+resource.provisioning.status=Resource Provisioning Status
+resource.menu.provisioning.status=Resource provisioning status

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc72d69a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
index 1ad33ea..2f5a6ee 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
@@ -79,6 +79,34 @@ public class TopologyITCase extends AbstractConsoleITCase {
     }
 
     @Test
+    public void resourceBulkAction() {
+        wicketTester.clickLink("body:topologyLI:topology");
+
+        Component component = findComponentByProp("key", "body:resources", "ws-target-resource-1");
+        assertNotNull(component);
+        wicketTester.executeAjaxEvent(component.getPageRelativePath() + ":res", Constants.ON_CLICK);
+        wicketTester.clickLink("body:toggle:container:content:togglePanelContainer:container:actions:status");
+
+        wicketTester.assertComponent("body:toggle:outerObjectsRepeater:1:outer", Modal.class);
+
+        FormTester formTester = wicketTester.newFormTester("body:toggle:outerObjectsRepeater:1:outer:form");
+        formTester.setValue("content:type:dropDownChoiceField", "2");
+        wicketTester.executeAjaxEvent(
+                "body:toggle:outerObjectsRepeater:1:outer:form:content:type:dropDownChoiceField",
+                Constants.ON_CHANGE);
+        formTester.setValue("content:type:dropDownChoiceField", "2");
+
+        component = findComponentByProp("anyKey", "body:toggle:outerObjectsRepeater:1:outer:form:content:status:"
+                + "firstLevelContainer:first:container:content:searchContainer:resultTable:tablePanel:groupForm:"
+                + "checkgroup:dataTable", "b3cbc78d-32e6-4bd4-92e0-bbe07566a2ee");
+
+        assertNotNull(component);
+
+        wicketTester.executeAjaxEvent(
+                "body:toggle:outerObjectsRepeater:1:outer:dialog:footer:buttons:0:button", Constants.ON_CLICK);
+    }
+
+    @Test
     public void editProvisioning() {
         wicketTester.clickLink("body:topologyLI:topology");