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/26 11:55:04 UTC
[syncope] 02/02: Further Console extendability improvements
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ò <il...@apache.org>
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"]