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
commit 87829a692a3c8457943cc4156263a565244434e6 Author: Francesco Chicchiriccò <[email protected]> AuthorDate: Thu May 26 13:22:41 2022 +0200 Further Console extendability improvements --- .../client/console/panels/RealmChoicePanel.java | 75 ++++++++---- .../client/console/rest/RealmRestClient.java | 9 +- .../client/console/status/ReconTaskPanel.java | 2 +- .../console/tasks/SchedTaskWizardBuilder.java | 2 +- .../client/console/widgets/NumberWidget.java | 21 ++-- .../client/console/wizards/any/Details.java | 3 +- .../syncope/client/console/wizards/any/Groups.java | 15 +-- .../client/console/wizards/any/Relationships.java | 128 ++++++++++++--------- .../wizards/resources/ConnectorDetailsPanel.java | 3 +- .../console/wizards/role/RoleWizardBuilder.java | 3 +- .../client/console/panels/RealmChoicePanel.html | 6 +- .../apache/syncope/fit/console/RealmsITCase.java | 14 ++- .../workingwithapachesyncope/customization.adoc | 4 +- 13 files changed, 172 insertions(+), 113 deletions(-) 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 d3fa22ab26..11dedd50a2 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 @@ -25,6 +25,7 @@ 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.extensions.markup.html.bootstrap.icon.FontAwesome5IconType; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -48,6 +49,7 @@ import org.apache.syncope.common.lib.to.RealmTO; import org.apache.syncope.common.lib.types.StandardEntitlement; import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy; import org.apache.wicket.event.Broadcast; import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AbstractAutoCompleteRenderer; @@ -56,11 +58,11 @@ import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteSe import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField; import org.apache.wicket.extensions.ajax.markup.html.autocomplete.IAutoCompleteRenderer; import org.apache.wicket.markup.ComponentTag; -import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.link.AbstractLink; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; 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; @@ -94,9 +96,7 @@ public class RealmChoicePanel extends Panel { protected final boolean isSearchEnabled; - protected final Label realmDisplayKey; - - protected final Label realmDisplayValue; + protected final ListView<String> breadcrumb; public RealmChoicePanel(final String id, final String initialRealm, final PageReference pageRef) { super(id); @@ -172,33 +172,60 @@ public class RealmChoicePanel extends Panel { container = new WebMarkupContainerNoVeil("container", realmTree); 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)); + breadcrumb = new ListView<String>("breadcrumb") { + + private static final long serialVersionUID = -8746795666847966508L; + + @Override + protected void populateItem(final ListItem<String> item) { + AjaxLink<Void> bcitem = new AjaxLink<Void>("bcitem") { + + private static final long serialVersionUID = -817438685948164787L; + + @Override + public void onClick(final AjaxRequestTarget target) { + realmRestClient.list(item.getModelObject()).stream(). + filter(r -> item.getModelObject().equals(r.getFullPath())). + findFirst().ifPresent(t -> chooseRealm(t, target)); + } + }; + bcitem.setBody(Model.of(SyncopeConstants.ROOT_REALM.equals(item.getModelObject()) + ? SyncopeConstants.ROOT_REALM + : StringUtils.substringAfterLast(item.getModelObject(), "/"))); + bcitem.setEnabled(!model.getObject().getFullPath().equals(item.getModelObject())); + item.add(bcitem); + } + }; + container.addOrReplace(breadcrumb.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true)); + setBreadcrumb(model.getObject()); reloadRealmTree(); } - 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"); - } + protected void setBreadcrumb(final RealmTO realm) { + if (SyncopeConstants.ROOT_REALM.equals(realm.getFullPath())) { + breadcrumb.setList(Arrays.asList(realm.getFullPath())); + } else { + List<String> bcitems = new ArrayList<>(); + bcitems.add(SyncopeConstants.ROOT_REALM); + + String[] split = realm.getFullPath().split("/"); + for (int i = 1; i < split.length; i++) { + StringBuilder bcitem = new StringBuilder(); + for (int j = 1; j <= i; j++) { + bcitem.append('/').append(split[j]); + } + bcitems.add(bcitem.toString()); + } - protected String realmDisplayValueText() { - return RealmsUtils.getFullPath(model.getObject().getFullPath()); + breadcrumb.setList(bcitems); + } } protected void chooseRealm(final RealmTO realm, final AjaxRequestTarget target) { model.setObject(realm); - realmDisplayValue.setDefaultModelObject(realmDisplayValueText()); - realmDisplayKey.setDefaultModel(realmDisplayKeyModel(false)); - target.add(realmDisplayValue); + setBreadcrumb(realm); + target.add(container); send(pageRef.getPage(), Broadcast.EXACT, new ChosenRealm<>(realm, target)); } @@ -404,7 +431,7 @@ public class RealmChoicePanel extends Panel { protected Map<String, Pair<RealmTO, List<RealmTO>>> reloadRealmParentMap() { List<RealmTO> realmsToList = isSearchEnabled ? realmRestClient.search(RealmsUtils.buildQuery(searchQuery)).getResult() - : realmRestClient.list(); + : realmRestClient.list(SyncopeConstants.ROOT_REALM); return reloadRealmParentMap(realmsToList.stream(). sorted(Comparator.comparing(RealmTO::getName)). diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java index 8e1b5d7cfb..70ebcc7f0c 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java @@ -21,7 +21,6 @@ package org.apache.syncope.client.console.rest; import java.util.List; import javax.ws.rs.core.GenericType; import javax.ws.rs.core.Response; -import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.common.lib.to.DynRealmTO; import org.apache.syncope.common.lib.to.PagedResult; import org.apache.syncope.common.lib.to.ProvisioningResult; @@ -36,13 +35,13 @@ import org.apache.syncope.common.rest.api.service.RealmService; public class RealmRestClient extends BaseRestClient { private static final long serialVersionUID = -8549081557283519638L; - + public PagedResult<RealmTO> search(final RealmQuery query) { return getService(RealmService.class).search(query); } - - public List<RealmTO> list() { - return getService(RealmService.class).list(SyncopeConstants.ROOT_REALM); + + public List<RealmTO> list(final String fullpath) { + return getService(RealmService.class).list(fullpath); } public List<DynRealmTO> listDynRealms() { diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java index 89efaf202c..32c6b2fd6c 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java @@ -139,7 +139,7 @@ public class ReconTaskPanel extends MultilevelPanel.SecondLevel { return (RealmsUtils.checkInput(input) ? (isSearchEnabled ? realmRestClient.search(RealmsUtils.buildQuery(input)).getResult() - : realmRestClient.list()) + : realmRestClient.list(SyncopeConstants.ROOT_REALM)) : Collections.<RealmTO>emptyList()).stream(). sorted(Comparator.comparing(RealmTO::getName)). map(RealmTO::getFullPath).collect(Collectors.toList()).iterator(); diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java index c1927d7772..937bd2ba97 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java @@ -113,7 +113,7 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui private List<RealmTO> searchRealms(final String realmQuery) { return isSearchEnabled ? realmRestClient.search(RealmsUtils.buildQuery(realmQuery)).getResult() - : realmRestClient.list(); + : realmRestClient.list(SyncopeConstants.ROOT_REALM); } public class Profile extends WizardStep { diff --git a/client/console/src/main/java/org/apache/syncope/client/console/widgets/NumberWidget.java b/client/console/src/main/java/org/apache/syncope/client/console/widgets/NumberWidget.java index 425cec1460..caac674db7 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/widgets/NumberWidget.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/widgets/NumberWidget.java @@ -21,6 +21,7 @@ package org.apache.syncope.client.console.widgets; import java.util.List; import org.apache.syncope.client.console.SyncopeConsoleApplication; import org.apache.syncope.client.console.SyncopeConsoleSession; +import org.apache.syncope.client.console.pages.BasePage; import org.apache.syncope.client.console.rest.AnyTypeRestClient; import org.apache.syncope.client.console.topology.TabularTopology; import org.apache.wicket.behavior.AttributeAppender; @@ -32,7 +33,6 @@ import org.apache.syncope.client.console.pages.Realms; import org.apache.syncope.client.console.pages.Security; import org.apache.syncope.client.console.topology.Topology; import org.apache.syncope.common.lib.types.StandardEntitlement; -import org.apache.wicket.request.component.IRequestablePage; import org.apache.wicket.request.mapper.parameter.PageParameters; public class NumberWidget extends BaseWidget { @@ -51,20 +51,27 @@ public class NumberWidget extends BaseWidget { WebMarkupContainer box = new WebMarkupContainer("box"); box.add(new AttributeAppender("class", " " + bg)); + @SuppressWarnings("unchecked") + Class<? extends BasePage> realmsPage = + (Class<? extends BasePage>) SyncopeConsoleApplication.get().getPageClass("realms"); + if (realmsPage == null) { + realmsPage = Realms.class; + } + boolean isAuthorized = true; - final PageParameters pageParameters = new PageParameters(); - final Class<? extends IRequestablePage> responsePage; + PageParameters pageParameters = new PageParameters(); + Class<? extends BasePage> responsePage; List<String> anyTypes = new AnyTypeRestClient().list(); switch (id) { case "totalUsers": pageParameters.add(Realms.SELECTED_INDEX, 1); - responsePage = Realms.class; + responsePage = realmsPage; isAuthorized = SyncopeConsoleSession.get().owns(StandardEntitlement.USER_SEARCH); break; case "totalGroups": pageParameters.add(Realms.SELECTED_INDEX, 2); - responsePage = Realms.class; + responsePage = realmsPage; isAuthorized = SyncopeConsoleSession.get().owns(StandardEntitlement.GROUP_SEARCH); break; @@ -77,7 +84,7 @@ public class NumberWidget extends BaseWidget { pageParameters.add(Realms.SELECTED_INDEX, selectedIndex); } } - responsePage = Realms.class; + responsePage = realmsPage; isAuthorized = SyncopeConsoleSession.get().owns(label + "_SEARCH"); } else { responsePage = Security.class; @@ -109,7 +116,7 @@ public class NumberWidget extends BaseWidget { default: pageParameters.add(Realms.SELECTED_INDEX, 0); - responsePage = Realms.class; + responsePage = realmsPage; } AjaxEventBehavior clickToRealms = new AjaxEventBehavior("mousedown") { diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java index 27039c3576..c7411ae647 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java @@ -29,6 +29,7 @@ import org.apache.syncope.client.console.rest.RealmRestClient; import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSearchFieldPanel; import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel; import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel; +import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.common.lib.to.AnyTO; import org.apache.syncope.common.lib.to.RealmTO; import org.apache.wicket.Component; @@ -86,7 +87,7 @@ public class Details<T extends AnyTO> extends WizardStep { ? realmRestClient.search(RealmsUtils.buildQuery(input)).getResult() : pageRef.getPage() instanceof Realms ? getRealmsFromLinks(Realms.class.cast(pageRef.getPage()).getRealmChoicePanel().getLinks()) - : realmRestClient.list()). + : realmRestClient.list(SyncopeConstants.ROOT_REALM)). stream().filter(realm -> authRealms.stream().anyMatch( authRealm -> realm.getFullPath().startsWith(authRealm))). map(item -> item.getFullPath()).collect(Collectors.toList()).iterator(); diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java index 347c92c3c2..8038828dfa 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java @@ -87,6 +87,10 @@ public class Groups extends AbstractGroups { addDynamicRealmsContainer(); } + protected List<GroupTO> searchAssignable(final String realm, final String term) { + return syncopeRestClient.searchAssignableGroups(realm, term, 1, Constants.MAX_GROUP_LIST_SIZE); + } + @Override protected void addGroupsPanel() { if (anyTO instanceof GroupTO) { @@ -128,7 +132,6 @@ public class Groups extends AbstractGroups { public List<MembershipTO> getObject() { return Groups.this.groupsModel.getMemberships(); } - }, new AjaxPalettePanel.Builder.Query<MembershipTO>() { private static final long serialVersionUID = -7223078772249308813L; @@ -139,8 +142,7 @@ public class Groups extends AbstractGroups { ? Collections.emptyList() : ("*".equals(filter) ? groupsModel.getObject() - : syncopeRestClient.searchAssignableGroups( - anyTO.getRealm(), filter, 1, Constants.MAX_GROUP_LIST_SIZE)).stream(). + : searchAssignable(anyTO.getRealm(), filter)).stream(). map(group -> new MembershipTO.Builder(). group(group.getKey(), group.getName()).build()). collect(Collectors.toList()); @@ -156,7 +158,6 @@ public class Groups extends AbstractGroups { public List<String> getObject() { return Groups.this.groupsModel.getDynMemberships(); } - }, new ListModel<>(groupsModel.getObject().stream().map(GroupTO::getName).collect(Collectors.toList()))). hideLabel().setEnabled(false).setOutputMarkupId(true)); } @@ -213,11 +214,7 @@ public class Groups extends AbstractGroups { * Retrieve the first MAX_GROUP_LIST_SIZE assignable. */ protected void reloadObject() { - groups = syncopeRestClient.searchAssignableGroups( - realm, - null, - 1, - Constants.MAX_GROUP_LIST_SIZE); + groups = searchAssignable(realm, null); } public List<MembershipTO> getMemberships() { diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java index 967e4904bc..46e5b3652c 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java @@ -81,15 +81,17 @@ public class Relationships extends WizardStep implements ICondition { private static final long serialVersionUID = 855618618337931784L; - private final PageReference pageRef; + protected final AnyTypeRestClient anyTypeRestClient = new AnyTypeRestClient(); - private final AnyTypeRestClient anyTypeRestClient = new AnyTypeRestClient(); + protected final AnyTypeClassRestClient anyTypeClassRestClient = new AnyTypeClassRestClient(); - private final AnyTypeClassRestClient anyTypeClassRestClient = new AnyTypeClassRestClient(); + protected final RelationshipTypeRestClient relationshipTypeRestClient = new RelationshipTypeRestClient(); - private final AnyTO anyTO; + protected final AnyTO anyTO; - private final RelationshipTypeRestClient relationshipTypeRestClient = new RelationshipTypeRestClient(); + protected final Specification specification; + + protected final PageReference pageRef; public Relationships(final AnyWrapper<?> modelObject, final PageReference pageRef) { super(); @@ -106,6 +108,7 @@ public class Relationships extends WizardStep implements ICondition { } this.anyTO = modelObject.getInnerObject(); + this.specification = new Specification(); this.pageRef = pageRef; // ------------------------ @@ -120,11 +123,11 @@ public class Relationships extends WizardStep implements ICondition { return super.getHeader(id, parent, wizard).setVisible(false); } - private Fragment getViewFragment() { - final Map<String, List<RelationshipTO>> relationships = new HashMap<>(); + protected Fragment getViewFragment() { + Map<String, List<RelationshipTO>> relationships = new HashMap<>(); addRelationship(relationships, getCurrentRelationships().toArray(new RelationshipTO[] {})); - final Fragment viewFragment = new Fragment("relationships", "viewFragment", this); + Fragment viewFragment = new Fragment("relationships", "viewFragment", this); viewFragment.setOutputMarkupId(true); viewFragment.add(new Accordion("relationships", relationships.keySet().stream().map(relationship -> { @@ -164,7 +167,7 @@ public class Relationships extends WizardStep implements ICondition { } }); - final ActionsPanel<RelationshipTO> panel = new ActionsPanel<>("actions", null); + ActionsPanel<RelationshipTO> panel = new ActionsPanel<>("actions", null); viewFragment.add(panel); panel.add(new ActionLink<RelationshipTO>() { @@ -175,7 +178,7 @@ public class Relationships extends WizardStep implements ICondition { public void onClick(final AjaxRequestTarget target, final RelationshipTO ignore) { Fragment addFragment = new Fragment("relationships", "addFragment", Relationships.this); addOrReplace(addFragment); - addFragment.add(new Specification().setRenderBodyOnly(true)); + addFragment.add(specification.setRenderBodyOnly(true)); target.add(Relationships.this); } }, ActionType.CREATE, AnyEntitlement.UPDATE.getFor(anyTO.getType())).hideLabel(); @@ -183,16 +186,18 @@ public class Relationships extends WizardStep implements ICondition { return viewFragment; } - private List<RelationshipTO> getCurrentRelationships() { + protected List<RelationshipTO> getCurrentRelationships() { return anyTO instanceof GroupableRelatableTO ? GroupableRelatableTO.class.cast(anyTO).getRelationships() : Collections.<RelationshipTO>emptyList(); } - private void addRelationship(final Map<String, List<RelationshipTO>> relationships, final RelationshipTO... rels) { + protected void addRelationship( + final Map<String, List<RelationshipTO>> relationships, + final RelationshipTO... rels) { for (RelationshipTO relationship : rels) { - final List<RelationshipTO> listrels; + List<RelationshipTO> listrels; if (relationships.containsKey(relationship.getType())) { listrels = relationships.get(relationship.getType()); } else { @@ -203,17 +208,18 @@ public class Relationships extends WizardStep implements ICondition { } } - private void addNewRelationships(final RelationshipTO... rels) { + protected void addNewRelationships(final RelationshipTO... rels) { getCurrentRelationships().addAll(Arrays.asList(rels)); } - private void removeRelationships( + protected void removeRelationships( final Map<String, List<RelationshipTO>> relationships, final RelationshipTO... rels) { - final List<RelationshipTO> currentRels = getCurrentRelationships(); + + List<RelationshipTO> currentRels = getCurrentRelationships(); for (RelationshipTO relationship : rels) { currentRels.remove(relationship); if (relationships.containsKey(relationship.getType())) { - final List<RelationshipTO> rellist = relationships.get(relationship.getType()); + List<RelationshipTO> rellist = relationships.get(relationship.getType()); rellist.remove(relationship); if (rellist.isEmpty()) { relationships.remove(relationship.getType()); @@ -232,29 +238,38 @@ public class Relationships extends WizardStep implements ICondition { private static final long serialVersionUID = 6199050589175839467L; - private final RelationshipTO rel; + protected final RelationshipTO rel; + + protected final AjaxDropDownChoicePanel<String> type; + + protected final AjaxDropDownChoicePanel<AnyTypeTO> otherType; + + protected final WebMarkupContainer container; + + protected final Fragment emptyFragment; - private AnyObjectSearchPanel anyObjectSearchPanel; + protected final Fragment fragment; - private WizardMgtPanel<AnyWrapper<AnyObjectTO>> anyObjectDirectoryPanel; + protected AnyObjectSearchPanel anyObjectSearchPanel; + + protected WizardMgtPanel<AnyWrapper<AnyObjectTO>> anyObjectDirectoryPanel; public Specification() { super("specification"); rel = new RelationshipTO(); - final List<String> availableRels = relationshipTypeRestClient.list().stream(). + List<String> availableRels = relationshipTypeRestClient.list().stream(). map(EntityTO::getKey).collect(Collectors.toList()); - final AjaxDropDownChoicePanel<String> type = new AjaxDropDownChoicePanel<>( - "type", "type", new PropertyModel<>(rel, "type")); + type = new AjaxDropDownChoicePanel<>("type", "type", new PropertyModel<>(rel, "type")); type.setChoices(availableRels); - add(type.setRenderBodyOnly(true)); + add(type.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true).setRenderBodyOnly(true)); - final List<AnyTypeTO> availableTypes = anyTypeRestClient.listAnyTypes().stream(). + List<AnyTypeTO> availableTypes = anyTypeRestClient.listAnyTypes().stream(). filter(anyType -> anyType.getKind() != AnyTypeKind.GROUP && anyType.getKind() != AnyTypeKind.USER).collect(Collectors.toList()); - final AjaxDropDownChoicePanel<AnyTypeTO> otherType = new AjaxDropDownChoicePanel<>( + otherType = new AjaxDropDownChoicePanel<>( "otherType", "otherType", new PropertyModel<AnyTypeTO>(rel, "otherType") { private static final long serialVersionUID = -5861057041758169508L; @@ -297,22 +312,22 @@ public class Relationships extends WizardStep implements ICondition { }); // enable "otherType" dropdown only if "type" option is selected - SYNCOPE-1140 otherType.setEnabled(false); - add(otherType); + add(otherType.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true)); - final WebMarkupContainer container = new WebMarkupContainer("searchPanelContainer"); - container.setOutputMarkupId(true); - add(container); + container = new WebMarkupContainer("searchPanelContainer"); + add(container.setOutputMarkupId(true)); - Fragment emptyFragment = new Fragment("searchPanel", "emptyFragment", this); + emptyFragment = new Fragment("searchPanel", "emptyFragment", this); container.add(emptyFragment.setRenderBodyOnly(true)); + fragment = new Fragment("searchPanel", "searchFragment", Specification.this); + type.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { private static final long serialVersionUID = -1107858522700306810L; @Override protected void onUpdate(final AjaxRequestTarget target) { - Fragment emptyFragment = new Fragment("searchPanel", "emptyFragment", Specification.this); container.addOrReplace(emptyFragment.setRenderBodyOnly(true)); otherType.setModelObject(null); // enable "otherType" dropdown only if "type" option is selected - SYNCOPE-1140 @@ -328,46 +343,47 @@ public class Relationships extends WizardStep implements ICondition { @Override protected void onUpdate(final AjaxRequestTarget target) { - final AnyTypeTO anyType = otherType.getModelObject(); + AnyTypeTO anyType = otherType.getModelObject(); if (anyType == null) { - Fragment emptyFragment = new Fragment("searchPanel", "emptyFragment", Specification.this); container.addOrReplace(emptyFragment.setRenderBodyOnly(true)); } else { - final Fragment fragment = new Fragment("searchPanel", "searchFragment", Specification.this); + setupFragment(anyType); container.addOrReplace(fragment.setRenderBodyOnly(true)); - - anyObjectSearchPanel = new AnyObjectSearchPanel.Builder( - anyType.getKey(), - new ListModel<>(new ArrayList<>())). - enableSearch(Specification.this). - build("searchPanel"); - fragment.add(anyObjectSearchPanel.setRenderBodyOnly(true)); - - anyObjectDirectoryPanel = new AnyObjectSelectionDirectoryPanel.Builder( - anyTypeClassRestClient.list(anyType.getClasses()), - anyType.getKey(), - pageRef). - setFiql(SyncopeClient.getAnyObjectSearchConditionBuilder(anyType.getKey()). - is(Constants.KEY_FIELD_NAME).notNullValue().query()). - setWizardInModal(true).build("searchResultPanel"); - fragment.add(anyObjectDirectoryPanel.setRenderBodyOnly(true)); } target.add(container); } }); } + protected void setupFragment(final AnyTypeTO anyType) { + anyObjectSearchPanel = new AnyObjectSearchPanel.Builder( + anyType.getKey(), + new ListModel<>(new ArrayList<>())). + enableSearch(Specification.this). + build("searchPanel"); + fragment.addOrReplace(anyObjectSearchPanel.setRenderBodyOnly(true)); + + anyObjectDirectoryPanel = new AnyObjectSelectionDirectoryPanel.Builder( + anyTypeClassRestClient.list(anyType.getClasses()), + anyType.getKey(), + pageRef). + setFiql(SyncopeClient.getAnyObjectSearchConditionBuilder(anyType.getKey()). + is(Constants.KEY_FIELD_NAME).notNullValue().query()). + setWizardInModal(true).build("searchResultPanel"); + fragment.addOrReplace(anyObjectDirectoryPanel.setRenderBodyOnly(true)); + } + @Override public void onEvent(final IEvent<?> event) { if (event.getPayload() instanceof SearchClausePanel.SearchEvent) { - final AjaxRequestTarget target = SearchClausePanel.SearchEvent.class.cast(event.getPayload()). - getTarget(); - final String fiql = SearchUtils.buildFIQL(anyObjectSearchPanel.getModel().getObject(), + AjaxRequestTarget target = + SearchClausePanel.SearchEvent.class.cast(event.getPayload()).getTarget(); + String fiql = SearchUtils.buildFIQL(anyObjectSearchPanel.getModel().getObject(), SyncopeClient.getAnyObjectSearchConditionBuilder(anyObjectSearchPanel.getBackObjectType())); AnyDirectoryPanel.class.cast(Specification.this.anyObjectDirectoryPanel).search(fiql, target); } else if (event.getPayload() instanceof AnySelectionDirectoryPanel.ItemSelection) { - final AjaxRequestTarget target = AnySelectionDirectoryPanel.ItemSelection.class.cast(event. - getPayload()).getTarget(); + AjaxRequestTarget target = + AnySelectionDirectoryPanel.ItemSelection.class.cast(event.getPayload()).getTarget(); AnyTO right = AnySelectionDirectoryPanel.ItemSelection.class.cast(event.getPayload()).getSelection(); rel.setOtherEndKey(right.getKey()); diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java index 2471b162e0..de5932887d 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java @@ -33,6 +33,7 @@ import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownCho import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSearchFieldPanel; import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSpinnerFieldPanel; import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel; +import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.common.lib.to.ConnBundleTO; import org.apache.syncope.common.lib.to.ConnInstanceTO; import org.apache.syncope.common.lib.to.ConnPoolConfTO; @@ -66,7 +67,7 @@ public class ConnectorDetailsPanel extends WizardStep { protected Iterator<String> getChoices(final String input) { return (isSearchEnabled ? realmRestClient.search(RealmsUtils.buildQuery(input)).getResult() - : realmRestClient.list()). + : realmRestClient.list(SyncopeConstants.ROOT_REALM)). stream().filter(realm -> SyncopeConsoleSession.get().getAuthRealms().stream().anyMatch( authRealm -> realm.getFullPath().startsWith(authRealm))). map(item -> item.getFullPath()).collect(Collectors.toList()).iterator(); diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/role/RoleWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/role/RoleWizardBuilder.java index 8df8cddccf..1d274da1c2 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/role/RoleWizardBuilder.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/role/RoleWizardBuilder.java @@ -34,6 +34,7 @@ import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accor import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel; import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel; import org.apache.syncope.client.console.wizards.AjaxWizardBuilder; +import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.common.lib.to.EntityTO; import org.apache.syncope.common.lib.to.RealmTO; import org.apache.syncope.common.lib.to.RoleTO; @@ -165,7 +166,7 @@ public class RoleWizardBuilder extends AjaxWizardBuilder<RoleWrapper> { setTitleModel(new ResourceModel("realms")); add(new AjaxPalettePanel.Builder<>().build("realms", new PropertyModel<>(modelObject, "realms"), - new ListModel<>(new RealmRestClient().list().stream(). + new ListModel<>(new RealmRestClient().list(SyncopeConstants.ROOT_REALM).stream(). map(RealmTO::getFullPath).collect(Collectors.toList()))). hideLabel().setOutputMarkupId(true)); } diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html index bfbb60600e..73d57b0044 100644 --- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html +++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html @@ -20,7 +20,11 @@ under the License. <wicket:panel> <div wicket:id="container" class="realm-header"> <div class="realm-label"> - <label wicket:id="realmDisplayKey"/>: <label wicket:id="realmDisplayValue"/> + <nav aria-label="breadcrumb"> + <ol class="breadcrumb"> + <li class="breadcrumb-item" wicket:id="breadcrumb"><a wicket:id="bcitem"/></li> + </ol> + </nav> </div> <span wicket:id="realmsFragment"></span> 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 f89c96686f..34a3a740f8 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 @@ -18,7 +18,9 @@ */ package org.apache.syncope.fit.console; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal; import org.apache.syncope.client.console.commons.Constants; @@ -69,7 +71,8 @@ public class RealmsITCase extends AbstractConsoleITCase { TESTER.executeAjaxEvent("body:content:realmChoicePanel:container:realmsFragment:realms:dropdown-menu:buttons:5:button", Constants.ON_CLICK); - TESTER.assertLabel("body:content:realmChoicePanel:container:realmDisplayValue", "/testRealm"); + assertTrue(TESTER.getLastResponseAsString().contains(">/</a>")); + assertTrue(TESTER.getLastResponseAsString().contains(">testRealm</a>")); TESTER.getRequest().addParameter("confirm", "true"); TESTER.clickLink( @@ -81,7 +84,8 @@ public class RealmsITCase extends AbstractConsoleITCase { TESTER.assertLabel("body:content:body:container:content:tabbedPanel:panel:container:accountPolicy:field-label", "Account Policy"); - TESTER.assertLabel("body:content:realmChoicePanel:container:realmDisplayValue", "/"); + assertTrue(TESTER.getLastResponseAsString().contains(">/</a>")); + assertFalse(TESTER.getLastResponseAsString().contains(">testRealm</a>")); } @Test @@ -107,7 +111,8 @@ public class RealmsITCase extends AbstractConsoleITCase { TESTER.executeAjaxEvent("body:content:realmChoicePanel:container:realmsFragment:realms:dropdown-menu:buttons:4:button", Constants.ON_CLICK); - TESTER.assertLabel("body:content:realmChoicePanel:container:realmDisplayValue", "/odd"); + assertTrue(TESTER.getLastResponseAsString().contains(">/</a>")); + assertTrue(TESTER.getLastResponseAsString().contains(">odd</a>")); TESTER.clickLink( "body:content:body:container:content:tabbedPanel:panel:actions:actions:actionRepeater:2:action:action"); @@ -127,7 +132,8 @@ public class RealmsITCase extends AbstractConsoleITCase { assertSuccessMessage(); TESTER.cleanupFeedbackMessages(); - TESTER.assertLabel("body:content:realmChoicePanel:container:realmDisplayValue", "/odd"); + assertTrue(TESTER.getLastResponseAsString().contains(">/</a>")); + assertTrue(TESTER.getLastResponseAsString().contains(">odd</a>")); TESTER.clickLink( "body:content:body:container:content:tabbedPanel:panel:actions:actions:actionRepeater:2:action:action"); diff --git a/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc b/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc index f16bf420ae..d38ee26bf1 100644 --- a/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc +++ b/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc @@ -33,11 +33,11 @@ adding new features or replacing existing components. .Override behavior **** As a rule of thumb, any file of the local project will take precedence over a file with the same name in the same -directory of the standard Apache Syncope release. +package directory of the standard Apache Syncope release. For example, if you place - core/spring/src/main/java/org/apache/syncope/core/spring/security/SyncopeAuthenticationProvider.java + core/src/main/java/org/apache/syncope/core/spring/security/SyncopeAuthenticationProvider.java in the local project, this file will be picked up instead of ifeval::["{snapshotOrRelease}" == "release"]
