You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2015/02/16 09:06:58 UTC

[33/59] [abbrv] [partial] syncope git commit: [SYNCOPE-620] Re-organization completed

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java
new file mode 100644
index 0000000..205bfa5
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java
@@ -0,0 +1,286 @@
+/*
+ * 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.panels;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.pages.SchedTaskModalPage;
+import org.apache.syncope.client.console.pages.Tasks;
+import org.apache.syncope.client.console.pages.Tasks.TasksProvider;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
+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.DatePropertyColumn;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.SchedTaskTO;
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+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.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.StringResourceModel;
+import org.apache.wicket.request.http.WebResponse;
+
+public class SchedTasks extends AbstractTasks {
+
+    private static final long serialVersionUID = 525486152284253354L;
+
+    private int paginatorRows;
+
+    private WebMarkupContainer container;
+
+    private ModalWindow window;
+
+    private AjaxDataTablePanel<AbstractTaskTO, String> table;
+
+    public SchedTasks(final String id, final PageReference pageRef) {
+        super(id, pageRef);
+
+        container = new WebMarkupContainer("container");
+        container.setOutputMarkupId(true);
+        add(container);
+
+        window = new ModalWindow("taskWin");
+        window.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        window.setInitialHeight(WIN_HEIGHT);
+        window.setInitialWidth(WIN_WIDTH);
+        window.setCookieName(VIEW_TASK_WIN_COOKIE_NAME);
+        add(window);
+
+        ((Tasks) pageRef.getPage()).setWindowClosedCallback(window, container);
+
+        paginatorRows = prefMan.getPaginatorRows(getWebRequest(), Constants.PREF_SCHED_TASKS_PAGINATOR_ROWS);
+
+        table = Tasks.updateTaskTable(
+                getColumns(),
+                new TasksProvider<SchedTaskTO>(restClient, paginatorRows, getId(), SchedTaskTO.class),
+                container,
+                0,
+                pageRef,
+                restClient);
+
+        container.add(table);
+
+        @SuppressWarnings("rawtypes")
+        Form paginatorForm = new Form("PaginatorForm");
+
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final DropDownChoice rowsChooser = new DropDownChoice("rowsChooser", new PropertyModel(this, "paginatorRows"),
+                prefMan.getPaginatorChoices());
+
+        rowsChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                prefMan.set(getWebRequest(), (WebResponse) getResponse(), Constants.PREF_SCHED_TASKS_PAGINATOR_ROWS,
+                        String.valueOf(paginatorRows));
+
+                table = Tasks.updateTaskTable(
+                        getColumns(),
+                        new TasksProvider<SchedTaskTO>(restClient, paginatorRows, getId(), SchedTaskTO.class),
+                        container,
+                        table == null ? 0 : (int) table.getCurrentPage(),
+                        pageRef,
+                        restClient);
+
+                target.add(container);
+            }
+        });
+
+        paginatorForm.add(rowsChooser);
+        add(paginatorForm);
+
+        AjaxLink createLink = new ClearIndicatingAjaxLink("createLink", pageRef) {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            protected void onClickInternal(final AjaxRequestTarget target) {
+                window.setPageCreator(new ModalWindow.PageCreator() {
+
+                    private static final long serialVersionUID = -7834632442532690940L;
+
+                    @Override
+                    public Page createPage() {
+                        return new SchedTaskModalPage(window, new SchedTaskTO(), pageRef);
+                    }
+                });
+
+                window.show(target);
+            }
+        };
+
+        MetaDataRoleAuthorizationStrategy.authorize(
+                createLink, RENDER, xmlRolesReader.getEntitlement(TASKS, "create"));
+
+        add(createLink);
+    }
+
+    private List<IColumn<AbstractTaskTO, String>> getColumns() {
+        final List<IColumn<AbstractTaskTO, String>> columns = new ArrayList<IColumn<AbstractTaskTO, String>>();
+
+        columns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("key", this, null), "key", "key"));
+        columns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("name", this, null), "name", "name"));
+        columns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("description", this, null), "description", "description"));
+        columns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("class", this, null), "jobClassName", "jobClassName"));
+        columns.add(new DatePropertyColumn<AbstractTaskTO>(
+                new StringResourceModel("lastExec", this, null), "lastExec", "lastExec"));
+        columns.add(new DatePropertyColumn<AbstractTaskTO>(
+                new StringResourceModel("nextExec", this, null), "nextExec", "nextExec"));
+        columns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
+
+        columns.add(new ActionColumn<AbstractTaskTO, String>(new StringResourceModel("actions", this, null, "")) {
+
+            private static final long serialVersionUID = 2054811145491901166L;
+
+            @Override
+            public ActionLinksPanel getActions(final String componentId, final IModel<AbstractTaskTO> model) {
+
+                final SchedTaskTO taskTO = (SchedTaskTO) model.getObject();
+
+                final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, pageRef);
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        window.setPageCreator(new ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = -7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                return new SchedTaskModalPage(window, taskTO, pageRef);
+                            }
+                        });
+
+                        window.show(target);
+                    }
+                }, ActionLink.ActionType.EDIT, TASKS);
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        try {
+                            restClient.startExecution(taskTO.getKey(), false);
+                            getSession().info(getString(Constants.OPERATION_SUCCEEDED));
+                        } catch (SyncopeClientException scce) {
+                            error(scce.getMessage());
+                        }
+
+                        ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
+                        target.add(container);
+                    }
+                }, ActionLink.ActionType.EXECUTE, TASKS);
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        try {
+                            restClient.startExecution(taskTO.getKey(), true);
+                            getSession().info(getString(Constants.OPERATION_SUCCEEDED));
+                        } catch (SyncopeClientException scce) {
+                            error(scce.getMessage());
+                        }
+
+                        ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
+                        target.add(container);
+                    }
+                }, ActionLink.ActionType.DRYRUN, TASKS);
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        try {
+                            restClient.delete(taskTO.getKey(), SchedTaskTO.class);
+                            info(getString(Constants.OPERATION_SUCCEEDED));
+                        } catch (SyncopeClientException scce) {
+                            error(scce.getMessage());
+                        }
+                        target.add(container);
+                        ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
+                    }
+                }, ActionLink.ActionType.DELETE, TASKS);
+
+                return panel;
+            }
+
+            @Override
+            public Component getHeader(final String componentId) {
+                @SuppressWarnings("rawtypes")
+                final ActionLinksPanel panel = new ActionLinksPanel(componentId, new Model(), pageRef);
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        if (target != null) {
+                            target.add(table);
+                        }
+                    }
+                }, ActionLink.ActionType.RELOAD, TASKS, "list");
+
+                return panel;
+            }
+        });
+        return columns;
+    }
+
+    @Override
+    public void onEvent(final IEvent<?> event) {
+        if (event.getPayload() instanceof AbstractSearchResultPanel.EventDataWrapper) {
+            ((AbstractSearchResultPanel.EventDataWrapper) event.getPayload()).getTarget().add(container);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchClause.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchClause.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchClause.java
new file mode 100644
index 0000000..488a2cf
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchClause.java
@@ -0,0 +1,129 @@
+/*
+ * 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.panels;
+
+import java.io.Serializable;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+public class SearchClause implements Serializable {
+
+    private static final long serialVersionUID = 2010794463096110104L;
+
+    public enum Operator {
+
+        AND,
+        OR;
+
+    }
+
+    public enum Type {
+
+        ATTRIBUTE,
+        MEMBERSHIP,
+        RESOURCE,
+        ENTITLEMENT;
+
+    }
+
+    public enum Comparator {
+
+        IS_NULL,
+        IS_NOT_NULL,
+        EQUALS,
+        NOT_EQUALS,
+        GREATER_OR_EQUALS,
+        GREATER_THAN,
+        LESS_OR_EQUALS,
+        LESS_THAN;
+
+    }
+
+    private Operator operator;
+
+    private Type type;
+
+    private String property;
+
+    private Comparator comparator;
+
+    private String value;
+
+    public SearchClause() {
+        setOperator(SearchClause.Operator.AND);
+        setComparator(SearchClause.Comparator.EQUALS);
+    }
+
+    public Operator getOperator() {
+        return operator;
+    }
+
+    public void setOperator(final Operator operator) {
+        this.operator = operator;
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+    public void setType(final Type type) {
+        this.type = type;
+    }
+
+    public String getProperty() {
+        return property;
+    }
+
+    public void setProperty(final String property) {
+        this.property = property;
+    }
+
+    public Comparator getComparator() {
+        return comparator;
+    }
+
+    public void setComparator(final Comparator comparator) {
+        this.comparator = comparator;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(final String value) {
+        this.value = value;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        return EqualsBuilder.reflectionEquals(this, obj);
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    @Override
+    public String toString() {
+        return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchView.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchView.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchView.java
new file mode 100644
index 0000000..b432d82
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchView.java
@@ -0,0 +1,461 @@
+/*
+ * 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.panels;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.PropertyModel;
+
+public class SearchView extends ListView<SearchClause> {
+
+    private static final long serialVersionUID = -527351923968737757L;
+
+    private final WebMarkupContainer searchFormContainer;
+
+    private final boolean required;
+
+    private final IModel<List<SearchClause.Type>> types;
+
+    private final IModel<List<String>> anames;
+
+    private final IModel<List<String>> dnames;
+
+    private final IModel<List<String>> roleNames;
+
+    private final IModel<List<String>> resourceNames;
+
+    private final IModel<List<String>> entitlements;
+
+    public SearchView(final String id, final List<? extends SearchClause> list,
+            final WebMarkupContainer searchFormContainer,
+            final boolean required,
+            final IModel<List<SearchClause.Type>> types,
+            final IModel<List<String>> anames,
+            final IModel<List<String>> dnames,
+            final IModel<List<String>> roleNames,
+            final IModel<List<String>> resourceNames,
+            final IModel<List<String>> entitlements) {
+
+        super(id, list);
+
+        this.searchFormContainer = searchFormContainer;
+        this.required = required;
+        this.types = types;
+        this.anames = anames;
+        this.dnames = dnames;
+        this.roleNames = roleNames;
+        this.resourceNames = resourceNames;
+        this.entitlements = entitlements;
+    }
+
+    @Override
+    protected void populateItem(final ListItem<SearchClause> item) {
+        final SearchClause searchClause = item.getModelObject();
+
+        final DropDownChoice<SearchClause.Operator> operator = new DropDownChoice<SearchClause.Operator>("operator",
+                new PropertyModel<SearchClause.Operator>(searchClause, "operator"),
+                Arrays.asList(SearchClause.Operator.values()));
+        operator.setOutputMarkupPlaceholderTag(true);
+        operator.setNullValid(false);
+        operator.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+            }
+        });
+        item.add(operator);
+        if (item.getIndex() == 0) {
+            operator.setVisible(false);
+        }
+
+        final DropDownChoice<SearchClause.Type> type = new DropDownChoice<SearchClause.Type>("type",
+                new PropertyModel<SearchClause.Type>(searchClause, "type"), types);
+        type.setOutputMarkupId(true);
+        type.setRequired(required);
+        type.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                target.add(searchFormContainer);
+            }
+        });
+        item.add(type);
+
+        @SuppressWarnings("unchecked")
+        final DropDownChoice<String> property = new DropDownChoice<String>("property",
+                new PropertyModel<String>(searchClause, "property"), (IModel) null);
+        property.setOutputMarkupId(true);
+        property.setRequired(required);
+        property.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+            }
+        });
+        item.add(property);
+
+        final TextField<String> value = new TextField<String>("value",
+                new PropertyModel<String>(searchClause, "value"));
+        value.setOutputMarkupId(true);
+        value.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+            }
+        });
+        item.add(value);
+
+        final DropDownChoice<SearchClause.Comparator> comparator =
+                new DropDownChoice<SearchClause.Comparator>("comparator",
+                        new PropertyModel<SearchClause.Comparator>(searchClause, "comparator"),
+                        Collections.<SearchClause.Comparator>emptyList());
+        comparator.setOutputMarkupId(true);
+        comparator.setNullValid(false);
+        comparator.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                if (type.getModelObject() == SearchClause.Type.ATTRIBUTE) {
+                    if (comparator.getModelObject() == SearchClause.Comparator.IS_NULL
+                            || comparator.getModelObject() == SearchClause.Comparator.IS_NOT_NULL) {
+
+                        value.setModelObject(null);
+                        value.setEnabled(false);
+                    } else {
+                        value.setEnabled(true);
+                    }
+                    target.add(value);
+                }
+            }
+        });
+        comparator.setRequired(required);
+        item.add(comparator);
+
+        AjaxLink<Void> drop = new IndicatingAjaxLink<Void>("drop") {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                SearchView.this.getModel().getObject().remove(item.getModelObject());
+                target.add(searchFormContainer);
+            }
+        };
+        item.add(drop);
+        if (item.getIndex() == 0) {
+            drop.setVisible(false);
+            drop.setEnabled(false);
+        } else {
+            drop.setVisible(true);
+            drop.setEnabled(true);
+        }
+
+        final AjaxLink<Void> add = new IndicatingAjaxLink<Void>("add") {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                SearchClause clause = new SearchClause();
+                SearchView.this.getModel().getObject().add(clause);
+                target.add(searchFormContainer);
+            }
+        };
+        item.add(add);
+
+        if (searchClause == null || searchClause.getType() == null) {
+            property.setChoices(Collections.<String>emptyList());
+        } else {
+            switch (searchClause.getType()) {
+                case ATTRIBUTE:
+                    final List<String> names = new ArrayList<String>(dnames.getObject());
+                    if (anames.getObject() != null && !anames.getObject().isEmpty()) {
+                        names.addAll(anames.getObject());
+                    }
+                    Collections.sort(names);
+                    property.setChoices(names);
+
+                    comparator.setChoices(new LoadableDetachableModel<List<SearchClause.Comparator>>() {
+
+                        private static final long serialVersionUID = 5275935387613157437L;
+
+                        @Override
+                        protected List<SearchClause.Comparator> load() {
+                            return Arrays.asList(SearchClause.Comparator.values());
+                        }
+                    });
+                    comparator.setChoiceRenderer(new IChoiceRenderer<SearchClause.Comparator>() {
+
+                        private static final long serialVersionUID = -9086043750227867686L;
+
+                        @Override
+                        public Object getDisplayValue(final SearchClause.Comparator object) {
+                            String display;
+
+                            switch (object) {
+                                case IS_NULL:
+                                    display = "NULL";
+                                    break;
+
+                                case IS_NOT_NULL:
+                                    display = "NOT NULL";
+                                    break;
+
+                                case EQUALS:
+                                    display = "==";
+                                    break;
+
+                                case NOT_EQUALS:
+                                    display = "!=";
+                                    break;
+
+                                case LESS_THAN:
+                                    display = "<";
+                                    break;
+
+                                case LESS_OR_EQUALS:
+                                    display = "<=";
+                                    break;
+
+                                case GREATER_THAN:
+                                    display = ">";
+                                    break;
+
+                                case GREATER_OR_EQUALS:
+                                    display = ">=";
+                                    break;
+
+                                default:
+                                    display = StringUtils.EMPTY;
+                            }
+
+                            return display;
+                        }
+
+                        @Override
+                        public String getIdValue(final SearchClause.Comparator object, int index) {
+                            return getDisplayValue(object).toString();
+                        }
+                    });
+                    if (!comparator.isEnabled()) {
+                        comparator.setEnabled(true);
+                        comparator.setRequired(true);
+                    }
+
+                    if (!value.isEnabled()) {
+                        value.setEnabled(true);
+                    }
+                    break;
+
+                case MEMBERSHIP:
+                    property.setChoices(roleNames);
+                    property.setChoiceRenderer(new IChoiceRenderer<String>() {
+
+                        private static final long serialVersionUID = -4288397951948436434L;
+
+                        @Override
+                        public Object getDisplayValue(final String object) {
+                            return object;
+                        }
+
+                        @Override
+                        public String getIdValue(final String object, final int index) {
+                            return object;
+                        }
+                    });
+
+                    comparator.setChoices(new LoadableDetachableModel<List<SearchClause.Comparator>>() {
+
+                        private static final long serialVersionUID = 5275935387613157437L;
+
+                        @Override
+                        protected List<SearchClause.Comparator> load() {
+                            List<SearchClause.Comparator> comparators = new ArrayList<SearchClause.Comparator>();
+                            comparators.add(SearchClause.Comparator.EQUALS);
+                            comparators.add(SearchClause.Comparator.NOT_EQUALS);
+                            return comparators;
+                        }
+                    });
+                    comparator.setChoiceRenderer(new IChoiceRenderer<SearchClause.Comparator>() {
+
+                        private static final long serialVersionUID = -9086043750227867686L;
+
+                        @Override
+                        public Object getDisplayValue(final SearchClause.Comparator object) {
+                            String display;
+
+                            switch (object) {
+                                case EQUALS:
+                                    display = "IN";
+                                    break;
+
+                                case NOT_EQUALS:
+                                    display = "NOT IN";
+                                    break;
+
+                                default:
+                                    display = StringUtils.EMPTY;
+                            }
+
+                            return display;
+                        }
+
+                        @Override
+                        public String getIdValue(final SearchClause.Comparator object, final int index) {
+                            return getDisplayValue(object).toString();
+                        }
+                    });
+
+                    value.setEnabled(false);
+                    value.setModelObject("");
+
+                    break;
+
+                case RESOURCE:
+                    property.setChoices(resourceNames);
+
+                    comparator.setChoices(new LoadableDetachableModel<List<SearchClause.Comparator>>() {
+
+                        private static final long serialVersionUID = 5275935387613157437L;
+
+                        @Override
+                        protected List<SearchClause.Comparator> load() {
+                            List<SearchClause.Comparator> comparators = new ArrayList<SearchClause.Comparator>();
+                            comparators.add(SearchClause.Comparator.EQUALS);
+                            comparators.add(SearchClause.Comparator.NOT_EQUALS);
+                            return comparators;
+                        }
+                    });
+                    comparator.setChoiceRenderer(new IChoiceRenderer<SearchClause.Comparator>() {
+
+                        private static final long serialVersionUID = -9086043750227867686L;
+
+                        @Override
+                        public Object getDisplayValue(final SearchClause.Comparator object) {
+                            String display;
+
+                            switch (object) {
+                                case EQUALS:
+                                    display = "HAS";
+                                    break;
+
+                                case NOT_EQUALS:
+                                    display = "HAS NOT";
+                                    break;
+
+                                default:
+                                    display = StringUtils.EMPTY;
+                            }
+
+                            return display;
+                        }
+
+                        @Override
+                        public String getIdValue(final SearchClause.Comparator object, final int index) {
+                            return getDisplayValue(object).toString();
+                        }
+                    });
+
+                    value.setEnabled(false);
+                    value.setModelObject("");
+
+                    break;
+
+                case ENTITLEMENT:
+                    property.setChoices(entitlements);
+
+                    comparator.setChoices(new LoadableDetachableModel<List<SearchClause.Comparator>>() {
+
+                        private static final long serialVersionUID = 5275935387613157437L;
+
+                        @Override
+                        protected List<SearchClause.Comparator> load() {
+                            List<SearchClause.Comparator> comparators = new ArrayList<SearchClause.Comparator>();
+                            comparators.add(SearchClause.Comparator.EQUALS);
+                            comparators.add(SearchClause.Comparator.NOT_EQUALS);
+                            return comparators;
+                        }
+                    });
+                    comparator.setChoiceRenderer(new IChoiceRenderer<SearchClause.Comparator>() {
+
+                        private static final long serialVersionUID = -9086043750227867686L;
+
+                        @Override
+                        public Object getDisplayValue(final SearchClause.Comparator object) {
+                            String display;
+
+                            switch (object) {
+                                case EQUALS:
+                                    display = "HAS";
+                                    break;
+
+                                case NOT_EQUALS:
+                                    display = "HAS NOT";
+                                    break;
+
+                                default:
+                                    display = StringUtils.EMPTY;
+                            }
+
+                            return display;
+                        }
+
+                        @Override
+                        public String getIdValue(final SearchClause.Comparator object, final int index) {
+                            return getDisplayValue(object).toString();
+                        }
+                    });
+
+                    value.setEnabled(false);
+                    value.setModelObject("");
+
+                    break;
+
+                default:
+                    property.setChoices(Collections.<String>emptyList());
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionPanel.java
new file mode 100644
index 0000000..8658cf6
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionPanel.java
@@ -0,0 +1,98 @@
+/*
+ * 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.panels;
+
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.TreeMap;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.rest.SecurityQuestionRestClient;
+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.common.lib.to.SecurityQuestionTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+public class SecurityQuestionPanel extends Panel {
+
+    private static final long serialVersionUID = -790642213865180146L;
+
+    private final Map<Long, String> questions = new TreeMap<Long, String>();
+
+    @SpringBean
+    private SecurityQuestionRestClient restClient;
+
+    public SecurityQuestionPanel(final String id, final UserTO userTO) {
+        super(id);
+        setOutputMarkupId(true);
+
+        for (SecurityQuestionTO secQues : restClient.list()) {
+            questions.put(secQues.getKey(), secQues.getContent());
+        }
+
+        final AjaxTextFieldPanel securityAnswer = new AjaxTextFieldPanel("securityAnswer", "securityAnswer",
+                new PropertyModel<String>(userTO, "securityAnswer"));
+        securityAnswer.getField().setOutputMarkupId(true);
+        securityAnswer.setEnabled(false);
+        add(securityAnswer);
+
+        final AjaxDropDownChoicePanel<Long> securityQuestion =
+                new AjaxDropDownChoicePanel<>("securityQuestion", "securityQuestion",
+                        new PropertyModel<Long>(userTO, "securityQuestion"));
+        ((DropDownChoice) securityQuestion.getField()).setNullValid(true);
+        securityQuestion.setChoices(new ArrayList<>(questions.keySet()));
+        securityQuestion.setStyleSheet("ui-widget-content ui-corner-all long_dynamicsize");
+        securityQuestion.getField().setOutputMarkupId(true);
+        securityQuestion.setChoiceRenderer(new IChoiceRenderer<Long>() {
+
+            private static final long serialVersionUID = 2693996850376268294L;
+
+            @Override
+            public Object getDisplayValue(final Long object) {
+                return questions.get(object);
+            }
+
+            @Override
+            public String getIdValue(final Long object, final int index) {
+                return questions.get(object);
+            }
+        });
+        securityQuestion.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                if (securityQuestion.getModelObject() == null) {
+                    securityAnswer.setModelObject(null);
+                } else {
+                    securityAnswer.setEnabled(true);
+                }
+                target.add(SecurityQuestionPanel.this);
+            }
+        });
+        add(securityQuestion);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectOnlyUserSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectOnlyUserSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectOnlyUserSearchResultPanel.java
new file mode 100644
index 0000000..a55db53
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectOnlyUserSearchResultPanel.java
@@ -0,0 +1,93 @@
+/*
+ * 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.panels;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.client.console.pages.DisplayAttributesModalPage;
+import org.apache.syncope.client.console.rest.UserRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+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.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.ResourceModel;
+
+public class SelectOnlyUserSearchResultPanel extends UserSearchResultPanel {
+
+    private static final long serialVersionUID = 2146781496050131930L;
+
+    private final PageReference pageRef;
+
+    private final ModalWindow window;
+
+    public <T extends AbstractAttributableTO> SelectOnlyUserSearchResultPanel(final String id, final boolean filtered,
+            final String fiql, final PageReference pageRef, final ModalWindow window, final UserRestClient restClient) {
+
+        super(id, filtered, fiql, pageRef, restClient);
+
+        this.pageRef = pageRef;
+        this.window = window;
+    }
+
+    @Override
+    protected List<IColumn<AbstractAttributableTO, String>> getColumns() {
+        final List<IColumn<AbstractAttributableTO, String>> columns =
+                new ArrayList<IColumn<AbstractAttributableTO, String>>();
+        for (String name : DisplayAttributesModalPage.DEFAULT_SELECTION) {
+            columns.add(new PropertyColumn<AbstractAttributableTO, String>(new ResourceModel(name, name), name, name));
+        }
+
+        columns.add(new AbstractColumn<AbstractAttributableTO, String>(new ResourceModel("actions", "")) {
+
+            private static final long serialVersionUID = 8263694778917279290L;
+
+            @Override
+            public void populateItem(final Item<ICellPopulator<AbstractAttributableTO>> cellItem,
+                    final String componentId, final IModel<AbstractAttributableTO> rowModel) {
+
+                final ActionLinksPanel panel = new ActionLinksPanel(componentId, rowModel, pageRef);
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        send(pageRef.getPage(), Broadcast.BREADTH,
+                                new RoleDetailsPanel.UserOwnerSelectPayload(rowModel.getObject().getKey()));
+                        window.close(target);
+                    }
+                }, ActionLink.ActionType.SELECT, "Users");
+
+                cellItem.add(panel);
+            }
+        });
+
+        return columns;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectedEventsPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectedEventsPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectedEventsPanel.java
new file mode 100644
index 0000000..96c8d77
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectedEventsPanel.java
@@ -0,0 +1,167 @@
+/*
+ * 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.panels;
+
+import java.util.List;
+import java.util.Set;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.markup.html.form.ListMultipleChoice;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.util.ListModel;
+
+public class SelectedEventsPanel extends Panel {
+
+    private static final long serialVersionUID = -4832450230348213500L;
+
+    private final WebMarkupContainer selectionContainer;
+
+    private ListMultipleChoice<String> selectedEvents;
+
+    private final IModel<List<String>> model;
+
+    public SelectedEventsPanel(final String id, final IModel<List<String>> model) {
+        super(id);
+
+        this.model = model;
+
+        selectionContainer = new WebMarkupContainer("selectionContainer");
+        selectionContainer.setOutputMarkupId(true);
+        add(selectionContainer);
+
+        selectedEvents = new ListMultipleChoice<String>("selectedEvents", new ListModel<String>(), model) {
+
+            private static final long serialVersionUID = 1226677544225737338L;
+
+            @Override
+            protected void onComponentTag(final ComponentTag tag) {
+                super.onComponentTag(tag);
+                tag.remove("size");
+                tag.remove("multiple");
+                tag.put("size", 5);
+            }
+        };
+
+        selectedEvents.setMaxRows(5);
+        selectedEvents.setChoiceRenderer(new IChoiceRenderer<String>() {
+
+            private static final long serialVersionUID = -4288397951948436434L;
+
+            @Override
+            public Object getDisplayValue(final String object) {
+                return object;
+            }
+
+            @Override
+            public String getIdValue(final String object, final int index) {
+                return object;
+            }
+        });
+
+        selectedEvents.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -151291731388673682L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                send(SelectedEventsPanel.this.getPage(),
+                        Broadcast.BREADTH,
+                        new InspectSelectedEvent(target, selectedEvents.getModelValue()));
+            }
+        });
+
+        selectionContainer.add(selectedEvents);
+    }
+
+    @Override
+    public void onEvent(final IEvent<?> event) {
+        if (event.getPayload() instanceof EventSelectionChanged) {
+            final EventSelectionChanged eventSelectionChanged = (EventSelectionChanged) event.getPayload();
+
+            for (String toBeRemoved : eventSelectionChanged.getToBeRemoved()) {
+                model.getObject().remove(toBeRemoved);
+            }
+
+            for (String toBeAdded : eventSelectionChanged.getToBeAdded()) {
+                if (!model.getObject().contains(toBeAdded)) {
+                    model.getObject().add(toBeAdded);
+                }
+            }
+
+            eventSelectionChanged.getTarget().add(selectionContainer);
+        }
+    }
+
+    public static class InspectSelectedEvent {
+
+        private final AjaxRequestTarget target;
+
+        private final String event;
+
+        public InspectSelectedEvent(final AjaxRequestTarget target, final String event) {
+            this.target = target;
+            this.event = event;
+        }
+
+        public AjaxRequestTarget getTarget() {
+            return target;
+        }
+
+        public String getEvent() {
+            return event;
+        }
+    }
+
+    public static class EventSelectionChanged {
+
+        private final AjaxRequestTarget target;
+
+        private final Set<String> toBeRemoved;
+
+        private final Set<String> toBeAdded;
+
+        public EventSelectionChanged(
+                final AjaxRequestTarget target,
+                final Set<String> toBeAdded,
+                final Set<String> toBeRemoved) {
+            this.target = target;
+            this.toBeAdded = toBeAdded;
+            this.toBeRemoved = toBeRemoved;
+        }
+
+        public AjaxRequestTarget getTarget() {
+            return target;
+        }
+
+        public Set<String> getToBeRemoved() {
+            return toBeRemoved;
+        }
+
+        public Set<String> getToBeAdded() {
+            return toBeAdded;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/StatusPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/StatusPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/StatusPanel.java
new file mode 100644
index 0000000..4faea4e
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/StatusPanel.java
@@ -0,0 +1,263 @@
+/*
+ * 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.panels;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+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.pages.ConnObjectModalPage;
+import org.apache.syncope.client.console.rest.RoleRestClient;
+import org.apache.syncope.client.console.rest.UserRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.client.console.wicket.markup.html.list.AltListView;
+import org.apache.syncope.common.lib.mod.StatusMod;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.AbstractSubjectTO;
+import org.apache.syncope.common.lib.to.ConnObjectTO;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.IHeaderContributor;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Check;
+import org.apache.wicket.markup.html.form.CheckGroup;
+import org.apache.wicket.markup.html.form.CheckGroupSelector;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class StatusPanel extends Panel implements IHeaderContributor {
+
+    /**
+     * Logger.
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(StatusPanel.class);
+
+    private static final long serialVersionUID = -4064294905566247728L;
+
+    public static final String IMG_STATUES = "../statuses/";
+
+    private static final int CONNOBJECT_WIN_HEIGHT = 400;
+
+    private static final int CONNOBJECT_WIN_WIDTH = 600;
+
+    @SpringBean
+    private UserRestClient userRestClient;
+
+    @SpringBean
+    private RoleRestClient roleRestClient;
+
+    private final ModalWindow connObjectWin;
+
+    private final List<ConnObjectWrapper> connObjects;
+
+    private final Map<String, StatusBean> initialStatusBeanMap;
+
+    private final CheckGroup<StatusBean> checkGroup;
+
+    private final ListView<StatusBean> statusBeansListView;
+
+    private final StatusUtils statusUtils;
+
+    public <T extends AbstractAttributableTO> StatusPanel(
+            final String id,
+            final AbstractSubjectTO subject,
+            final List<StatusBean> selectedResources,
+            final PageReference pageref) {
+
+        super(id);
+
+        connObjectWin = new ModalWindow("connObjectWin");
+        connObjectWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        connObjectWin.setInitialHeight(CONNOBJECT_WIN_HEIGHT);
+        connObjectWin.setInitialWidth(CONNOBJECT_WIN_WIDTH);
+        connObjectWin.setCookieName("connobject-modal");
+        add(connObjectWin);
+
+        statusUtils = new StatusUtils(subject instanceof RoleTO ? roleRestClient : userRestClient);
+
+        connObjects = statusUtils.getConnectorObjects(subject);
+
+        final List<StatusBean> statusBeans = new ArrayList<>(connObjects.size() + 1);
+        initialStatusBeanMap = new LinkedHashMap<>(connObjects.size() + 1);
+
+        final StatusBean syncope = new StatusBean(subject, "syncope");
+
+        if (subject instanceof UserTO) {
+            syncope.setAccountLink(((UserTO) subject).getUsername());
+
+            Status syncopeStatus = Status.UNDEFINED;
+            if (((UserTO) subject).getStatus() != null) {
+                try {
+                    syncopeStatus = Status.valueOf(((UserTO) subject).getStatus().toUpperCase());
+                } catch (IllegalArgumentException e) {
+                    LOG.warn("Unexpected status found: {}", ((UserTO) subject).getStatus(), e);
+                }
+            }
+            syncope.setStatus(syncopeStatus);
+        } else if (subject instanceof RoleTO) {
+            syncope.setAccountLink(((RoleTO) subject).getDisplayName());
+            syncope.setStatus(Status.ACTIVE);
+        }
+
+        statusBeans.add(syncope);
+        initialStatusBeanMap.put(syncope.getResourceName(), syncope);
+
+        for (ConnObjectWrapper entry : connObjects) {
+            final StatusBean statusBean = statusUtils.getStatusBean(
+                    entry.getAttributable(),
+                    entry.getResourceName(),
+                    entry.getConnObjectTO(),
+                    subject instanceof RoleTO);
+
+            initialStatusBeanMap.put(entry.getResourceName(), statusBean);
+            statusBeans.add(statusBean);
+        }
+
+        checkGroup = new CheckGroup<>("group", selectedResources);
+        checkGroup.setOutputMarkupId(true);
+        checkGroup.add(new AjaxFormChoiceComponentUpdatingBehavior() {
+
+            private static final long serialVersionUID = -151291731388673682L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                // ignore
+            }
+        });
+        add(checkGroup);
+
+        CheckGroupSelector groupSelector = new CheckGroupSelector("groupselector", checkGroup);
+        if (subject instanceof RoleTO) {
+            groupSelector.setVisible(false);
+        }
+        add(groupSelector);
+
+        statusBeansListView = new AltListView<StatusBean>("resources", statusBeans) {
+
+            private static final long serialVersionUID = 4949588177564901031L;
+
+            @Override
+            protected void populateItem(final ListItem<StatusBean> item) {
+                item.add(statusUtils.getStatusImage("icon", item.getModelObject().getStatus()));
+
+                final Check<StatusBean> check = new Check<StatusBean>("check", item.getModel(), checkGroup);
+                if (subject instanceof RoleTO) {
+                    check.setVisible(false);
+                }
+                item.add(check);
+
+                item.add(new Label("resource", new ResourceModel(item.getModelObject().getResourceName(), item
+                        .getModelObject().getResourceName())));
+
+                if (StringUtils.isNotBlank(item.getModelObject().getAccountLink())) {
+                    item.add(new Label("accountLink", new ResourceModel(item.getModelObject().getAccountLink(),
+                            item.getModelObject().getAccountLink())));
+                } else {
+                    item.add(new Label("accountLink", ""));
+                }
+
+                final ConnObjectTO connObjectTO = statusUtils.getConnObjectTO(
+                        item.getModelObject().getAttributableId(),
+                        item.getModelObject().getResourceName(),
+                        connObjects);
+
+                if (pageref == null || connObjectTO == null) {
+                    item.add(new Label("connObject", new Model<String>()));
+                } else {
+                    final ActionLinksPanel connObject = new ActionLinksPanel("connObject", new Model(), pageref);
+
+                    connObject.add(new ActionLink() {
+
+                        private static final long serialVersionUID = -3722207913631435501L;
+
+                        @Override
+                        public void onClick(final AjaxRequestTarget target) {
+                            connObjectWin.setPageCreator(new ModalWindow.PageCreator() {
+
+                                private static final long serialVersionUID = -7834632442532690940L;
+
+                                @Override
+                                public Page createPage() {
+                                    return new ConnObjectModalPage(connObjectTO);
+                                }
+                            });
+
+                            connObjectWin.show(target);
+                        }
+                    }, ActionLink.ActionType.SEARCH, "Resources", "getConnectorObject");
+
+                    item.add(connObject);
+                }
+            }
+        };
+        statusBeansListView.setReuseItems(true);
+        checkGroup.add(statusBeansListView);
+    }
+
+    public StatusMod getStatusMod() {
+        StatusMod result = new StatusMod();
+
+        Collection<StatusBean> statusBeans = checkGroup.getModel().getObject();
+        if (statusBeans != null && !statusBeans.isEmpty()) {
+            result = StatusUtils.buildStatusMod(statusBeans);
+        }
+
+        return result;
+    }
+
+    public List<StatusBean> getStatusBeans() {
+        return statusBeansListView.getModelObject();
+    }
+
+    public Map<String, StatusBean> getInitialStatusBeanMap() {
+        return initialStatusBeanMap;
+    }
+
+    public void updateStatusBeans(final List<StatusBean> statusBeans) {
+        statusBeansListView.removeAll();
+        statusBeansListView.getModelObject().clear();
+        statusBeansListView.getModelObject().addAll(statusBeans);
+
+        for (StatusBean statusBean : statusBeans) {
+            if (!checkGroup.getModelObject().contains(statusBean)
+                    && statusBean.getStatus() == Status.NOT_YET_SUBMITTED) {
+
+                checkGroup.getModelObject().add(statusBean);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/SyncTasksPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/SyncTasksPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/SyncTasksPanel.java
new file mode 100644
index 0000000..f520391
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/SyncTasksPanel.java
@@ -0,0 +1,226 @@
+/*
+ * 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.panels;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.pages.RoleTemplateModalPage;
+import org.apache.syncope.client.console.pages.SyncTaskModalPage;
+import org.apache.syncope.client.console.pages.UserTemplateModalPage;
+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.DatePropertyColumn;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.SyncTaskTO;
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+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.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.StringResourceModel;
+
+public class SyncTasksPanel extends AbstractProvisioningTasksPanel<SyncTaskTO> {
+
+    private static final long serialVersionUID = 53189199346016099L;
+
+    public SyncTasksPanel(final String id, final PageReference pageRef) {
+        super(id, pageRef, SyncTaskTO.class);
+        initTasksTable();
+    }
+
+    @Override
+    protected List<IColumn<AbstractTaskTO, String>> getColumns() {
+        final List<IColumn<AbstractTaskTO, String>> syncTaskscolumns = new ArrayList<>();
+
+        syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("key", this, null), "key", "key"));
+        syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("name", this, null), "name", "name"));
+        syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("description", this, null), "description", "description"));
+        syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("resourceName", this, null), "resource", "resource"));
+        syncTaskscolumns.add(new DatePropertyColumn<AbstractTaskTO>(
+                new StringResourceModel("lastExec", this, null), "lastExec", "lastExec"));
+        syncTaskscolumns.add(new DatePropertyColumn<AbstractTaskTO>(
+                new StringResourceModel("nextExec", this, null), "nextExec", "nextExec"));
+        syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
+
+        syncTaskscolumns.add(
+                new ActionColumn<AbstractTaskTO, String>(new StringResourceModel("actions", this, null, "")) {
+
+                    private static final long serialVersionUID = 2054811145491901166L;
+
+                    @Override
+                    public ActionLinksPanel getActions(final String componentId, final IModel<AbstractTaskTO> model) {
+
+                        final SyncTaskTO taskTO = (SyncTaskTO) model.getObject();
+
+                        final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, pageRef);
+
+                        panel.add(new ActionLink() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target) {
+
+                                window.setPageCreator(new ModalWindow.PageCreator() {
+
+                                    private static final long serialVersionUID = -7834632442532690940L;
+
+                                    @Override
+                                    public Page createPage() {
+                                        return new SyncTaskModalPage(window, taskTO, pageRef);
+                                    }
+                                });
+
+                                window.show(target);
+                            }
+                        }, ActionLink.ActionType.EDIT, TASKS);
+
+                        panel.add(new ActionLink() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target) {
+
+                                window.setPageCreator(new ModalWindow.PageCreator() {
+
+                                    private static final long serialVersionUID = -7834632442532690940L;
+
+                                    @Override
+                                    public Page createPage() {
+                                        return new UserTemplateModalPage(pageRef, window, taskTO);
+                                    }
+                                });
+
+                                window.show(target);
+                            }
+                        }, ActionLink.ActionType.USER_TEMPLATE, TASKS);
+
+                        panel.add(new ActionLink() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target) {
+
+                                window.setPageCreator(new ModalWindow.PageCreator() {
+
+                                    private static final long serialVersionUID = -7834632442532690940L;
+
+                                    @Override
+                                    public Page createPage() {
+                                        return new RoleTemplateModalPage(pageRef, window, taskTO);
+                                    }
+                                });
+
+                                window.show(target);
+                            }
+                        }, ActionLink.ActionType.ROLE_TEMPLATE, TASKS);
+
+                        panel.add(new ActionLink() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target) {
+                                try {
+                                    restClient.startExecution(taskTO.getKey(), false);
+                                    getSession().info(getString(Constants.OPERATION_SUCCEEDED));
+                                } catch (SyncopeClientException scce) {
+                                    error(scce.getMessage());
+                                }
+
+                                target.add(container);
+                                ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
+                            }
+                        }, ActionLink.ActionType.EXECUTE, TASKS);
+
+                        panel.add(new ActionLink() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target) {
+                                try {
+                                    restClient.startExecution(taskTO.getKey(), true);
+                                    getSession().info(getString(Constants.OPERATION_SUCCEEDED));
+                                } catch (SyncopeClientException scce) {
+                                    error(scce.getMessage());
+                                }
+
+                                target.add(container);
+                                ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
+                            }
+                        }, ActionLink.ActionType.DRYRUN, TASKS);
+
+                        panel.add(new ActionLink() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target) {
+                                try {
+                                    restClient.delete(taskTO.getKey(), SyncTaskTO.class);
+                                    info(getString(Constants.OPERATION_SUCCEEDED));
+                                } catch (SyncopeClientException scce) {
+                                    error(scce.getMessage());
+                                }
+                                target.add(container);
+                                ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
+                            }
+                        }, ActionLink.ActionType.DELETE, TASKS);
+
+                        return panel;
+                    }
+
+                    @Override
+                    public Component getHeader(final String componentId) {
+                        final ActionLinksPanel panel = new ActionLinksPanel(componentId, new Model(), pageRef);
+
+                        panel.add(new ActionLink() {
+
+                            private static final long serialVersionUID = -7978723352517770644L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target) {
+                                if (target != null) {
+                                    target.add(table);
+                                }
+                            }
+                        }, ActionLink.ActionType.RELOAD, TASKS, "list");
+
+                        return panel;
+                    }
+                });
+
+        return syncTaskscolumns;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDetailsPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDetailsPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDetailsPanel.java
new file mode 100644
index 0000000..18e2066
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDetailsPanel.java
@@ -0,0 +1,122 @@
+/*
+ * 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.panels;
+
+import org.apache.syncope.client.console.commons.JexlHelpUtil;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPasswordFieldPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.behavior.Behavior;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.PasswordTextField;
+import org.apache.wicket.markup.html.form.validation.EqualPasswordInputValidator;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
+
+public class UserDetailsPanel extends Panel {
+
+    private static final long serialVersionUID = 6592027822510220463L;
+
+    public UserDetailsPanel(final String id, final UserTO userTO, final Form form, final boolean resetPassword,
+            final boolean templateMode) {
+
+        super(id);
+
+        // ------------------------
+        // Username
+        // ------------------------
+        final FieldPanel<String> username = new AjaxTextFieldPanel("username", "username",
+                new PropertyModel<String>(userTO, "username"));
+
+        final WebMarkupContainer jexlHelp = JexlHelpUtil.getJexlHelpWebContainer("usernameJexlHelp");
+
+        final AjaxLink<?> questionMarkJexlHelp = JexlHelpUtil.getAjaxLink(jexlHelp, "usernameQuestionMarkJexlHelp");
+        add(questionMarkJexlHelp);
+        questionMarkJexlHelp.add(jexlHelp);
+
+        if (!templateMode) {
+            username.addRequiredLabel();
+            questionMarkJexlHelp.setVisible(false);
+        }
+        add(username);
+        // ------------------------
+
+        // ------------------------
+        // Password
+        // ------------------------
+        final WebMarkupContainer pwdJexlHelp = JexlHelpUtil.getJexlHelpWebContainer("pwdJexlHelp");
+
+        final AjaxLink<?> pwdQuestionMarkJexlHelp = JexlHelpUtil.getAjaxLink(pwdJexlHelp, "pwdQuestionMarkJexlHelp");
+        add(pwdQuestionMarkJexlHelp);
+        pwdQuestionMarkJexlHelp.add(pwdJexlHelp);
+
+        FieldPanel<String> password;
+        Label confirmPasswordLabel = new Label("confirmPasswordLabel", new ResourceModel("confirmPassword"));
+        FieldPanel<String> confirmPassword;
+        if (templateMode) {
+            password = new AjaxTextFieldPanel("password", "password", new PropertyModel<String>(userTO, "password"));
+
+            confirmPasswordLabel.setVisible(false);
+            confirmPassword = new AjaxTextFieldPanel("confirmPassword", "confirmPassword", new Model<String>());
+            confirmPassword.setEnabled(false);
+            confirmPassword.setVisible(false);
+        } else {
+            pwdQuestionMarkJexlHelp.setVisible(false);
+
+            password = new AjaxPasswordFieldPanel("password", "password",
+                    new PropertyModel<String>(userTO, "password"));
+            ((PasswordTextField) password.getField()).setResetPassword(resetPassword);
+
+            confirmPassword = new AjaxPasswordFieldPanel("confirmPassword", "confirmPassword", new Model<String>());
+            if (!resetPassword) {
+                confirmPassword.getField().setModelObject(userTO.getPassword());
+            }
+            ((PasswordTextField) confirmPassword.getField()).setResetPassword(resetPassword);
+
+            form.add(new EqualPasswordInputValidator(password.getField(), confirmPassword.getField()));
+        }
+        add(password);
+        add(confirmPasswordLabel);
+        add(confirmPassword);
+
+        final WebMarkupContainer mandatoryPassword = new WebMarkupContainer("mandatory_pwd");
+        mandatoryPassword.add(new Behavior() {
+
+            private static final long serialVersionUID = 1469628524240283489L;
+
+            @Override
+            public void onComponentTag(final Component component, final ComponentTag tag) {
+                if (userTO.getKey() > 0) {
+                    tag.put("style", "display:none;");
+                }
+            }
+        });
+
+        add(mandatoryPassword);
+        // ------------------------
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/UserSearchPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/UserSearchPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/UserSearchPanel.java
new file mode 100644
index 0000000..2ca1b94
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/UserSearchPanel.java
@@ -0,0 +1,113 @@
+/*
+ * 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.panels;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.client.console.rest.RoleRestClient;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.search.SyncopeFiqlSearchConditionBuilder;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+public class UserSearchPanel extends AbstractSearchPanel {
+
+    private static final long serialVersionUID = -1769527800450203738L;
+
+    @SpringBean
+    private RoleRestClient roleRestClient;
+
+    public static class Builder implements Serializable {
+
+        private static final long serialVersionUID = 6308997285778809578L;
+
+        private String id;
+
+        private String fiql = null;
+
+        private boolean required = true;
+
+        public Builder(final String id) {
+            this.id = id;
+        }
+
+        public Builder fiql(final String fiql) {
+            this.fiql = fiql;
+            return this;
+        }
+
+        public Builder required(final boolean required) {
+            this.required = required;
+            return this;
+        }
+
+        public UserSearchPanel build() {
+            return new UserSearchPanel(this);
+        }
+    }
+
+    private UserSearchPanel(final Builder builder) {
+        super(builder.id, AttributableType.USER, builder.fiql, builder.required);
+    }
+
+    @Override
+    protected void populate() {
+        super.populate();
+
+        this.types = new LoadableDetachableModel<List<SearchClause.Type>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected List<SearchClause.Type> load() {
+                List<SearchClause.Type> result = new ArrayList<SearchClause.Type>();
+                result.add(SearchClause.Type.ATTRIBUTE);
+                result.add(SearchClause.Type.MEMBERSHIP);
+                result.add(SearchClause.Type.RESOURCE);
+                return result;
+            }
+        };
+
+        this.roleNames = new LoadableDetachableModel<List<String>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected List<String> load() {
+                List<RoleTO> roleTOs = roleRestClient.list();
+
+                List<String> result = new ArrayList<String>(roleTOs.size());
+                for (RoleTO role : roleTOs) {
+                    result.add(role.getDisplayName());
+                }
+
+                return result;
+            }
+        };
+    }
+
+    @Override
+    protected SyncopeFiqlSearchConditionBuilder getSearchConditionBuilder() {
+        return SyncopeClient.getUserSearchConditionBuilder();
+    }
+
+}