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/18 14:53:21 UTC

[syncope] 02/02: Improving Realms page extendability

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

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

commit ac55c571f5ca4ea3ca118b626246fb4d5f1dbaea
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Wed May 18 16:53:08 2022 +0200

    Improving Realms page extendability
---
 .../client/console/SyncopeConsoleSession.java      |  10 +-
 .../client/console/commons/RealmsUtils.java        |   2 +-
 .../syncope/client/console/pages/Realms.java       | 180 +++++++------
 .../syncope/client/console/panels/AnyPanel.java    |   2 +-
 .../syncope/client/console/panels/Realm.java       | 211 +++++++++-------
 .../client/console/panels/RealmChoicePanel.java    | 277 ++++++++++-----------
 .../client/console/panels/RealmDetails.java        |  12 +-
 .../client/console/panels/RealmWizardBuilder.java  |   3 +-
 .../client/console/rest/RealmRestClient.java       |   4 +-
 .../console/wicket/markup/html/form/Action.java    |   2 +-
 .../wicket/markup/html/form/ActionsPanel.java      |  10 +
 .../client/console/widgets/NumberWidget.java       |  10 +-
 .../client/console/panels/RealmChoicePanel.html    |   2 +-
 .../syncope/core/logic/ReconciliationLogic.java    |   2 +-
 .../java/data/RealmDataBinderImpl.java             |   3 +-
 .../apache/syncope/fit/console/RealmsITCase.java   |   8 +-
 16 files changed, 396 insertions(+), 342 deletions(-)

diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
index 3292c2c667..e0f1c3ecc3 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
@@ -292,9 +292,13 @@ public class SyncopeConsoleSession extends AuthenticatedWebSession implements Ba
                 : roots.stream().sorted().collect(Collectors.toList());
     }
 
-    public Optional<String> getRootRealm() {
-        List<String> roots = getSearchableRealms();
-        return roots.isEmpty() ? Optional.empty() : roots.stream().findFirst();
+    public Optional<String> getRootRealm(final String initial) {
+        List<String> searchable = getSearchableRealms();
+        return searchable.isEmpty()
+                ? Optional.empty()
+                : initial != null && searchable.stream().anyMatch(initial::startsWith)
+                ? Optional.of(initial)
+                : searchable.stream().findFirst();
     }
 
     public boolean owns(final String entitlements, final String... realms) {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/RealmsUtils.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/RealmsUtils.java
index bfef5acc9d..1553337c36 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/RealmsUtils.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/RealmsUtils.java
@@ -48,7 +48,7 @@ public final class RealmsUtils {
     public static boolean isSearchEnabled(final List<String> realms) {
         return realms.isEmpty()
                 ? false
-                : new RealmRestClient().search(
+                : RealmRestClient.search(
                         new RealmQuery.Builder().keyword(
                                 realms.contains(SyncopeConstants.ROOT_REALM)
                                 ? SyncopeConstants.ROOT_REALM
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
index 1f2b18b653..706fd73d62 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
+++ b/client/idrepo/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.SyncopeConsoleSession;
 import org.apache.syncope.client.console.panels.Realm;
 import org.apache.syncope.client.console.panels.RealmChoicePanel;
@@ -30,13 +31,16 @@ import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.Bas
 import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.any.ResultPage;
 import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
+import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.ui.commons.Constants;
 import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
 import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
 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.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.event.IEvent;
@@ -51,15 +55,19 @@ public class Realms extends BasePage {
 
     private static final long serialVersionUID = -1100228004207271270L;
 
-    private final TemplatesTogglePanel templates;
+    public static final String SELECTED_INDEX = "selectedIndex";
 
-    private final RealmChoicePanel realmChoicePanel;
+    public static final String INITIAL_REALM = "initialRealm";
 
-    private final WebMarkupContainer content;
+    protected final TemplatesTogglePanel templates;
 
-    private final BaseModal<RealmTO> modal;
+    protected final RealmChoicePanel realmChoicePanel;
 
-    private final BaseModal<Serializable> templateModal;
+    protected final WebMarkupContainer content;
+
+    protected final BaseModal<RealmTO> modal;
+
+    protected final BaseModal<Serializable> templateModal;
 
     public Realms(final PageParameters parameters) {
         super(parameters);
@@ -82,8 +90,7 @@ public class Realms extends BasePage {
 
         content = new WebMarkupContainer("content");
 
-        realmChoicePanel = new RealmChoicePanel("realmChoicePanel", getPageReference());
-        realmChoicePanel.setOutputMarkupId(true);
+        realmChoicePanel = buildRealmChoicePanel(parameters.get(INITIAL_REALM).toOptionalString(), getPageReference());
         content.add(realmChoicePanel);
 
         content.add(new Label("body", "Root realm"));
@@ -120,7 +127,17 @@ public class Realms extends BasePage {
             templateModal.show(false);
         });
 
-        updateRealmContent(realmChoicePanel.getCurrentRealm(), parameters.get("selectedIndex").toInt(0));
+        updateRealmContent(realmChoicePanel.getCurrentRealm(), parameters.get(SELECTED_INDEX).toInt(0));
+    }
+
+    protected RealmChoicePanel buildRealmChoicePanel(final String initialRealm, final PageReference pageRef) {
+        RealmChoicePanel panel = new RealmChoicePanel("realmChoicePanel", initialRealm, pageRef);
+        panel.setOutputMarkupId(true);
+        return panel;
+    }
+
+    public RealmChoicePanel getRealmChoicePanel() {
+        return realmChoicePanel;
     }
 
     @Override
@@ -156,88 +173,89 @@ 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;
+    protected class Content extends Realm {
 
-            @Override
-            protected void onClickTemplate(final AjaxRequestTarget target) {
-                templates.setTargetObject(realmTO);
-                templates.toggle(target, true);
-            }
+        private static final long serialVersionUID = 8221398624379357183L;
 
-            @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);
-                });
-            }
-
-            @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";
                 }
-                ((BaseWebPage) 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", " "));
+            }
+            ((BaseWebPage) Realms.this.getPage()).getNotificationPanel().refresh(target);
+        }
     }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java
index efb5b91e68..ec9590ab6a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java
@@ -83,7 +83,7 @@ public class AnyPanel extends Panel implements ModalPanel {
                 PageReference pageRef);
     }
 
-    protected static DirectoryPanelSupplier DEFAULT_DIRECTORYPANEL_SUPPLIER =
+    protected static final DirectoryPanelSupplier DEFAULT_DIRECTORYPANEL_SUPPLIER =
             (id, anyTypeTO, realmTO, anyLayout, pageRef) -> {
 
                 Panel panel;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
index 625d2bc423..8ce7769914 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
+++ b/client/idrepo/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.ui.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;
@@ -55,7 +53,6 @@ import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
 import org.apache.wicket.model.ResourceModel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -66,24 +63,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 = 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 +97,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"),
-                IdRepoEntitlement.REALM_CREATE, IdRepoEntitlement.REALM_UPDATE, IdRepoEntitlement.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) {
-
-                        private static final long serialVersionUID = 2802988981431379827L;
-
-                        @Override
-                        public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
-                            onClickCreate(target);
-                        }
-                    }, ActionLink.ActionType.CREATE, IdRepoEntitlement.REALM_CREATE).hideLabel();
-
-                    actionPanel.add(new ActionLink<>(realmTO) {
-
-                        private static final long serialVersionUID = 2802988981431379828L;
-
-                        @Override
-                        public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
-                            onClickEdit(target, realmTO);
-                        }
-                    }, ActionLink.ActionType.EDIT, IdRepoEntitlement.REALM_UPDATE).hideLabel();
-
-                    actionPanel.add(new ActionLink<>(realmTO) {
-
-                        private static final long serialVersionUID = 2802988981431379827L;
-
-                        @Override
-                        public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
-                            onClickTemplate(target);
-                        }
-                    }, ActionLink.ActionType.TEMPLATE, IdRepoEntitlement.REALM_UPDATE).hideLabel();
-
-                    actionPanel.add(new ActionLink<>(realmTO) {
-
-                        private static final long serialVersionUID = 2802988981431379829L;
-
-                        @Override
-                        public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
-                            onClickDelete(target, realmTO);
-                        }
-                    }, ActionLink.ActionType.DELETE, IdRepoEntitlement.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 SyncopeWebApplication.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 +143,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 +154,8 @@ public abstract class Realm extends WizardMgtPanel<RealmTO> {
         propagations.add(syncope);
         propagations.addAll(((ProvisioningResult) result).getPropagationStatuses());
 
-        ListViewPanel.Builder<PropagationStatus> builder = new ListViewPanel.Builder<>(
-            PropagationStatus.class, pageRef) {
+        ListViewPanel.Builder<PropagationStatus> builder =
+                new ListViewPanel.Builder<>(PropagationStatus.class, pageRef) {
 
             private static final long serialVersionUID = -6809736686861678498L;
 
@@ -215,19 +164,21 @@ public abstract class Realm extends WizardMgtPanel<RealmTO> {
                 if ("afterObj".equalsIgnoreCase(key)) {
                     ConnObjectTO afterObj = bean.getAfterObj();
                     String remoteId = afterObj == null
-                        || afterObj.getAttrs().isEmpty()
-                        || afterObj.getAttr(ConnIdSpecialName.NAME).isEmpty()
-                        || afterObj.getAttr(ConnIdSpecialName.NAME).get().getValues() == null
-                        || afterObj.getAttr(ConnIdSpecialName.NAME).get().getValues().isEmpty()
-                        ? StringUtils.EMPTY
-                        : afterObj.getAttr(ConnIdSpecialName.NAME).get().getValues().get(0);
+                            || afterObj.getAttrs().isEmpty()
+                            || afterObj.getAttr(ConnIdSpecialName.NAME).isEmpty()
+                            || afterObj.getAttr(ConnIdSpecialName.NAME).get().getValues() == null
+                            || afterObj.getAttr(ConnIdSpecialName.NAME).get().getValues().isEmpty()
+                            ? StringUtils.EMPTY
+                            : 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);
             }
         };
 
@@ -244,8 +195,8 @@ public abstract class Realm extends WizardMgtPanel<RealmTO> {
             @Override
             protected boolean statusCondition(final PropagationStatus bean) {
                 return !Constants.SYNCOPE.equals(bean.getResource())
-                    && (ExecStatus.CREATED == bean.getStatus()
-                    || ExecStatus.SUCCESS == bean.getStatus());
+                        && (ExecStatus.CREATED == bean.getStatus()
+                        || ExecStatus.SUCCESS == bean.getStatus());
             }
 
             @Override
@@ -282,13 +233,13 @@ public abstract class Realm extends WizardMgtPanel<RealmTO> {
 
     protected abstract void onClickDelete(AjaxRequestTarget target, RealmTO realmTO);
 
-    static 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,
@@ -302,4 +253,72 @@ 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 ResourceModel("realm.details", "DETAILS"),
+                    IdRepoEntitlement.REALM_CREATE, IdRepoEntitlement.REALM_UPDATE, IdRepoEntitlement.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) {
+
+                    private static final long serialVersionUID = 2802988981431379827L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
+                        onClickCreate(target);
+                    }
+                }, ActionLink.ActionType.CREATE, IdRepoEntitlement.REALM_CREATE).hideLabel();
+
+                actionPanel.add(new ActionLink<>(realmTO) {
+
+                    private static final long serialVersionUID = 2802988981431379828L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
+                        onClickEdit(target, realmTO);
+                    }
+                }, ActionLink.ActionType.EDIT, IdRepoEntitlement.REALM_UPDATE).hideLabel();
+
+                actionPanel.add(new ActionLink<>(realmTO) {
+
+                    private static final long serialVersionUID = 2802988981431379827L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
+                        onClickTemplate(target);
+                    }
+                }, ActionLink.ActionType.TEMPLATE, IdRepoEntitlement.REALM_UPDATE).hideLabel();
+
+                actionPanel.add(new ActionLink<>(realmTO) {
+
+                    private static final long serialVersionUID = 2802988981431379829L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
+                        onClickDelete(target, realmTO);
+                    }
+                }, ActionLink.ActionType.DELETE, IdRepoEntitlement.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 SyncopeWebApplication.get().getSecuritySettings().getAuthorizationStrategy().
+                    isActionAuthorized(this, RENDER);
+        }
+    }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java
index d4c149d602..da1cbe8636 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java
@@ -59,6 +59,7 @@ import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.link.AbstractLink;
 import org.apache.wicket.markup.html.panel.Fragment;
 import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.LoadableDetachableModel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.ResourceModel;
@@ -68,34 +69,36 @@ public class RealmChoicePanel extends Panel {
 
     private static final long serialVersionUID = -1100228004207271270L;
 
-    private static final String SEARCH_REALMS = "searchRealms";
+    protected static final String SEARCH_REALMS = "searchRealms";
 
-    private final PageReference pageRef;
+    protected final PageReference pageRef;
 
-    private final LoadableDetachableModel<List<Pair<String, RealmTO>>> realmTree;
+    protected final LoadableDetachableModel<List<Pair<String, RealmTO>>> realmTree;
 
-    private final LoadableDetachableModel<List<DynRealmTO>> dynRealmTree;
+    protected final LoadableDetachableModel<List<DynRealmTO>> dynRealmTree;
 
-    private final WebMarkupContainerNoVeil container;
+    protected final WebMarkupContainerNoVeil container;
 
-    private Model<RealmTO> model;
+    protected Model<RealmTO> model;
 
-    private final Collection<String> availableRealms;
+    protected final Map<String, Pair<RealmTO, List<RealmTO>>> tree;
 
-    private final Map<String, Pair<RealmTO, List<RealmTO>>> tree;
+    protected final List<AbstractLink> links = new ArrayList<>();
 
-    private final List<AbstractLink> links = new ArrayList<>();
+    protected String searchQuery;
 
-    private String searchQuery;
+    protected List<RealmTO> realmsChoices;
 
-    private List<RealmTO> realmsChoices;
+    protected final boolean isSearchEnabled;
 
-    private final boolean isSearchEnabled;
+    protected final Label realmDisplayKey;
 
-    public RealmChoicePanel(final String id, final PageReference pageRef) {
+    protected final Label realmDisplayValue;
+
+    public RealmChoicePanel(final String id, final String initialRealm, final PageReference pageRef) {
         super(id);
         this.pageRef = pageRef;
-        availableRealms = SyncopeConsoleSession.get().getSearchableRealms();
+
         tree = new HashMap<>();
         isSearchEnabled = RealmsUtils.isSearchEnabled(SyncopeConsoleSession.get().getSearchableRealms());
 
@@ -106,23 +109,18 @@ public class RealmChoicePanel extends Panel {
             @Override
             protected List<Pair<String, RealmTO>> load() {
                 Map<String, Pair<RealmTO, List<RealmTO>>> map = reloadRealmParentMap();
-                List<Pair<String, RealmTO>> full;
+                Stream<Pair<String, RealmTO>> full;
                 if (isSearchEnabled) {
-                    full = map.entrySet().stream().map(el -> Pair.of(
-                        el.getKey(),
-                        el.getValue().getLeft())).
-                        collect(Collectors.toList());
+                    full = map.entrySet().stream().
+                            map(el -> Pair.of(el.getKey(), el.getValue().getLeft()));
                 } else {
                     full = map.entrySet().stream().
-                        map(el -> Pair.of(
-                            el.getValue().getLeft().getFullPath(),
-                            el.getValue().getKey())).
-                        sorted(Comparator.comparing(Pair::getLeft)).
-                        collect(Collectors.toList());
+                            map(el -> Pair.of(el.getValue().getLeft().getFullPath(), el.getValue().getKey())).
+                            sorted(Comparator.comparing(Pair::getLeft));
                 }
-                return full.stream().filter(realm -> availableRealms.stream().anyMatch(
-                    availableRealm -> realm.getValue().getFullPath().startsWith(availableRealm))).
-                    collect(Collectors.toList());
+                return full.filter(realm -> SyncopeConsoleSession.get().getSearchableRealms().stream().anyMatch(
+                        availableRealm -> realm.getValue().getFullPath().startsWith(availableRealm))).
+                        collect(Collectors.toList());
             }
         };
 
@@ -132,30 +130,31 @@ public class RealmChoicePanel extends Panel {
 
             @Override
             protected List<DynRealmTO> load() {
-                List<DynRealmTO> dynRealms = RealmRestClient.listDynReams();
+                List<DynRealmTO> dynRealms = RealmRestClient.listDynRealms();
                 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)
+                return dynRealms.stream().filter(dynRealm -> SyncopeConsoleSession.get().getSearchableRealms().stream().
+                        anyMatch(availableRealm -> SyncopeConstants.ROOT_REALM.equals(availableRealm)
                         || dynRealm.getKey().equals(availableRealm))).collect(Collectors.toList());
             }
         };
 
-        RealmTO realmTO = SyncopeConsoleSession.get().getRootRealm().map(rootRealm -> {
+        RealmTO realm = SyncopeConsoleSession.get().getRootRealm(initialRealm).map(rootRealm -> {
             String rootRealmName = StringUtils.substringAfterLast(rootRealm, "/");
 
             List<RealmTO> realmTOs = RealmRestClient.search(
                     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(r -> rootRealm.equals(r.getFullPath())).findFirst().
                     orElseGet(() -> {
                         RealmTO placeholder = new RealmTO();
                         placeholder.setName(rootRealmName);
@@ -164,74 +163,88 @@ public class RealmChoicePanel extends Panel {
                     });
         }).orElseGet(RealmTO::new);
 
-        model = Model.of(realmTO);
-        searchQuery = realmTO.getName();
+        model = Model.of(realm);
+        searchQuery = realm.getName();
+
         container = new WebMarkupContainerNoVeil("container", realmTree);
-        container.setOutputMarkupId(true);
-        add(container);
+        add(container.setOutputMarkupId(true));
+
+        realmDisplayKey = new Label("realmDisplayKey", realmDisplayKeyModel(null));
+        container.addOrReplace(realmDisplayKey.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
+        realmDisplayValue = new Label("realmDisplayValue", realmDisplayValueText());
+        container.addOrReplace(realmDisplayValue.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
+
         reloadRealmTree();
     }
 
-    public final void reloadRealmTree() {
-        Label realmLabel = new Label("realmLabel", new Model<>());
-        realmLabel.setOutputMarkupId(true);
-
-        container.addOrReplace(realmLabel);
+    protected IModel<String> realmDisplayKeyModel(final Boolean dynamic) {
+        return dynamic == null
+                ? model.getObject().getFullPath().startsWith(SyncopeConstants.ROOT_REALM)
+                ? new ResourceModel("realmDisplayKey", "Realm")
+                : new ResourceModel("dynRealmLabel", "Dynamic Realm")
+                : dynamic
+                        ? new ResourceModel("dynRealmLabel", "Dynamic Realm")
+                        : new ResourceModel("realmDisplayKey", "Realm");
+    }
 
-        if (StringUtils.startsWith(model.getObject().getFullPath(), SyncopeConstants.ROOT_REALM)) {
-            realmLabel.setDefaultModel(new ResourceModel("realmLabel", "Realm"));
-        } else {
-            realmLabel.setDefaultModel(new ResourceModel("dynRealmLabel", "Dynamic Realm"));
-        }
+    protected String realmDisplayValueText() {
+        return RealmsUtils.getFullPath(model.getObject().getFullPath());
+    }
 
-        Label label = new Label("realm", RealmsUtils.getFullPath(model.getObject().getFullPath()));
-        label.setOutputMarkupId(true);
-        container.addOrReplace(label);
+    protected void chooseRealm(final RealmTO realm, final AjaxRequestTarget target) {
+        model.setObject(realm);
+        realmDisplayValue.setDefaultModelObject(realmDisplayValueText());
+        realmDisplayKey.setDefaultModel(realmDisplayKeyModel(false));
+        target.add(realmDisplayValue);
+        send(pageRef.getPage(), Broadcast.EXACT, new ChosenRealm<>(realm, target));
+    }
 
+    public void reloadRealmTree() {
         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<>(SEARCH_REALMS, new Model<>(), settings) {
+            AutoCompleteTextField<String> searchRealms =
+                    new AutoCompleteTextField<>(SEARCH_REALMS, new Model<>(), settings) {
 
-                    private static final long serialVersionUID = -6635259975264955783L;
+                private static final long serialVersionUID = -6635259975264955783L;
 
-                    @Override
-                    protected Iterator<String> getChoices(final String input) {
-                        searchQuery = input;
-                        realmsChoices = RealmsUtils.checkInput(input)
+                @Override
+                protected Iterator<String> getChoices(final String input) {
+                    searchQuery = input;
+                    realmsChoices = RealmsUtils.checkInput(input)
                             ? buildRealmChoices()
                             : List.of();
-                        return realmsChoices.stream().
-                            map(RealmTO::getFullPath).sorted().collect(Collectors.toList()).iterator();
-                    }
+                    return realmsChoices.stream().map(RealmTO::getFullPath).sorted().iterator();
+                }
 
-                    @Override
-                    protected AutoCompleteBehavior<String> newAutoCompleteBehavior(
+                @Override
+                protected AutoCompleteBehavior<String> newAutoCompleteBehavior(
                         final IAutoCompleteRenderer<String> renderer,
                         final AutoCompleteSettings settings) {
-                        return super.newAutoCompleteBehavior(new AbstractAutoCompleteRenderer<>() {
 
-                            private static final long serialVersionUID = -4789925973199139157L;
+                    return super.newAutoCompleteBehavior(new AbstractAutoCompleteRenderer<>() {
+
+                        private static final long serialVersionUID = -4789925973199139157L;
 
-                            @Override
-                            protected void renderChoice(
+                        @Override
+                        protected void renderChoice(
                                 final String object,
                                 final Response response,
                                 final String criteria) {
-                                response.write(object);
-                            }
-
-                            @Override
-                            protected String getTextValue(final String object) {
-                                return object;
-                            }
-                        }, settings);
-                    }
-                };
+
+                            response.write(object);
+                        }
+
+                        @Override
+                        protected String getTextValue(final String object) {
+                            return object;
+                        }
+                    }, settings);
+                }
+            };
 
             searchRealms.add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
 
@@ -239,15 +252,9 @@ public class RealmChoicePanel extends Panel {
 
                 @Override
                 protected void onUpdate(final AjaxRequestTarget target) {
-                    realmsChoices.stream().filter(
-                            item -> item.getFullPath().equals(searchRealms.getModelObject())).
-                            findFirst().ifPresent(realm -> {
-                                model.setObject(realm);
-                                label.setDefaultModelObject(model.getObject().getFullPath());
-                                realmLabel.setDefaultModel(new ResourceModel("realmLabel", "Realm"));
-                                target.add(label);
-                                send(pageRef.getPage(), Broadcast.EXACT, new ChosenRealm<>(realm, target));
-                            });
+                    realmsChoices.stream().
+                            filter(item -> item.getFullPath().equals(searchRealms.getModelObject())).
+                            findFirst().ifPresent(realm -> chooseRealm(realm, target));
                 }
             });
 
@@ -262,7 +269,7 @@ public class RealmChoicePanel extends Panel {
 
                 @Override
                 protected List<AbstractLink> newSubMenuButtons(final String buttonMarkupId) {
-                    buildRealmLinks(label, realmLabel);
+                    buildRealmLinks();
                     return RealmChoicePanel.this.links;
                 }
             };
@@ -277,13 +284,13 @@ public class RealmChoicePanel extends Panel {
         }
     }
 
-    private void buildRealmLinks(final Label label, final Label realmLabel) {
+    protected void buildRealmLinks() {
         RealmChoicePanel.this.links.clear();
         RealmChoicePanel.this.links.add(new BootstrapAjaxLink<>(
-            ButtonList.getButtonMarkupId(),
-            new Model<>(),
-            Buttons.Type.Link,
-            new ResourceModel("realms", "Realms")) {
+                ButtonList.getButtonMarkupId(),
+                new Model<>(),
+                Buttons.Type.Link,
+                new ResourceModel("realms", "Realms")) {
 
             private static final long serialVersionUID = -7978723352517770744L;
 
@@ -304,36 +311,31 @@ public class RealmChoicePanel extends Panel {
 
         realmTree.getObject().forEach(link -> {
             RealmChoicePanel.this.links.add(new BootstrapAjaxLink<>(
-                ButtonList.getButtonMarkupId(),
-                Model.of(link.getRight()),
-                Buttons.Type.Link,
-                new Model<>(link.getLeft())) {
+                    ButtonList.getButtonMarkupId(),
+                    Model.of(link.getRight()),
+                    Buttons.Type.Link,
+                    new Model<>(link.getLeft())) {
 
                 private static final long serialVersionUID = -7978723352517770644L;
 
                 @Override
                 public void onClick(final AjaxRequestTarget target) {
-                    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<>(link.getRight(), target));
+                    chooseRealm(link.getRight(), target);
                 }
             });
         });
 
         if (!dynRealmTree.getObject().isEmpty()) {
             RealmChoicePanel.this.links.add(new BootstrapAjaxLink<>(
-                ButtonList.getButtonMarkupId(),
-                new Model<>(),
-                Buttons.Type.Link,
-                new ResourceModel("dynrealms", "Dynamic Realms")) {
+                    ButtonList.getButtonMarkupId(),
+                    new Model<>(),
+                    Buttons.Type.Link,
+                    new ResourceModel("dynrealms", "Dynamic Realms")) {
 
                 private static final long serialVersionUID = -7978723352517770744L;
 
                 @Override
                 public void onClick(final AjaxRequestTarget target) {
-
                 }
 
                 @Override
@@ -348,34 +350,44 @@ public class RealmChoicePanel extends Panel {
             });
 
             dynRealmTree.getObject().forEach(dynRealmTO -> {
-                final RealmTO realmTO = new RealmTO();
-                realmTO.setKey(dynRealmTO.getKey());
-                realmTO.setName(dynRealmTO.getKey());
-                realmTO.setFullPath(dynRealmTO.getKey());
+                RealmTO realm = new RealmTO();
+                realm.setKey(dynRealmTO.getKey());
+                realm.setName(dynRealmTO.getKey());
+                realm.setFullPath(dynRealmTO.getKey());
 
                 RealmChoicePanel.this.links.add(new BootstrapAjaxLink<>(
-                    ButtonList.getButtonMarkupId(),
-                    new Model<>(),
-                    Buttons.Type.Link,
-                    new Model<>(realmTO.getKey())) {
+                        ButtonList.getButtonMarkupId(),
+                        new Model<>(),
+                        Buttons.Type.Link,
+                        new Model<>(realm.getKey())) {
 
                     private static final long serialVersionUID = -7978723352517770644L;
 
                     @Override
                     public void onClick(final AjaxRequestTarget target) {
-                        model.setObject(realmTO);
-                        label.setDefaultModelObject(realmTO.getKey());
-                        realmLabel.setDefaultModel(new ResourceModel("dynRealmLabel", "Dynamic Realm"));
-                        target.add(label);
-                        send(pageRef.getPage(), Broadcast.EXACT, new ChosenRealm<>(realmTO, target));
+                        chooseRealm(realm, target);
                     }
                 });
             });
         }
     }
 
+    protected List<RealmTO> buildRealmChoices() {
+        return Stream.of(
+                realmTree.getObject().stream().map(Pair::getValue).collect(Collectors.toList()),
+                dynRealmTree.getObject().stream().map(item -> {
+                    RealmTO realm = new RealmTO();
+                    realm.setKey(item.getKey());
+                    realm.setName(item.getKey());
+                    realm.setFullPath(item.getKey());
+                    return realm;
+                }).collect(Collectors.toList())).flatMap(Collection::stream).
+                collect(Collectors.toList());
+    }
+
     public final RealmChoicePanel reloadRealmTree(final AjaxRequestTarget target) {
         reloadRealmTree();
+        chooseRealm(model.getObject(), target);
         target.add(container);
         return this;
     }
@@ -386,7 +398,7 @@ public class RealmChoicePanel extends Panel {
         return this;
     }
 
-    private Map<String, Pair<RealmTO, List<RealmTO>>> reloadRealmParentMap() {
+    protected Map<String, Pair<RealmTO, List<RealmTO>>> reloadRealmParentMap() {
         List<RealmTO> realmsToList = isSearchEnabled
                 ? RealmRestClient.search(RealmsUtils.buildQuery(searchQuery)).getResult()
                 : RealmRestClient.list();
@@ -396,7 +408,7 @@ public class RealmChoicePanel extends Panel {
                 collect(Collectors.toList()));
     }
 
-    private Map<String, Pair<RealmTO, List<RealmTO>>> reloadRealmParentMap(final List<RealmTO> realms) {
+    protected Map<String, Pair<RealmTO, List<RealmTO>>> reloadRealmParentMap(final List<RealmTO> realms) {
         tree.clear();
 
         Map<String, List<RealmTO>> cache = new HashMap<>();
@@ -421,20 +433,6 @@ public class RealmChoicePanel extends Panel {
         return tree;
     }
 
-    private List<RealmTO> buildRealmChoices() {
-        return Stream.of(
-                realmTree.getObject().stream().map(Pair::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).
-                collect(Collectors.toList());
-    }
-
     /**
      * Gets current selected realm.
      *
@@ -458,14 +456,13 @@ public class RealmChoicePanel extends Panel {
             }
         }
         return null;
-
     }
 
     public static class ChosenRealm<T> {
 
-        private final AjaxRequestTarget target;
+        protected final AjaxRequestTarget target;
 
-        private final T obj;
+        protected final T obj;
 
         public ChosenRealm(final T obj, final AjaxRequestTarget target) {
             this.obj = obj;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
index 9c689f4c30..ccdbe61388 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
@@ -57,7 +57,7 @@ public class RealmDetails extends Panel {
         @Override
         protected List<String> load() {
             return ImplementationRestClient.list(IdRepoImplementationType.LOGIC_ACTIONS).stream().
-                map(EntityTO::getKey).sorted().collect(Collectors.toList());
+                    map(EntityTO::getKey).sorted().collect(Collectors.toList());
         }
     };
 
@@ -71,6 +71,8 @@ public class RealmDetails extends Panel {
         }
     };
 
+    private final ActionsPanel<RealmTO> actionsPanel;
+
     @SpringBean
     private RealmPolicyProvider realmPolicyProvider;
 
@@ -83,11 +85,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);
@@ -139,4 +143,8 @@ public class RealmDetails extends Panel {
         container.setEnabled(enable);
         return this;
     }
+
+    public ActionsPanel<RealmTO> getActionsPanel() {
+        return actionsPanel;
+    }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmWizardBuilder.java
index f85ab7b437..edefc3e4d8 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmWizardBuilder.java
@@ -32,7 +32,7 @@ public class RealmWizardBuilder extends BaseAjaxWizardBuilder<RealmTO> {
 
     private static final long serialVersionUID = 5945391813567245081L;
 
-    private String parentPath;
+    protected String parentPath;
 
     /**
      * Construct.
@@ -69,7 +69,6 @@ public class RealmWizardBuilder extends BaseAjaxWizardBuilder<RealmTO> {
             realmDetail.add(new AttributeAppender("style", "overflow-x:hidden;"));
             add(realmDetail);
         }
-
     }
 
     public void setParentPath(final String parentPath) {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java
index 1581dd3d84..46d5ca820d 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java
@@ -45,11 +45,11 @@ public class RealmRestClient extends BaseRestClient {
         return getService(RealmService.class).list(SyncopeConstants.ROOT_REALM);
     }
 
-    public static List<DynRealmTO> listDynReams() {
+    public static List<DynRealmTO> listDynRealms() {
         return getService(DynRealmService.class).list();
     }
 
-    public static DynRealmTO readDynReams(final String key) {
+    public static DynRealmTO readDynRealm(final String key) {
         return getService(DynRealmService.class).read(key);
     }
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/Action.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/Action.java
index f01a984106..a3979b3fa7 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/Action.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/Action.java
@@ -69,7 +69,7 @@ public final class Action<T extends Serializable> implements Serializable {
     }
 
     public String[] getRealms() {
-        return realms.toArray(new String[realms.size()]);
+        return realms.toArray(String[]::new);
     }
 
     public void setRealm(final String realm) {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel.java
index f34ea520f0..3d598a5151 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel.java
@@ -82,6 +82,16 @@ public final class ActionsPanel<T extends Serializable> extends Panel {
         return action;
     }
 
+    public Action<T> add(final int index, final Action<T> action) {
+        actions.add(index, action);
+        return action;
+    }
+
+    public Action<T> set(final int index, final Action<T> action) {
+        actions.set(index, action);
+        return action;
+    }
+
     public List<Action<T>> getActions() {
         return actions;
     }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/NumberWidget.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/NumberWidget.java
index e6e577f7a4..1f720a6f32 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/NumberWidget.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/NumberWidget.java
@@ -54,13 +54,13 @@ public class NumberWidget extends BaseWidget {
         List<String> anyTypes = AnyTypeRestClient.list();
         switch (id) {
             case "totalUsers":
-                pageParameters.add("selectedIndex", 1);
+                pageParameters.add(Realms.SELECTED_INDEX, 1);
                 responsePage = Realms.class;
                 isAuthorized = SyncopeConsoleSession.get().owns(IdRepoEntitlement.USER_SEARCH);
                 break;
 
             case "totalGroups":
-                pageParameters.add("selectedIndex", 2);
+                pageParameters.add(Realms.SELECTED_INDEX, 2);
                 responsePage = Realms.class;
                 isAuthorized = SyncopeConsoleSession.get().owns(IdRepoEntitlement.GROUP_SEARCH);
                 break;
@@ -71,7 +71,7 @@ public class NumberWidget extends BaseWidget {
                     for (int i = 0; i < anyTypes.size() && selectedIndex == null; i++) {
                         if (anyTypes.get(i).equals(label)) {
                             selectedIndex = i + 1;
-                            pageParameters.add("selectedIndex", selectedIndex);
+                            pageParameters.add(Realms.SELECTED_INDEX, selectedIndex);
                         }
                     }
                     responsePage = Realms.class;
@@ -87,7 +87,7 @@ public class NumberWidget extends BaseWidget {
                 for (int i = 0; i < anyTypes.size() && selectedIndex == null; i++) {
                     if (anyTypes.get(i).equals(label)) {
                         selectedIndex = i + 1;
-                        pageParameters.add("selectedIndex", selectedIndex);
+                        pageParameters.add(Realms.SELECTED_INDEX, selectedIndex);
                     }
                 }
                 responsePage = Realms.class;
@@ -95,7 +95,7 @@ public class NumberWidget extends BaseWidget {
                 break;
 
             default:
-                pageParameters.add("selectedIndex", 0);
+                pageParameters.add(Realms.SELECTED_INDEX, 0);
                 responsePage = Realms.class;
         }
 
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html
index 7d14dfc236..0691389902 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html
@@ -20,7 +20,7 @@ under the License.
   <wicket:panel>
     <div wicket:id="container" class="realm-header">
       <div class="realm-label">
-        <label wicket:id="realmLabel"/>: <label wicket:id="realm"/> 
+        <label wicket:id="realmDisplayKey"/>: <label wicket:id="realmDisplayValue"/>
       </div>
       <span wicket:id="realmsFragment"></span>
 
diff --git a/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
index 1361304553..ef3deee89b 100644
--- a/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
+++ b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
@@ -627,7 +627,7 @@ public class ReconciliationLogic extends AbstractTransactionalLogic<EntityTO> {
                 csvSchema(spec),
                 null,
                 os,
-                columns.toArray(new String[columns.size()]))) {
+                columns.toArray(String[]::new))) {
 
             SyncopeStreamPushExecutor executor =
                     (SyncopeStreamPushExecutor) ApplicationContextProvider.getBeanFactory().
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
index 43df9c9f6f..df5593da37 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
@@ -310,8 +310,7 @@ public class RealmDataBinderImpl implements RealmDataBinder {
         if (admin) {
             realmTO.setAccountPolicy(realm.getAccountPolicy() == null ? null : realm.getAccountPolicy().getKey());
             realmTO.setPasswordPolicy(realm.getPasswordPolicy() == null ? null : realm.getPasswordPolicy().getKey());
-            realmTO.setAuthPolicy(
-                    realm.getAuthPolicy() == null ? null : realm.getAuthPolicy().getKey());
+            realmTO.setAuthPolicy(realm.getAuthPolicy() == null ? null : realm.getAuthPolicy().getKey());
             realmTO.setAccessPolicy(realm.getAccessPolicy() == null ? null : realm.getAccessPolicy().getKey());
             realmTO.setAttrReleasePolicy(
                     realm.getAttrReleasePolicy() == null ? null : realm.getAttrReleasePolicy().getKey());
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java
index a77eae8cd9..47ee9853ab 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java
@@ -73,7 +73,7 @@ public class RealmsITCase extends AbstractConsoleITCase {
                 "body:content:realmChoicePanel:container:realmsFragment:realms:dropdown-menu:buttons:5:button",
                 Constants.ON_CLICK);
 
-        TESTER.assertLabel("body:content:realmChoicePanel:container:realm", "/testRealm");
+        TESTER.assertLabel("body:content:realmChoicePanel:container:realmDisplayValue", "/testRealm");
 
         TESTER.getRequest().addParameter("confirm", "true");
         TESTER.clickLink(
@@ -86,7 +86,7 @@ public class RealmsITCase extends AbstractConsoleITCase {
                 "body:content:body:container:content:tabbedPanel:panel:container:policies:1:field-label",
                 "Account Policy");
 
-        TESTER.assertLabel("body:content:realmChoicePanel:container:realm", "/");
+        TESTER.assertLabel("body:content:realmChoicePanel:container:realmDisplayValue", "/");
     }
 
     @Test
@@ -116,7 +116,7 @@ public class RealmsITCase extends AbstractConsoleITCase {
                 "body:content:realmChoicePanel:container:realmsFragment:realms:dropdown-menu:buttons:4:button",
                 Constants.ON_CLICK);
 
-        TESTER.assertLabel("body:content:realmChoicePanel:container:realm", "/odd");
+        TESTER.assertLabel("body:content:realmChoicePanel:container:realmDisplayValue", "/odd");
 
         TESTER.clickLink(
                 "body:content:body:container:content:tabbedPanel:panel:actions:actions:actionRepeater:2:action:action");
@@ -136,7 +136,7 @@ public class RealmsITCase extends AbstractConsoleITCase {
         assertSuccessMessage();
         TESTER.cleanupFeedbackMessages();
 
-        TESTER.assertLabel("body:content:realmChoicePanel:container:realm", "/odd");
+        TESTER.assertLabel("body:content:realmChoicePanel:container:realmDisplayValue", "/odd");
 
         TESTER.clickLink(
                 "body:content:body:container:content:tabbedPanel:panel:actions:actions:actionRepeater:2:action:action");