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 2022/05/16 07:33:04 UTC

[syncope] branch 2_1_X updated: Improve Realms page extendability

This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch 2_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/2_1_X by this push:
     new 1babf7369f Improve Realms page extendability
1babf7369f is described below

commit 1babf7369f81627d424b75590e0cee93548587be
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Mon May 16 09:32:51 2022 +0200

    Improve Realms page extendability
---
 .../syncope/client/console/pages/Realms.java       | 200 ++++++++++-----------
 .../syncope/client/console/panels/Realm.java       | 196 +++++++++++---------
 .../client/console/panels/RealmChoicePanel.java    | 102 +++++------
 .../client/console/panels/RealmDetails.java        |  10 +-
 .../client/console/panels/RealmWizardBuilder.java  |   5 +-
 5 files changed, 257 insertions(+), 256 deletions(-)

diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
index 99914a5364..ff3caf32f8 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
@@ -20,6 +20,7 @@ package org.apache.syncope.client.console.pages;
 
 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
 import java.io.Serializable;
+import java.util.List;
 import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
@@ -27,19 +28,20 @@ import org.apache.syncope.client.console.panels.Realm;
 import org.apache.syncope.client.console.panels.RealmChoicePanel;
 import org.apache.syncope.client.console.panels.RealmChoicePanel.ChosenRealm;
 import org.apache.syncope.client.console.panels.WizardModalPanel;
+import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.rest.RealmRestClient;
 import org.apache.syncope.client.console.tasks.TemplatesTogglePanel;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.any.ResultPage;
 import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.to.TemplatableTO;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.event.IEvent;
-import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow.WindowClosedCallback;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.model.CompoundPropertyModel;
@@ -51,17 +53,19 @@ public class Realms extends BasePage {
 
     private static final long serialVersionUID = -1100228004207271270L;
 
-    private final RealmRestClient realmRestClient = new RealmRestClient();
+    protected final RealmRestClient realmRestClient = new RealmRestClient();
 
-    private final TemplatesTogglePanel templates;
+    protected final AnyTypeRestClient anyTypeRestClient = new AnyTypeRestClient();
 
-    private final RealmChoicePanel realmChoicePanel;
+    protected final TemplatesTogglePanel templates;
 
-    private final WebMarkupContainer content;
+    protected final RealmChoicePanel realmChoicePanel;
 
-    private final BaseModal<RealmTO> modal;
+    protected final WebMarkupContainer content;
 
-    private final BaseModal<Serializable> templateModal;
+    protected final BaseModal<RealmTO> modal;
+
+    protected final BaseModal<Serializable> templateModal;
 
     public Realms(final PageParameters parameters) {
         super(parameters);
@@ -111,35 +115,18 @@ public class Realms extends BasePage {
         templateModal.size(Modal.Size.Large);
         content.add(templateModal);
 
-        modal.setWindowClosedCallback(new WindowClosedCallback() {
-
-            private static final long serialVersionUID = 8804221891699487139L;
-
-            @Override
-            public void onClose(final AjaxRequestTarget target) {
-                target.add(realmChoicePanel.reloadRealmTree(target));
-                target.add(content);
-                modal.show(false);
-            }
+        modal.setWindowClosedCallback(target -> {
+            target.add(realmChoicePanel.reloadRealmTree(target));
+            target.add(content);
+            modal.show(false);
         });
 
-        templateModal.setWindowClosedCallback(new WindowClosedCallback() {
-
-            private static final long serialVersionUID = 8804221891699487139L;
-
-            @Override
-            public void onClose(final AjaxRequestTarget target) {
-                target.add(content);
-                templateModal.show(false);
-            }
+        templateModal.setWindowClosedCallback(target -> {
+            target.add(content);
+            templateModal.show(false);
         });
 
-        try {
-            updateRealmContent(realmChoicePanel.getCurrentRealm(), parameters.get("selectedIndex").toInteger());
-        } catch (Exception e) {
-            LOG.debug("Unexpected error", e);
-            updateRealmContent(realmChoicePanel.getCurrentRealm(), 0);
-        }
+        updateRealmContent(realmChoicePanel.getCurrentRealm(), parameters.get("selectedIndex").toInt(0));
     }
 
     @Override
@@ -175,88 +162,93 @@ public class Realms extends BasePage {
         }
     }
 
-    private WebMarkupContainer updateRealmContent(final RealmTO realmTO, final int selectedIndex) {
-        if (realmTO == null) {
-            return content;
+    protected WebMarkupContainer updateRealmContent(final RealmTO realmTO, final int selectedIndex) {
+        if (realmTO != null) {
+            content.addOrReplace(new Content(realmTO, anyTypeRestClient.listAnyTypes(), selectedIndex));
         }
-        content.addOrReplace(new Realm("body", realmTO, Realms.this.getPageReference(), selectedIndex) {
+        return content;
+    }
 
-            private static final long serialVersionUID = 8221398624379357183L;
+    public RealmChoicePanel getRealmChoicePanel() {
+        return realmChoicePanel;
+    }
 
-            @Override
-            protected void onClickTemplate(final AjaxRequestTarget target) {
-                templates.setTargetObject(realmTO);
-                templates.toggle(target, true);
-            }
+    protected class Content extends Realm {
 
-            @Override
-            protected void setWindowClosedReloadCallback(final BaseModal<?> modal) {
-                modal.setWindowClosedCallback(target -> {
-                    if (modal.getContent() instanceof ResultPage) {
-                        Serializable result = ResultPage.class.cast(modal.getContent()).getResult();
-
-                        RealmTO newRealmTO = RealmTO.class.cast(ProvisioningResult.class.cast(result).getEntity());
-                        // reload realmChoicePanel label too - SYNCOPE-1151
-                        target.add(realmChoicePanel.reloadRealmTree(target, Model.of(newRealmTO)));
-                        realmChoicePanel.setCurrentRealm(newRealmTO);
-                        send(Realms.this, Broadcast.DEPTH, new ChosenRealm<>(newRealmTO, target));
-                    } else {
-                        target.add(realmChoicePanel.reloadRealmTree(target));
-                    }
-                    target.add(content);
-                    modal.show(false);
-                });
-            }
+        private static final long serialVersionUID = 8221398624379357183L;
 
-            @Override
-            protected void onClickCreate(final AjaxRequestTarget target) {
-                this.wizardBuilder.setParentPath(realmChoicePanel.getCurrentRealm().getFullPath());
-                send(this, Broadcast.EXACT, new AjaxWizard.NewItemActionEvent<RealmTO>(new RealmTO(), target) {
-
-                    @Override
-                    public String getEventDescription() {
-                        return "realm.new";
-                    }
-                });
-            }
+        protected Content(final RealmTO realmTO, final List<AnyTypeTO> anyTypes, final int selectedIndex) {
+            super("body", realmTO, anyTypes, selectedIndex, Realms.this.getPageReference());
+        }
 
-            @Override
-            protected void onClickEdit(final AjaxRequestTarget target, final RealmTO realmTO) {
-                this.wizardBuilder.setParentPath(realmTO.getFullPath());
-                send(this, Broadcast.EXACT, new AjaxWizard.EditItemActionEvent<RealmTO>(realmTO, target) {
-
-                    @Override
-                    public String getEventDescription() {
-                        return "realm.edit";
-                    }
-                });
-            }
+        @Override
+        protected void onClickTemplate(final AjaxRequestTarget target) {
+            templates.setTargetObject(realmTO);
+            templates.toggle(target, true);
+        }
 
-            @Override
-            protected void onClickDelete(final AjaxRequestTarget target, final RealmTO realmTO) {
-                try {
-                    if (realmTO.getKey() == null) {
-                        throw new Exception("Root realm cannot be deleted");
-                    }
-                    realmRestClient.delete(realmTO.getFullPath());
-                    RealmTO parent = realmChoicePanel.moveToParentRealm(realmTO.getKey());
+        @Override
+        protected void setWindowClosedReloadCallback(final BaseModal<?> modal) {
+            modal.setWindowClosedCallback(target -> {
+                if (modal.getContent() instanceof ResultPage) {
+                    Serializable result = ResultPage.class.cast(modal.getContent()).getResult();
+
+                    RealmTO newRealmTO = RealmTO.class.cast(ProvisioningResult.class.cast(result).getEntity());
+                    // reload realmChoicePanel label too - SYNCOPE-1151
+                    target.add(realmChoicePanel.reloadRealmTree(target, Model.of(newRealmTO)));
+                    realmChoicePanel.setCurrentRealm(newRealmTO);
+                    send(Realms.this, Broadcast.DEPTH, new ChosenRealm<>(newRealmTO, target));
+                } else {
                     target.add(realmChoicePanel.reloadRealmTree(target));
+                }
+                target.add(content);
+                modal.show(false);
+            });
+        }
 
-                    SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
-                    updateRealmContent(parent, selectedIndex);
-                    target.add(content);
-                } catch (Exception e) {
-                    LOG.error("While deleting realm", e);
-                    // Escape line breaks
-                    SyncopeConsoleSession.get().error(e.getMessage().replace("\n", " "));
+        @Override
+        protected void onClickCreate(final AjaxRequestTarget target) {
+            this.wizardBuilder.setParentPath(realmChoicePanel.getCurrentRealm().getFullPath());
+            send(this, Broadcast.EXACT, new AjaxWizard.NewItemActionEvent<RealmTO>(new RealmTO(), target) {
+
+                @Override
+                public String getEventDescription() {
+                    return "realm.new";
                 }
-                ((BasePage) Realms.this.getPage()).getNotificationPanel().refresh(target);
-            }
-        });
-        return content;
-    }
+            });
+        }
 
-    public RealmChoicePanel getRealmChoicePanel() {
-        return realmChoicePanel;
+        @Override
+        protected void onClickEdit(final AjaxRequestTarget target, final RealmTO realmTO) {
+            this.wizardBuilder.setParentPath(realmTO.getFullPath());
+            send(this, Broadcast.EXACT, new AjaxWizard.EditItemActionEvent<RealmTO>(realmTO, target) {
+
+                @Override
+                public String getEventDescription() {
+                    return "realm.edit";
+                }
+            });
+        }
+
+        @Override
+        protected void onClickDelete(final AjaxRequestTarget target, final RealmTO realmTO) {
+            try {
+                if (realmTO.getKey() == null) {
+                    throw new Exception("Root realm cannot be deleted");
+                }
+                realmRestClient.delete(realmTO.getFullPath());
+                RealmTO parent = realmChoicePanel.moveToParentRealm(realmTO.getKey());
+                target.add(realmChoicePanel.reloadRealmTree(target));
+
+                SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
+                updateRealmContent(parent, selectedIndex);
+                target.add(content);
+            } catch (Exception e) {
+                LOG.error("While deleting realm", e);
+                // Escape line breaks
+                SyncopeConsoleSession.get().error(e.getMessage().replace("\n", " "));
+            }
+            ((BasePage) Realms.this.getPage()).getNotificationPanel().refresh(target);
+        }
     }
 }
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
index 74231b561a..587d94caf2 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
@@ -33,7 +33,6 @@ import org.apache.syncope.client.console.commons.ITabComponent;
 import org.apache.syncope.client.console.commons.status.StatusUtils;
 import org.apache.syncope.client.console.layout.AnyLayout;
 import org.apache.syncope.client.console.layout.AnyLayoutUtils;
-import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
@@ -41,7 +40,6 @@ import org.apache.syncope.client.console.wizards.any.ConnObjectPanel;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
-import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.RealmTO;
@@ -66,24 +64,32 @@ public abstract class Realm extends WizardMgtPanel<RealmTO> {
 
     protected static final Logger LOG = LoggerFactory.getLogger(Realm.class);
 
-    private final RealmTO realmTO;
+    protected final RealmTO realmTO;
 
-    private final List<AnyTypeTO> anyTypes;
+    protected final List<AnyTypeTO> anyTypes;
+
+    protected final int selectedIndex;
 
     protected final RealmWizardBuilder wizardBuilder;
 
-    public Realm(final String id, final RealmTO realmTO, final PageReference pageRef, final int selectedIndex) {
+    public Realm(
+            final String id,
+            final RealmTO realmTO,
+            final List<AnyTypeTO> anyTypes,
+            final int selectedIndex,
+            final PageReference pageRef) {
+
         super(id, true);
         this.realmTO = realmTO;
-        this.anyTypes = new AnyTypeRestClient().listAnyTypes();
+        this.anyTypes = anyTypes;
+        this.selectedIndex = selectedIndex;
 
         setPageRef(pageRef);
 
-        AjaxBootstrapTabbedPanel<ITab> tabbedPanel =
-                new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList(pageRef));
-        tabbedPanel.setSelectedTab(selectedIndex);
-        addInnerObject(tabbedPanel);
-        this.wizardBuilder = new RealmWizardBuilder(pageRef);
+        addInnerObject(new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList(pageRef)).
+                setSelectedTab(selectedIndex));
+
+        this.wizardBuilder = buildNewItemPanelBuilder(pageRef);
         addNewItemPanelBuilder(this.wizardBuilder, false);
 
         setShowResultPage(true);
@@ -92,81 +98,25 @@ public abstract class Realm extends WizardMgtPanel<RealmTO> {
         setWindowClosedReloadCallback(modal);
     }
 
+    protected RealmWizardBuilder buildNewItemPanelBuilder(final PageReference pageRef) {
+        return new RealmWizardBuilder(pageRef);
+    }
+
     public RealmTO getRealmTO() {
         return realmTO;
     }
 
-    private List<ITab> buildTabList(final PageReference pageRef) {
+    protected List<ITab> buildTabList(final PageReference pageRef) {
         List<ITab> tabs = new ArrayList<>();
 
-        tabs.add(new ITabComponent(new Model<>("DETAILS"),
-                StandardEntitlement.REALM_CREATE, StandardEntitlement.REALM_UPDATE, StandardEntitlement.REALM_DELETE) {
-
-            private static final long serialVersionUID = -5861786415855103549L;
-
-            @Override
-            public Panel getPanel(final String panelId) {
-                final ActionsPanel<RealmTO> actionPanel = new ActionsPanel<>("actions", null);
-
-                if (StringUtils.startsWith(realmTO.getFullPath(), SyncopeConstants.ROOT_REALM)) {
-                    actionPanel.add(new ActionLink<RealmTO>(realmTO) {
-
-                        private static final long serialVersionUID = 2802988981431379827L;
-
-                        @Override
-                        public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
-                            onClickCreate(target);
-                        }
-                    }, ActionLink.ActionType.CREATE, StandardEntitlement.REALM_CREATE).hideLabel();
-
-                    actionPanel.add(new ActionLink<RealmTO>(realmTO) {
-
-                        private static final long serialVersionUID = 2802988981431379828L;
-
-                        @Override
-                        public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
-                            onClickEdit(target, realmTO);
-                        }
-                    }, ActionLink.ActionType.EDIT, StandardEntitlement.REALM_UPDATE).hideLabel();
-
-                    actionPanel.add(new ActionLink<RealmTO>(realmTO) {
-
-                        private static final long serialVersionUID = 2802988981431379827L;
-
-                        @Override
-                        public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
-                            onClickTemplate(target);
-                        }
-                    }, ActionLink.ActionType.TEMPLATE, StandardEntitlement.REALM_UPDATE).hideLabel();
-
-                    actionPanel.add(new ActionLink<RealmTO>(realmTO) {
-
-                        private static final long serialVersionUID = 2802988981431379829L;
-
-                        @Override
-                        public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
-                            onClickDelete(target, realmTO);
-                        }
-                    }, ActionLink.ActionType.DELETE, StandardEntitlement.REALM_DELETE, true).hideLabel();
-                }
-
-                RealmDetails panel = new RealmDetails(panelId, realmTO, actionPanel, false);
-                panel.setContentEnabled(false);
-                actionPanel.setEnabled(true);
-                return panel;
-            }
-
-            @Override
-            public boolean isVisible() {
-                return SyncopeConsoleApplication.get().getSecuritySettings().getAuthorizationStrategy().
-                        isActionAuthorized(this, RENDER);
-            }
-        });
+        tabs.add(new RealmDetailsTabPanel());
 
         AnyLayout anyLayout = AnyLayoutUtils.fetch(
-                anyTypes.stream().map(EntityTO::getKey).collect(Collectors.toList()));
+                anyTypes.stream().map(AnyTypeTO::getKey).collect(Collectors.toList()));
         for (AnyTypeTO anyType : anyTypes) {
-            tabs.add(new ITabComponent(new Model<>(anyType.getKey()), String.format("%s_SEARCH", anyType.getKey())) {
+            tabs.add(new ITabComponent(
+                    new ResourceModel("anyType." + anyType.getKey(), anyType.getKey()),
+                    String.format("%s_SEARCH", anyType.getKey())) {
 
                 private static final long serialVersionUID = 1169585538404171118L;
 
@@ -194,10 +144,10 @@ public abstract class Realm extends WizardMgtPanel<RealmTO> {
             throw new IllegalStateException("Unsupported result type");
         }
 
-        final MultilevelPanel mlp = new MultilevelPanel(panelId);
+        MultilevelPanel mlp = new MultilevelPanel(panelId);
         add(mlp);
 
-        final PropagationStatus syncope = new PropagationStatus();
+        PropagationStatus syncope = new PropagationStatus();
         syncope.setStatus(ExecStatus.SUCCESS);
         syncope.setResource(Constants.SYNCOPE);
 
@@ -205,8 +155,8 @@ public abstract class Realm extends WizardMgtPanel<RealmTO> {
         propagations.add(syncope);
         propagations.addAll(((ProvisioningResult) result).getPropagationStatuses());
 
-        ListViewPanel.Builder<PropagationStatus> builder = new ListViewPanel.Builder<PropagationStatus>(
-                PropagationStatus.class, pageRef) {
+        ListViewPanel.Builder<PropagationStatus> builder =
+                new ListViewPanel.Builder<PropagationStatus>(PropagationStatus.class, pageRef) {
 
             private static final long serialVersionUID = -6809736686861678498L;
 
@@ -223,11 +173,13 @@ public abstract class Realm extends WizardMgtPanel<RealmTO> {
                             : afterObj.getAttr(ConnIdSpecialName.NAME).get().getValues().get(0);
 
                     return new Label("field", remoteId);
-                } else if ("status".equalsIgnoreCase(key)) {
+                }
+
+                if ("status".equalsIgnoreCase(key)) {
                     return StatusUtils.getStatusImagePanel("field", bean.getStatus());
-                } else {
-                    return super.getValueComponent(key, bean);
                 }
+
+                return super.getValueComponent(key, bean);
             }
         };
 
@@ -281,13 +233,13 @@ public abstract class Realm extends WizardMgtPanel<RealmTO> {
 
     protected abstract void onClickDelete(AjaxRequestTarget target, RealmTO realmTO);
 
-    class RemoteRealmPanel extends RemoteObjectPanel {
+    protected static class RemoteRealmPanel extends RemoteObjectPanel {
 
         private static final long serialVersionUID = 4303365227411467563L;
 
-        private final PropagationStatus bean;
+        protected final PropagationStatus bean;
 
-        RemoteRealmPanel(final PropagationStatus bean) {
+        protected RemoteRealmPanel(final PropagationStatus bean) {
             this.bean = bean;
             add(new ConnObjectPanel(
                     REMOTE_OBJECT_PANEL_ID,
@@ -301,4 +253,74 @@ public abstract class Realm extends WizardMgtPanel<RealmTO> {
             return Pair.of(bean.getBeforeObj(), bean.getAfterObj());
         }
     }
+
+    protected class RealmDetailsTabPanel extends ITabComponent {
+
+        private static final long serialVersionUID = -5861786415855103549L;
+
+        protected RealmDetailsTabPanel() {
+            super(new Model<>("DETAILS"),
+                    StandardEntitlement.REALM_CREATE,
+                    StandardEntitlement.REALM_UPDATE,
+                    StandardEntitlement.REALM_DELETE);
+        }
+
+        @Override
+        public Panel getPanel(final String panelId) {
+            ActionsPanel<RealmTO> actionPanel = new ActionsPanel<>("actions", null);
+
+            if (StringUtils.startsWith(realmTO.getFullPath(), SyncopeConstants.ROOT_REALM)) {
+                actionPanel.add(new ActionLink<RealmTO>(realmTO) {
+
+                    private static final long serialVersionUID = 2802988981431379827L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
+                        onClickCreate(target);
+                    }
+                }, ActionLink.ActionType.CREATE, StandardEntitlement.REALM_CREATE).hideLabel();
+
+                actionPanel.add(new ActionLink<RealmTO>(realmTO) {
+
+                    private static final long serialVersionUID = 2802988981431379828L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
+                        onClickEdit(target, realmTO);
+                    }
+                }, ActionLink.ActionType.EDIT, StandardEntitlement.REALM_UPDATE).hideLabel();
+
+                actionPanel.add(new ActionLink<RealmTO>(realmTO) {
+
+                    private static final long serialVersionUID = 2802988981431379827L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
+                        onClickTemplate(target);
+                    }
+                }, ActionLink.ActionType.TEMPLATE, StandardEntitlement.REALM_UPDATE).hideLabel();
+
+                actionPanel.add(new ActionLink<RealmTO>(realmTO) {
+
+                    private static final long serialVersionUID = 2802988981431379829L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
+                        onClickDelete(target, realmTO);
+                    }
+                }, ActionLink.ActionType.DELETE, StandardEntitlement.REALM_DELETE, true).hideLabel();
+            }
+
+            RealmDetails panel = new RealmDetails(panelId, realmTO, actionPanel, false);
+            panel.setContentEnabled(false);
+            actionPanel.setEnabled(true);
+            return panel;
+        }
+
+        @Override
+        public boolean isVisible() {
+            return SyncopeConsoleApplication.get().getSecuritySettings().getAuthorizationStrategy().
+                    isActionAuthorized(this, RENDER);
+        }
+    }
 }
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java
index 6b4b15d56e..235f233155 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java
@@ -23,8 +23,7 @@ import de.agilecoders.wicket.core.markup.html.bootstrap.button.BootstrapAjaxLink
 import de.agilecoders.wicket.core.markup.html.bootstrap.button.ButtonList;
 import de.agilecoders.wicket.core.markup.html.bootstrap.button.Buttons;
 import de.agilecoders.wicket.core.markup.html.bootstrap.button.dropdown.DropDownButton;
-import de.agilecoders.wicket.core.markup.html.bootstrap.image.GlyphIconType;
-import de.agilecoders.wicket.core.markup.html.bootstrap.image.IconType;
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.icon.FontAwesome5IconType;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -107,32 +106,19 @@ public class RealmChoicePanel extends Panel {
 
             private static final long serialVersionUID = -7688359318035249200L;
 
-            private void getChildren(
-                    final List<Pair<String, RealmTO>> full,
-                    final String key,
-                    final Map<String, Pair<RealmTO, List<RealmTO>>> tree,
-                    final String indent) {
-
-                if (tree.containsKey(key)) {
-                    Pair<RealmTO, List<RealmTO>> subtree = tree.get(key);
-                    subtree.getValue().forEach(child -> {
-                        full.add(Pair.of(indent + child.getName(), child));
-                        getChildren(full, child.getKey(), tree, "     " + indent + (indent.isEmpty() ? "|--- " : ""));
-                    });
-                }
-            }
-
             @Override
             protected List<Pair<String, RealmTO>> load() {
                 Map<String, Pair<RealmTO, List<RealmTO>>> map = reloadRealmParentMap();
-                List<Pair<String, RealmTO>> full = new ArrayList<>();
+                Stream<Pair<String, RealmTO>> full;
                 if (isSearchEnabled) {
-                    full = map.entrySet().stream().map(
-                            el -> Pair.of(el.getKey(), el.getValue().getKey())).collect(Collectors.toList());
+                    full = map.entrySet().stream().
+                            map(el -> Pair.of(el.getKey(), el.getValue().getLeft()));
                 } else {
-                    getChildren(full, null, map, StringUtils.EMPTY);
+                    full = map.entrySet().stream().
+                            map(el -> Pair.of(el.getValue().getLeft().getFullPath(), el.getValue().getKey())).
+                            sorted(Comparator.comparing(Pair::getLeft));
                 }
-                return full.stream().filter(realm -> availableRealms.stream().anyMatch(
+                return full.filter(realm -> availableRealms.stream().anyMatch(
                         availableRealm -> realm.getValue().getFullPath().startsWith(availableRealm))).
                         collect(Collectors.toList());
             }
@@ -148,11 +134,11 @@ public class RealmChoicePanel extends Panel {
                 dynRealms.sort((left, right) -> {
                     if (left == null) {
                         return -1;
-                    } else if (right == null) {
+                    }
+                    if (right == null) {
                         return 1;
-                    } else {
-                        return left.getKey().compareTo(right.getKey());
                     }
+                    return left.getKey().compareTo(right.getKey());
                 });
                 return dynRealms.stream().filter(dynRealm -> availableRealms.stream().
                         anyMatch(availableRealm -> SyncopeConstants.ROOT_REALM.equals(availableRealm)
@@ -167,14 +153,15 @@ public class RealmChoicePanel extends Panel {
                     RealmsUtils.buildQuery(SyncopeConstants.ROOT_REALM.equals(rootRealm)
                             ? SyncopeConstants.ROOT_REALM : rootRealmName)).getResult();
 
-            return realmTOs.stream().filter(realm -> rootRealm.equals(realm.getFullPath())).findFirst().
+            return realmTOs.stream().
+                    filter(realm -> rootRealm.equals(realm.getFullPath())).findFirst().
                     orElseGet(() -> {
                         RealmTO placeholder = new RealmTO();
                         placeholder.setName(rootRealmName);
                         placeholder.setFullPath(rootRealm);
                         return placeholder;
                     });
-        }).orElseGet(() -> new RealmTO());
+        }).orElseGet(RealmTO::new);
 
         model = Model.of(realmTO);
         searchQuery = realmTO.getName();
@@ -202,12 +189,12 @@ public class RealmChoicePanel extends Panel {
 
         if (isSearchEnabled) {
             realmsChoices = buildRealmChoices();
-            final AutoCompleteSettings settings = new AutoCompleteSettings();
+            AutoCompleteSettings settings = new AutoCompleteSettings();
             settings.setShowCompleteListOnFocusGain(false);
             settings.setShowListOnEmptyInput(false);
 
-            final AutoCompleteTextField<String> searchRealms =
-                    new AutoCompleteTextField<String>(SEARCH_REALMS, new Model<String>(), settings) {
+            AutoCompleteTextField<String> searchRealms =
+                    new AutoCompleteTextField<String>(SEARCH_REALMS, new Model<>(), settings) {
 
                 private static final long serialVersionUID = -6635259975264955783L;
 
@@ -216,15 +203,16 @@ public class RealmChoicePanel extends Panel {
                     searchQuery = input;
                     realmsChoices = RealmsUtils.checkInput(input)
                             ? buildRealmChoices()
-                            : Collections.<RealmTO>emptyList();
+                            : Collections.emptyList();
                     return realmsChoices.stream().
-                            map(item -> item.getFullPath()).sorted().collect(Collectors.toList()).iterator();
+                            map(RealmTO::getFullPath).sorted().collect(Collectors.toList()).iterator();
                 }
 
                 @Override
                 protected AutoCompleteBehavior<String> newAutoCompleteBehavior(
                         final IAutoCompleteRenderer<String> renderer,
                         final AutoCompleteSettings settings) {
+
                     return super.newAutoCompleteBehavior(new AbstractAutoCompleteRenderer<String>() {
 
                         private static final long serialVersionUID = -4789925973199139157L;
@@ -267,8 +255,8 @@ public class RealmChoicePanel extends Panel {
             fragment.addOrReplace(searchRealms);
             container.addOrReplace(fragment);
         } else {
-            final DropDownButton realms = new DropDownButton(
-                    "realms", new ResourceModel("select", ""), new Model<IconType>(GlyphIconType.folderopen)) {
+            DropDownButton realms = new DropDownButton(
+                    "realms", new ResourceModel("select", ""), new Model<>(FontAwesome5IconType.folder_open_r)) {
 
                 private static final long serialVersionUID = -5560086780455361131L;
 
@@ -293,7 +281,7 @@ public class RealmChoicePanel extends Panel {
         RealmChoicePanel.this.links.clear();
         RealmChoicePanel.this.links.add(new BootstrapAjaxLink<RealmTO>(
                 ButtonList.getButtonMarkupId(),
-                new Model<RealmTO>(),
+                new Model<>(),
                 Buttons.Type.Link,
                 new ResourceModel("realms", "Realms")) {
 
@@ -310,28 +298,26 @@ public class RealmChoicePanel extends Panel {
 
             @Override
             protected void onComponentTag(final ComponentTag tag) {
-                tag.put("class", "panel box box-primary box-header with-border");
-                tag.put("style", "margin: 20px 5px 0px 5px; width: 90%");
+                tag.put("class", "dropdown-header disabled");
             }
         });
 
         realmTree.getObject().forEach(link -> {
-            RealmTO realmTO = link.getValue();
             RealmChoicePanel.this.links.add(new BootstrapAjaxLink<RealmTO>(
                     ButtonList.getButtonMarkupId(),
-                    Model.of(realmTO),
+                    Model.of(link.getRight()),
                     Buttons.Type.Link,
-                    new Model<>(link.getKey())) {
+                    new Model<>(link.getLeft())) {
 
                 private static final long serialVersionUID = -7978723352517770644L;
 
                 @Override
                 public void onClick(final AjaxRequestTarget target) {
-                    model.setObject(realmTO);
+                    model.setObject(link.getRight());
                     label.setDefaultModelObject(model.getObject().getFullPath());
                     realmLabel.setDefaultModel(new ResourceModel("realmLabel", "Realm"));
                     target.add(label);
-                    send(pageRef.getPage(), Broadcast.EXACT, new ChosenRealm<>(realmTO, target));
+                    send(pageRef.getPage(), Broadcast.EXACT, new ChosenRealm<>(link.getRight(), target));
                 }
             });
         });
@@ -339,7 +325,7 @@ public class RealmChoicePanel extends Panel {
         if (!dynRealmTree.getObject().isEmpty()) {
             RealmChoicePanel.this.links.add(new BootstrapAjaxLink<RealmTO>(
                     ButtonList.getButtonMarkupId(),
-                    new Model<RealmTO>(),
+                    new Model<>(),
                     Buttons.Type.Link,
                     new ResourceModel("dynrealms", "Dynamic Realms")) {
 
@@ -347,7 +333,6 @@ public class RealmChoicePanel extends Panel {
 
                 @Override
                 public void onClick(final AjaxRequestTarget target) {
-
                 }
 
                 @Override
@@ -357,8 +342,7 @@ public class RealmChoicePanel extends Panel {
 
                 @Override
                 protected void onComponentTag(final ComponentTag tag) {
-                    tag.put("class", "panel box box-primary box-header with-border");
-                    tag.put("style", "margin: 20px 5px 0px 5px; width: 90%");
+                    tag.put("class", "dropdown-header disabled");
                 }
             });
 
@@ -370,7 +354,7 @@ public class RealmChoicePanel extends Panel {
 
                 RealmChoicePanel.this.links.add(new BootstrapAjaxLink<RealmTO>(
                         ButtonList.getButtonMarkupId(),
-                        new Model<RealmTO>(),
+                        new Model<>(),
                         Buttons.Type.Link,
                         new Model<>(realmTO.getKey())) {
 
@@ -413,14 +397,11 @@ public class RealmChoicePanel extends Panel {
 
     private Map<String, Pair<RealmTO, List<RealmTO>>> reloadRealmParentMap(final List<RealmTO> realms) {
         tree.clear();
-        if (!isSearchEnabled) {
-            tree.put(null, Pair.<RealmTO, List<RealmTO>>of(realms.get(0), new ArrayList<>()));
-        }
 
-        final Map<String, List<RealmTO>> cache = new HashMap<>();
+        Map<String, List<RealmTO>> cache = new HashMap<>();
 
         realms.forEach(realm -> {
-            final List<RealmTO> children = new ArrayList<>();
+            List<RealmTO> children = new ArrayList<>();
             tree.put(realm.getKey(), Pair.<RealmTO, List<RealmTO>>of(realm, children));
 
             if (cache.containsKey(realm.getKey())) {
@@ -441,15 +422,14 @@ public class RealmChoicePanel extends Panel {
 
     private List<RealmTO> buildRealmChoices() {
         return Stream.of(
-                realmTree.getObject().stream().map(item -> item.getValue()).collect(Collectors.toList()),
-                dynRealmTree.getObject().stream().map(
-                        item -> {
-                            final RealmTO realmTO = new RealmTO();
-                            realmTO.setKey(item.getKey());
-                            realmTO.setName(item.getKey());
-                            realmTO.setFullPath(item.getKey());
-                            return realmTO;
-                        }).collect(Collectors.toList())).flatMap(Collection::stream).
+                realmTree.getObject().stream().map(Pair::getValue).collect(Collectors.toList()),
+                dynRealmTree.getObject().stream().map(item -> {
+                    RealmTO realmTO = new RealmTO();
+                    realmTO.setKey(item.getKey());
+                    realmTO.setName(item.getKey());
+                    realmTO.setFullPath(item.getKey());
+                    return realmTO;
+                }).collect(Collectors.toList())).flatMap(Collection::stream).
                 collect(Collectors.toList());
     }
 
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
index b1f7551bea..74ff503db4 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
@@ -91,6 +91,8 @@ public class RealmDetails extends Panel {
         }
     };
 
+    private final ActionsPanel<RealmTO> actionsPanel;
+
     private final WebMarkupContainer container;
 
     public RealmDetails(final String id, final RealmTO realmTO) {
@@ -100,11 +102,13 @@ public class RealmDetails extends Panel {
     public RealmDetails(
             final String id,
             final RealmTO realmTO,
-            final ActionsPanel<?> actionsPanel,
+            final ActionsPanel<RealmTO> actionsPanel,
             final boolean unwrapped) {
 
         super(id);
 
+        this.actionsPanel = actionsPanel;
+
         container = new WebMarkupContainer("container");
         container.setOutputMarkupId(true);
         container.setRenderBodyOnly(unwrapped);
@@ -172,4 +176,8 @@ public class RealmDetails extends Panel {
         container.setEnabled(enable);
         return this;
     }
+
+    public ActionsPanel<RealmTO> getActionsPanel() {
+        return actionsPanel;
+    }
 }
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmWizardBuilder.java
index 9edcded301..edcdb8d8b9 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmWizardBuilder.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmWizardBuilder.java
@@ -32,9 +32,9 @@ public class RealmWizardBuilder extends AjaxWizardBuilder<RealmTO> {
 
     private static final long serialVersionUID = 5945391813567245081L;
 
-    private final RealmRestClient realmRestClient = new RealmRestClient();
+    protected final RealmRestClient realmRestClient = new RealmRestClient();
 
-    private String parentPath;
+    protected String parentPath;
 
     /**
      * Construct.
@@ -71,7 +71,6 @@ public class RealmWizardBuilder extends AjaxWizardBuilder<RealmTO> {
             realmDetail.add(new AttributeAppender("style", "overflow-x:hidden;"));
             add(realmDetail);
         }
-
     }
 
     public void setParentPath(final String parentPath) {