This is an automated email from the ASF dual-hosted git repository. ilgrosso pushed a commit to branch 2_1_X in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/2_1_X by this push: new d80301b [SYNCOPE-1500] Allow single import from External Resource (#137) d80301b is described below commit d80301b5ef40ae053d2cb245cf3ac8c5108e7f05 Author: Federico Palmitesta <federico.palmite...@gmail.com> AuthorDate: Thu Oct 31 14:14:20 2019 +0100 [SYNCOPE-1500] Allow single import from External Resource (#137) --- .../client/console/commons/status/StatusUtils.java | 4 +- .../console/panels/ConnObjectListViewPanel.java | 87 ++++++++++++++++++++-- .../syncope/client/console/panels/ConnObjects.java | 27 +++++++ .../console/status/AnyStatusDirectoryPanel.java | 2 + .../client/console/status/ReconTaskPanel.java | 52 +++++++++++-- .../status/ResourceStatusDirectoryPanel.java | 2 + .../META-INF/resources/css/syncopeConsole.css | 6 +- .../client/console/panels/ListViewPanel.html | 2 +- .../client/console/status/ReconTaskPanel.html | 1 + .../provisioning/java/utils/ConnObjectUtils.java | 8 +- 10 files changed, 175 insertions(+), 16 deletions(-) diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java index 14a98cc..4115ad0 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java @@ -173,7 +173,7 @@ public final class StatusUtils implements Serializable { case CREATED: alt = "created icon"; title = "Created"; - clazz = Constants.UNDEFINED_ICON; + clazz = Constants.CREATED_ICON; break; case SUSPENDED: @@ -235,7 +235,7 @@ public final class StatusUtils implements Serializable { return getLabel(componentId, alt, title, clazz); } - private static Label getLabel(final String componentId, final String alt, final String title, final String clazz) { + public static Label getLabel(final String componentId, final String alt, final String title, final String clazz) { return new Label(componentId, StringUtils.EMPTY) { private static final long serialVersionUID = 4755868673082976208L; diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectListViewPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectListViewPanel.java index bcff482..32925c4 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectListViewPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectListViewPanel.java @@ -18,6 +18,9 @@ */ package org.apache.syncope.client.console.panels; +import de.agilecoders.wicket.core.markup.html.bootstrap.components.PopoverBehavior; +import de.agilecoders.wicket.core.markup.html.bootstrap.components.PopoverConfig; +import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipConfig; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; @@ -26,6 +29,8 @@ import java.util.Optional; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.syncope.client.console.commons.ConnIdSpecialName; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.status.StatusUtils; import org.apache.syncope.client.console.panels.ListViewPanel.ListViewReload; import org.apache.syncope.client.console.panels.search.AbstractSearchPanel; import org.apache.syncope.client.console.panels.search.ConnObjectSearchPanel; @@ -33,6 +38,7 @@ import org.apache.syncope.client.console.panels.search.SearchClause; import org.apache.syncope.client.console.panels.search.SearchClausePanel; import org.apache.syncope.client.console.panels.search.SearchUtils; import org.apache.syncope.client.console.rest.AnyTypeRestClient; +import org.apache.syncope.client.console.rest.ReconciliationRestClient; import org.apache.syncope.client.console.rest.ResourceRestClient; import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.CollectionPanel; import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink; @@ -41,10 +47,13 @@ import org.apache.syncope.common.lib.to.ConnObjectTO; import org.apache.syncope.client.console.wicket.markup.html.bootstrap.tabs.Accordion; import org.apache.syncope.client.lib.SyncopeClient; import org.apache.syncope.common.lib.SyncopeConstants; +import org.apache.syncope.common.lib.to.ReconStatus; import org.apache.syncope.common.lib.to.ResourceTO; import org.apache.syncope.common.lib.types.AnyTypeKind; +import org.apache.syncope.common.lib.types.MatchType; import org.apache.syncope.common.lib.types.StandardEntitlement; import org.apache.syncope.common.rest.api.beans.ConnObjectTOQuery; +import org.apache.syncope.common.rest.api.beans.ReconQuery; import org.apache.wicket.Component; import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -68,8 +77,12 @@ public abstract class ConnObjectListViewPanel extends Panel { private final AnyTypeRestClient anyTypeRestClient = new AnyTypeRestClient(); + private final ReconciliationRestClient reconRestClient = new ReconciliationRestClient(); + private static final int SIZE = 10; + private static final String STATUS = "Status"; + private String nextPageCookie; private AbstractSearchPanel searchPanel; @@ -140,12 +153,42 @@ public abstract class ConnObjectListViewPanel extends Panel { @Override protected Component getValueComponent(final String key, final ConnObjectTO bean) { - Optional<AttrTO> attrTO = - bean.getAttrs().stream().filter(object -> object.getSchema().equals(key)).findAny(); - - return !attrTO.isPresent() || attrTO.get().getValues().isEmpty() - ? new Label("field", StringUtils.EMPTY) - : new CollectionPanel("field", attrTO.get().getValues()); + if (StringUtils.equals(key, STATUS)) { + ReconStatus status = reconRestClient.status(new ReconQuery.Builder(anyType, resource.getKey()). + connObjectKeyValue(bean.getAttr(ConnIdSpecialName.UID).get().getValues().get(0)).build()); + + return status.getOnSyncope() == null + ? StatusUtils.getLabel("field", "notfound icon", "Not found", Constants.NOT_FOUND_ICON) + : new Label("field", Model.of()).add(new PopoverBehavior( + Model.<String>of(), + Model.of(status.getAnyKey()), + new PopoverConfig(). + withTitle(status.getMatchType() == MatchType.LINKED_ACCOUNT + ? MatchType.LINKED_ACCOUNT.name() + ", " + AnyTypeKind.USER + : status.getAnyTypeKind().name()). + withPlacement(TooltipConfig.Placement.left)) { + + private static final long serialVersionUID = -7867802555691605021L; + + @Override + protected String createRelAttribute() { + return "field"; + } + + @Override + public void onComponentTag(Component component, ComponentTag tag) { + super.onComponentTag(component, tag); + tag.put("class", Constants.ACTIVE_ICON); + } + }); + } else { + Optional<AttrTO> attrTO = + bean.getAttrs().stream().filter(object -> object.getSchema().equals(key)).findAny(); + + return !attrTO.isPresent() || attrTO.get().getValues().isEmpty() + ? new Label("field", StringUtils.EMPTY) + : new CollectionPanel("field", attrTO.get().getValues()); + } } }; @@ -167,6 +210,30 @@ public abstract class ConnObjectListViewPanel extends Panel { withChecks(ListViewPanel.CheckAvailability.NONE). setReuseItem(false); + if (!StringUtils.equals(anyType, SyncopeConstants.REALM_ANYTYPE)) { + builder.addAction(new ActionLink<ConnObjectTO>() { + + private static final long serialVersionUID = 6377238742125L; + + @Override + public void onClick(final AjaxRequestTarget target, final ConnObjectTO modelObject) { + String connObjectKeyValue = modelObject.getAttr(ConnIdSpecialName.UID).get().getValues().get(0); + String anyKey = reconRestClient.status(new ReconQuery.Builder(anyType, resource.getKey()). + connObjectKeyValue(connObjectKeyValue).build()).getAnyKey(); + + pullConnObject( + connObjectKeyValue, + target, + resource.getKey(), + anyType, + StringUtils.isNotBlank(anyKey), + pageRef); + } + }, ActionLink.ActionType.RECONCILIATION_PULL, StandardEntitlement.TASK_EXECUTE); + + builder.includes(STATUS); + } + add(builder.build("objs")); arrows = new WebMarkupContainer("arrows"); @@ -208,6 +275,14 @@ public abstract class ConnObjectListViewPanel extends Panel { protected abstract void viewConnObject(ConnObjectTO connObjectTO, AjaxRequestTarget target); + protected abstract void pullConnObject( + String connObjectTO, + AjaxRequestTarget target, + String resource, + String anyType, + boolean isOnSyncope, + PageReference pageRef); + private List<ConnObjectTO> reloadItems( final String resource, final String anyType, diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjects.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjects.java index 8f70d26a..2ccbd7a 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjects.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjects.java @@ -22,11 +22,13 @@ import java.util.List; import java.util.stream.Collectors; import org.apache.syncope.client.console.commons.Constants; import org.apache.syncope.client.console.rest.AnyTypeRestClient; +import org.apache.syncope.client.console.status.ReconTaskPanel; import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal; import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel; import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.common.lib.to.ConnObjectTO; import org.apache.syncope.common.lib.to.ProvisionTO; +import org.apache.syncope.common.lib.to.PullTaskTO; import org.apache.syncope.common.lib.to.ResourceTO; import org.apache.syncope.common.lib.types.AnyTypeKind; import org.apache.wicket.PageReference; @@ -123,5 +125,30 @@ public class ConnObjects extends Panel implements ModalPanel { target); } + @Override + protected void pullConnObject( + final String connObjectKeyValue, + final AjaxRequestTarget target, + final String resource, + final String anyType, + final boolean isOnSyncope, + final PageReference pageRef) { + anyTypes.setEnabled(false); + target.add(anyTypes); + + connObjects.next("PULL " + resource, + new ReconTaskPanel( + resource, + new PullTaskTO(), + anyType, + null, + connObjectKeyValue, + isOnSyncope, + connObjects, + pageRef), + target + ); + } + } } diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusDirectoryPanel.java index b876f33..81438b4 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusDirectoryPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/status/AnyStatusDirectoryPanel.java @@ -213,6 +213,7 @@ public class AnyStatusDirectoryPanel new PushTaskTO(), anyTO.getType(), anyTO.getKey(), + true, multiLevelPanelRef, pageRef), target); @@ -233,6 +234,7 @@ public class AnyStatusDirectoryPanel new PullTaskTO(), anyTO.getType(), anyTO.getKey(), + true, multiLevelPanelRef, pageRef), target); 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 fb778a6..0e4e4f3 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 @@ -19,6 +19,7 @@ package org.apache.syncope.client.console.status; import java.util.Arrays; +import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; @@ -27,14 +28,17 @@ import org.apache.syncope.client.console.commons.Constants; import org.apache.syncope.client.console.pages.BasePage; import org.apache.syncope.client.console.panels.MultilevelPanel; import org.apache.syncope.client.console.rest.ImplementationRestClient; +import org.apache.syncope.client.console.rest.RealmRestClient; import org.apache.syncope.client.console.rest.ReconciliationRestClient; import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel; import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel; import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel; +import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.common.lib.to.EntityTO; import org.apache.syncope.common.lib.to.ProvisioningTaskTO; import org.apache.syncope.common.lib.to.PullTaskTO; import org.apache.syncope.common.lib.to.PushTaskTO; +import org.apache.syncope.common.lib.to.RealmTO; import org.apache.syncope.common.lib.types.ImplementationType; import org.apache.syncope.common.lib.types.MatchingRule; import org.apache.syncope.common.lib.types.UnmatchingRule; @@ -42,6 +46,7 @@ import org.apache.syncope.common.rest.api.beans.ReconQuery; import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink; +import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.model.CompoundPropertyModel; import org.apache.wicket.model.IModel; @@ -57,10 +62,12 @@ public class ReconTaskPanel extends MultilevelPanel.SecondLevel { protected static final Logger LOG = LoggerFactory.getLogger(ReconTaskPanel.class); - private final ReconciliationRestClient restClient = new ReconciliationRestClient(); - private final ImplementationRestClient implRestClient = new ImplementationRestClient(); + private final RealmRestClient realmRestClient = new RealmRestClient(); + + private final ReconciliationRestClient reconRestClient = new ReconciliationRestClient(); + private final IModel<List<String>> pullActions = new LoadableDetachableModel<List<String>>() { private static final long serialVersionUID = 5275935387613157437L; @@ -88,12 +95,45 @@ public class ReconTaskPanel extends MultilevelPanel.SecondLevel { final ProvisioningTaskTO taskTO, final String anyType, final String anyKey, + final boolean isOnSyncope, + final MultilevelPanel multiLevelPanelRef, + final PageReference pageRef) { + this(resource, taskTO, anyType, anyKey, null, isOnSyncope, multiLevelPanelRef, pageRef); + } + + public ReconTaskPanel( + final String resource, + final ProvisioningTaskTO taskTO, + final String anyType, + final String anyKey, + final String connObjectKeyValue, + final boolean isOnSyncope, final MultilevelPanel multiLevelPanelRef, final PageReference pageRef) { Form<ProvisioningTaskTO> form = new Form<>("form", new CompoundPropertyModel<>(taskTO)); add(form); + if (taskTO instanceof PushTaskTO) { + form.add(new Label("realm", "")); + } else { + AjaxDropDownChoicePanel<String> realm = new AjaxDropDownChoicePanel<>( + "realm", "destinationRealm", new PropertyModel<>(taskTO, "destinationRealm"), false); + form.add(realm); + realm.addRequiredLabel(); + realm.setOutputMarkupId(true); + + if (isOnSyncope) { + realm.getField().setModelObject(SyncopeConstants.ROOT_REALM); + realm.setVisible(false); + } else { + realm.setChoices(realmRestClient.list().stream(). + sorted(Comparator.comparing(RealmTO::getName)). + map(RealmTO::getFullPath). + collect(Collectors.toList())); + } + } + AjaxPalettePanel<String> actions = new AjaxPalettePanel.Builder<String>(). setAllowMoveAll(true).setAllowOrder(true). build("actions", @@ -140,12 +180,14 @@ public class ReconTaskPanel extends MultilevelPanel.SecondLevel { @Override protected void onSubmit(final AjaxRequestTarget target) { - ReconQuery reconQuery = new ReconQuery.Builder(anyType, resource).anyKey(anyKey).build(); + ReconQuery reconQuery = new ReconQuery.Builder(anyType, resource). + anyKey(anyKey). + connObjectKeyValue(connObjectKeyValue).build(); try { if (taskTO instanceof PushTaskTO) { - restClient.push(reconQuery, (PushTaskTO) form.getModelObject()); + reconRestClient.push(reconQuery, (PushTaskTO) form.getModelObject()); } else { - restClient.pull(reconQuery, (PullTaskTO) form.getModelObject()); + reconRestClient.pull(reconQuery, (PullTaskTO) form.getModelObject()); } SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED)); diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusDirectoryPanel.java index 217daea..410ace3 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusDirectoryPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/status/ResourceStatusDirectoryPanel.java @@ -141,6 +141,7 @@ public class ResourceStatusDirectoryPanel new PushTaskTO(), type, bean.getKey(), + true, multiLevelPanelRef, pageRef), target); @@ -166,6 +167,7 @@ public class ResourceStatusDirectoryPanel new PullTaskTO(), type, bean.getKey(), + true, multiLevelPanelRef, pageRef), target); diff --git a/client/console/src/main/resources/META-INF/resources/css/syncopeConsole.css b/client/console/src/main/resources/META-INF/resources/css/syncopeConsole.css index c2dcf2c..ee2fb5b 100644 --- a/client/console/src/main/resources/META-INF/resources/css/syncopeConsole.css +++ b/client/console/src/main/resources/META-INF/resources/css/syncopeConsole.css @@ -517,6 +517,10 @@ END - Style for Information panel width: 110px !important; } +.table > tbody > tr > td.list_view_panel_labels { + vertical-align: middle; +} + div.searchResult{ padding-top: 30px; display: block; @@ -880,7 +884,7 @@ li.todoitem a { } .popover{ - max-width: 100%; + max-width: 100%; } #popover:hover { diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/ListViewPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ListViewPanel.html index 2d3d7ee..400b2a0 100644 --- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/ListViewPanel.html +++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ListViewPanel.html @@ -45,7 +45,7 @@ under the License. <td id="check"> <input type="checkbox" wicket:id="check"/> </td> - <td wicket:id="fields" class="col_width"><span wicket:id="field"/></td> + <td wicket:id="fields" class="col_width list_view_panel_labels"><span wicket:id="field"/></td> <td> <div class="listview-actions"> <span wicket:id="actions">[actions]</span> diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/status/ReconTaskPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/status/ReconTaskPanel.html index c0c4891..7ec28d6 100644 --- a/client/console/src/main/resources/org/apache/syncope/client/console/status/ReconTaskPanel.html +++ b/client/console/src/main/resources/org/apache/syncope/client/console/status/ReconTaskPanel.html @@ -22,6 +22,7 @@ under the License. <div class="form-group form-palette"> <span wicket:id="actions">[actions]</span> </div> + <div class="form-group"><span wicket:id="realm">[realm]</span></div> <div class="form-group"><span wicket:id="matchingRule">[matchingRule]</span></div> <div class="form-group"><span wicket:id="unmatchingRule">[unmatchingRule]</span></div> <div class="form-group"><span wicket:id="performCreate">[performCreate]</span></div> diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/ConnObjectUtils.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/ConnObjectUtils.java index 064f477..17b4db6 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/ConnObjectUtils.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/ConnObjectUtils.java @@ -37,6 +37,7 @@ import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO; import org.apache.syncope.core.persistence.api.dao.UserDAO; import org.apache.syncope.core.persistence.api.entity.user.User; import org.apache.syncope.core.persistence.api.dao.RealmDAO; +import org.apache.syncope.core.persistence.api.entity.AnyTypeClass; import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory; import org.apache.syncope.core.persistence.api.entity.Realm; import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy; @@ -287,8 +288,11 @@ public class ConnObjectUtils { default: } - // SYNCOPE-1343, remove null or empty values from the patch plain attributes if (anyPatch != null) { + // ensure not to include incidental realm changes in the patch + anyPatch.setRealm(null); + + // SYNCOPE-1343, remove null or empty values from the patch plain attributes AnyOperations.cleanEmptyAttrs(updated, anyPatch); } return anyPatch; @@ -299,6 +303,8 @@ public class ConnObjectUtils { T anyTO = anyUtilsFactory.getInstance(provision.getAnyType().getKind()).newAnyTO(); anyTO.setType(provision.getAnyType().getKey()); + anyTO.getAuxClasses().addAll(provision.getAuxClasses().stream(). + map(AnyTypeClass::getKey).collect(Collectors.toList())); // 1. fill with data from connector object anyTO.setRealm(pullTask.getDestinatioRealm().getFullPath());