[SYNCOPE-156] providing status panel for any objects
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/e034afcd Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/e034afcd Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/e034afcd Branch: refs/heads/master Commit: e034afcd5e7da01d56d9222d85f14d3b15cb4c6a Parents: c2ce2e8 Author: fmartelli <[email protected]> Authored: Tue Nov 17 14:59:33 2015 +0100 Committer: fmartelli <[email protected]> Committed: Tue Nov 17 14:59:33 2015 +0100 ---------------------------------------------------------------------- .../client/console/commons/AnyDataProvider.java | 2 +- .../commons/NotificationAwareComponent.java | 25 + .../console/commons/status/StatusBean.java | 4 +- .../console/commons/status/StatusUtils.java | 19 +- .../client/console/pages/AbstractBasePage.java | 4 +- .../client/console/pages/StatusModal.java | 648 +++++++++++++++++++ .../client/console/pages/StatusModalPage.java | 648 ------------------- .../console/panels/AnySearchResultPanel.java | 4 +- .../console/panels/GroupSearchResultPanel.java | 6 +- .../client/console/panels/ListViewPanel.java | 187 ++++-- .../client/console/panels/ResourceModal.java | 2 +- .../console/panels/UserSearchResultPanel.java | 16 +- .../console/rest/AbstractAnyRestClient.java | 2 +- .../console/rest/AnyObjectRestClient.java | 6 +- .../client/console/rest/GroupRestClient.java | 2 +- .../client/console/rest/UserRestClient.java | 2 +- .../markup/html/ClearIndicatingAjaxLink.java | 8 +- .../markup/html/bootstrap/dialog/BaseModal.java | 4 +- .../wicket/markup/html/form/ActionLink.java | 15 + .../markup/html/form/ActionLinksPanel.java | 131 ++-- .../client/console/wizards/AjaxWizard.java | 42 +- .../console/wizards/AjaxWizardBuilder.java | 8 +- .../client/console/wizards/WizardMgtPanel.java | 19 +- .../console/wizards/any/AnyWizardBuilder.java | 12 + .../console/wizards/any/ConnObjectPanel.java | 98 +++ .../client/console/wizards/any/Details.java | 46 ++ .../console/wizards/any/GroupDetails.java | 15 +- .../console/wizards/any/GroupWizardBuilder.java | 16 +- .../console/wizards/any/PasswordPanel.java | 4 +- .../client/console/wizards/any/PlainAttrs.java | 4 +- .../client/console/wizards/any/StatusPanel.java | 220 +++++++ .../client/console/wizards/any/UserDetails.java | 48 +- .../console/wizards/any/UserWizardBuilder.java | 42 +- .../panels/AbstractSearchResultPanel.properties | 4 +- .../AbstractSearchResultPanel_it.properties | 4 +- .../AbstractSearchResultPanel_pt_BR.properties | 4 +- .../client/console/panels/ListViewPanel.html | 26 +- .../markup/html/form/ActionLinksPanel.html | 2 +- .../client/console/wizards/WizardMgtPanel.html | 8 +- .../console/wizards/any/ConnObjectPanel.html | 26 + .../client/console/wizards/any/Details.html | 27 + .../console/wizards/any/GroupDetails.html | 4 +- .../client/console/wizards/any/StatusPanel.html | 46 ++ .../console/wizards/any/StatusPanel.properties | 19 + .../wizards/any/StatusPanel_it.properties | 19 + .../wizards/any/StatusPanel_pt_BR.properties | 19 + .../client/console/wizards/any/UserDetails.html | 5 +- .../console/wizards/any/UserDetails.properties | 1 + .../wizards/any/UserDetails_it.properties | 1 + .../wizards/any/UserDetails_pt_BR.properties | 3 +- 50 files changed, 1688 insertions(+), 839 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/e034afcd/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java index dbf823b..6a2d226 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java @@ -99,7 +99,7 @@ public class AnyDataProvider<T extends AnyTO> extends SortableDataProvider<T, St ? 0 : restClient.searchCount(realm, fiql, type); } else { - result = restClient.count(realm); + result = restClient.count(type, realm); } return result; http://git-wip-us.apache.org/repos/asf/syncope/blob/e034afcd/client/console/src/main/java/org/apache/syncope/client/console/commons/NotificationAwareComponent.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/NotificationAwareComponent.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/NotificationAwareComponent.java new file mode 100644 index 0000000..b767db0 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/NotificationAwareComponent.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.client.console.commons; + +import org.apache.syncope.client.console.panels.NotificationPanel; + +public interface NotificationAwareComponent { + NotificationPanel getFeedbackPanel(); +} http://git-wip-us.apache.org/repos/asf/syncope/blob/e034afcd/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusBean.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusBean.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusBean.java index 893b8aa..3a317b8 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusBean.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusBean.java @@ -45,7 +45,9 @@ public class StatusBean implements Serializable { public StatusBean(final AnyTO any, final String resourceName) { this.anyKey = any.getKey(); - this.anyName = any instanceof UserTO ? ((UserTO) any).getUsername() : ((GroupTO) any).getName(); + this.anyName = any instanceof UserTO + ? ((UserTO) any).getUsername() + : any instanceof GroupTO ? ((GroupTO) any).getName() : String.valueOf(any.getKey()); this.resourceName = resourceName; } http://git-wip-us.apache.org/repos/asf/syncope/blob/e034afcd/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java ---------------------------------------------------------------------- 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 73da6a7..0e5c02f 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 @@ -28,6 +28,7 @@ import org.apache.syncope.client.console.commons.ConnIdSpecialAttributeName; import org.apache.syncope.client.console.commons.Constants; import org.apache.syncope.client.console.panels.ImagePanel; import org.apache.syncope.client.console.rest.AbstractAnyRestClient; +import org.apache.syncope.common.lib.patch.PasswordPatch; import org.apache.syncope.common.lib.patch.StatusPatch; import org.apache.syncope.common.lib.to.AnyTO; import org.apache.syncope.common.lib.to.AttrTO; @@ -48,9 +49,9 @@ public class StatusUtils implements Serializable { private static final String IMG_PREFIX = "/img/statuses/"; - private final AbstractAnyRestClient restClient; + private final AbstractAnyRestClient<?> restClient; - public StatusUtils(final AbstractAnyRestClient restClient) { + public StatusUtils(final AbstractAnyRestClient<?> restClient) { this.restClient = restClient; } @@ -139,6 +140,20 @@ public class StatusUtils implements Serializable { : null; } + public static PasswordPatch buildPasswordPatch(final String password, final Collection<StatusBean> statuses) { + final PasswordPatch.Builder builder = new PasswordPatch.Builder(); + builder.value(password); + + for (StatusBean status : statuses) { + if ("syncope".equalsIgnoreCase(status.getResourceName())) { + builder.onSyncope(true); + } else { + builder.resource(status.getResourceName()); + } + } + return builder.build(); + } + public static StatusPatch buildStatusPatch(final Collection<StatusBean> statuses) { return buildStatusPatch(statuses, null); } http://git-wip-us.apache.org/repos/asf/syncope/blob/e034afcd/client/console/src/main/java/org/apache/syncope/client/console/pages/AbstractBasePage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/AbstractBasePage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/AbstractBasePage.java index c4096af..247051e 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/pages/AbstractBasePage.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/AbstractBasePage.java @@ -19,6 +19,7 @@ package org.apache.syncope.client.console.pages; import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.NotificationAwareComponent; import org.apache.syncope.client.console.panels.NotificationPanel; import org.apache.syncope.client.console.wicket.markup.head.MetaHeaderItem; import org.apache.wicket.markup.head.HeaderItem; @@ -29,7 +30,7 @@ import org.apache.wicket.request.mapper.parameter.PageParameters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class AbstractBasePage extends WebPage { +public class AbstractBasePage extends WebPage implements NotificationAwareComponent { private static final long serialVersionUID = 8611724965544132636L; @@ -64,6 +65,7 @@ public class AbstractBasePage extends WebPage { add(feedbackPanel); } + @Override public NotificationPanel getFeedbackPanel() { return feedbackPanel; } http://git-wip-us.apache.org/repos/asf/syncope/blob/e034afcd/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModal.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModal.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModal.java new file mode 100644 index 0000000..e6c7a27 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModal.java @@ -0,0 +1,648 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.client.console.pages; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.status.AbstractStatusBeanProvider; +import org.apache.syncope.client.console.commons.status.ConnObjectWrapper; +import org.apache.syncope.client.console.commons.status.Status; +import org.apache.syncope.client.console.commons.status.StatusBean; +import org.apache.syncope.client.console.commons.status.StatusUtils; +import org.apache.syncope.client.console.panels.ActionDataTablePanel; +import org.apache.syncope.client.console.rest.GroupRestClient; +import org.apache.syncope.client.console.rest.ResourceRestClient; +import org.apache.syncope.client.console.rest.UserRestClient; +import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton; +import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal; +import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink; +import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel; +import org.apache.syncope.common.lib.to.AnyTO; +import org.apache.syncope.common.lib.to.BulkActionResult; +import org.apache.syncope.common.lib.to.ResourceTO; +import org.apache.syncope.common.lib.to.GroupTO; +import org.apache.syncope.common.lib.to.UserTO; +import org.apache.syncope.common.lib.types.ResourceAssociationAction; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator; +import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn; +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; +import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider; +import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn; +import org.apache.wicket.markup.ComponentTag; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.form.PasswordTextField; +import org.apache.wicket.markup.html.panel.Fragment; +import org.apache.wicket.markup.repeater.Item; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.model.StringResourceModel; + +public class StatusModal<T extends AnyTO> extends AbstractStatusModalPage { + + private static final long serialVersionUID = -9148734710505211261L; + + private final UserRestClient userRestClient = new UserRestClient(); + + private final GroupRestClient groupRestClient = new GroupRestClient(); + + private final ResourceRestClient resourceRestClient = new ResourceRestClient(); + + private final AnyTO anyTO; + + private int rowsPerPage = 10; + + private final StatusUtils statusUtils; + + private final boolean statusOnly; + + // -------------------------------- + // password management fields .. + // -------------------------------- + private final ClearIndicatingAjaxButton cancel; + + private final WebMarkupContainer pwdMgt; + + private final Form<?> pwdMgtForm; + + private final AjaxCheckBoxPanel changepwd; + + private final PasswordTextField password; + + private final PasswordTextField confirm; + // -------------------------------- + + private final ActionDataTablePanel<StatusBean, String> table; + + private final List<IColumn<StatusBean, String>> columns; + + public StatusModal( + final BaseModal<T> modal, + final PageReference pageRef, + final AnyTO attributableTO) { + + this(modal, pageRef, attributableTO, false); + } + + public StatusModal( + final BaseModal<T> modal, + final PageReference pageRef, + final AnyTO anyTO, + final boolean statusOnly) { + + super(modal, pageRef); + + this.statusOnly = statusOnly; + this.anyTO = anyTO; + + statusUtils = new StatusUtils(anyTO instanceof UserTO ? userRestClient : groupRestClient); + + add(new Label("displayName", anyTO.getKey() + " " + + (anyTO instanceof UserTO ? ((UserTO) anyTO).getUsername() : ((GroupTO) anyTO).getName()))); + + columns = new ArrayList<>(); + columns.add(new AbstractColumn<StatusBean, String>( + new StringResourceModel("resourceName", this, null), "resourceName") { + + private static final long serialVersionUID = 2054811145491901166L; + + @Override + public void populateItem( + final Item<ICellPopulator<StatusBean>> cellItem, + final String componentId, + final IModel<StatusBean> model) { + + cellItem.add(new Label(componentId, model.getObject().getResourceName()) { + + private static final long serialVersionUID = 8432079838783825801L; + + @Override + protected void onComponentTag(final ComponentTag tag) { + if (model.getObject().isLinked()) { + super.onComponentTag(tag); + } else { + tag.put("style", "color: #DDDDDD"); + } + } + }); + } + }); + + columns.add(new PropertyColumn<StatusBean, String>( + new StringResourceModel("connObjectLink", this, null), "connObjectLink", "connObjectLink")); + + columns.add(new AbstractColumn<StatusBean, String>( + new StringResourceModel("status", this, null)) { + + private static final long serialVersionUID = -3503023501954863131L; + + @Override + public String getCssClass() { + return "action"; + } + + @Override + public void populateItem( + final Item<ICellPopulator<StatusBean>> cellItem, + final String componentId, + final IModel<StatusBean> model) { + + if (model.getObject().isLinked()) { + cellItem.add(statusUtils.getStatusImagePanel(componentId, model.getObject(). + getStatus())); + } else { + cellItem.add(new Label(componentId, "")); + } + } + }); + + table = new ActionDataTablePanel<StatusBean, String>( + "resourceDatatable", + columns, + (ISortableDataProvider<StatusBean, String>) new AttributableStatusProvider(), + rowsPerPage, + pageRef) { + + private static final long serialVersionUID = 6510391461033818316L; + + @Override + public boolean isElementEnabled(final StatusBean element) { + return !statusOnly || element.getStatus() != Status.OBJECT_NOT_FOUND; + } + }; + table.setOutputMarkupId(true); + + final String pageId = anyTO instanceof GroupTO ? "Groups" : "Users"; + + final Fragment pwdMgtFragment = new Fragment("pwdMgtFields", "pwdMgtFragment", this); + addOrReplace(pwdMgtFragment); + + pwdMgt = new WebMarkupContainer("pwdMgt"); + pwdMgtFragment.add(pwdMgt.setOutputMarkupId(true)); + + pwdMgtForm = new Form<>("pwdMgtForm"); + pwdMgtForm.setVisible(false).setEnabled(false); + pwdMgt.add(pwdMgtForm); + + password = new PasswordTextField("password", new Model<String>()); + pwdMgtForm.add(password.setRequired(false).setEnabled(false)); + + confirm = new PasswordTextField("confirm", new Model<String>()); + pwdMgtForm.add(confirm.setRequired(false).setEnabled(false)); + + changepwd = new AjaxCheckBoxPanel("changepwd", "changepwd", new Model<>(false)); + pwdMgtForm.add(changepwd.setModelObject(false)); + pwdMgtForm.add(new Label("changePwdLabel", new ResourceModel("changePwdLabel", "Password propagation"))); + + changepwd.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { + + private static final long serialVersionUID = -1107858522700306810L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + password.setEnabled(changepwd.getModelObject()); + confirm.setEnabled(changepwd.getModelObject()); + target.add(pwdMgt); + } + }); + + cancel = new ClearIndicatingAjaxButton("cancel", new ResourceModel("cancel"), pageRef) { + + private static final long serialVersionUID = -2341391430136818026L; + + @Override + protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) { + // ignore + modal.close(target); + } + }.feedbackPanelAutomaticReload(false); + + pwdMgtForm.add(cancel); + + final ClearIndicatingAjaxButton goon = new ClearIndicatingAjaxButton("continue", new ResourceModel("continue"), + pageRef) { + + private static final long serialVersionUID = -2341391430136818027L; + + @Override + protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) { + // none + } + }; + + pwdMgtForm.add(goon); + + if (statusOnly) { + table.addAction(new ActionLink<Serializable>() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target, final Serializable ignore) { + try { + userRestClient.reactivate( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + + ((BasePage) pageRef.getPage()).setModalResult(true); + + modal.close(target); + } catch (Exception e) { + LOG.error("Error enabling resources", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + modal.getFeedbackPanel().refresh(target); + } + } + }, ActionLink.ActionType.REACTIVATE, pageId); + + table.addAction(new ActionLink<Serializable>() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target, final Serializable ignore) { + try { + userRestClient.suspend( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + + if (pageRef.getPage() instanceof BasePage) { + ((BasePage) pageRef.getPage()).setModalResult(true); + } + + modal.close(target); + } catch (Exception e) { + LOG.error("Error disabling resources", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + modal.getFeedbackPanel().refresh(target); + } + } + }, ActionLink.ActionType.SUSPEND, pageId); + } else { + table.addAction(new ActionLink<Serializable>() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target, final Serializable ignore) { + try { + if (anyTO instanceof UserTO) { + userRestClient.unlink( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } else { + groupRestClient.unlink( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + modal.close(target); + } catch (Exception e) { + LOG.error("Error unlinking resources", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + modal.getFeedbackPanel().refresh(target); + } + } + }, ActionLink.ActionType.UNLINK, pageId); + + table.addAction(new ActionLink<Serializable>() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target, final Serializable ignore) { + try { + if (anyTO instanceof UserTO) { + userRestClient.link( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } else { + groupRestClient.link( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + modal.close(target); + } catch (Exception e) { + LOG.error("Error linking resources", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + modal.getFeedbackPanel().refresh(target); + } + } + }, ActionLink.ActionType.LINK, pageId); + + table.addAction(new ActionLink<Serializable>() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target, final Serializable ignore) { + try { + BulkActionResult bulkActionResult; + if (anyTO instanceof UserTO) { + bulkActionResult = userRestClient.deprovision( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } else { + bulkActionResult = groupRestClient.deprovision( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + loadBulkActionResultPage(target, table.getModelObject(), bulkActionResult); + } catch (Exception e) { + LOG.error("Error de-provisioning user", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + modal.getFeedbackPanel().refresh(target); + } + } + }, ActionLink.ActionType.DEPROVISION, pageId); + + table.addAction(new ActionLink<Serializable>() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target, final Serializable ignore) { + + if (anyTO instanceof UserTO) { + StatusModal.this.passwordManagement( + target, ResourceAssociationAction.PROVISION, table.getModelObject()); + } else { + try { + final BulkActionResult bulkActionResult = groupRestClient.provision( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + + ((BasePage) pageRef.getPage()).setModalResult(true); + loadBulkActionResultPage(target, table.getModelObject(), bulkActionResult); + } catch (Exception e) { + LOG.error("Error provisioning user", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + modal.getFeedbackPanel().refresh(target); + } + } + } + }.feedbackPanelAutomaticReload(!(anyTO instanceof UserTO)), ActionLink.ActionType.PROVISION, pageId); + + table.addAction(new ActionLink<Serializable>() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target, final Serializable ignore) { + try { + final BulkActionResult bulkActionResult; + if (anyTO instanceof UserTO) { + bulkActionResult = userRestClient.unassign( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } else { + bulkActionResult = groupRestClient.unassign( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + loadBulkActionResultPage(target, table.getModelObject(), bulkActionResult); + } catch (Exception e) { + LOG.error("Error unassigning resources", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + modal.getFeedbackPanel().refresh(target); + } + } + }, ActionLink.ActionType.UNASSIGN, pageId); + + table.addAction(new ActionLink<Serializable>() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target, final Serializable ignore) { + if (anyTO instanceof UserTO) { + StatusModal.this.passwordManagement( + target, ResourceAssociationAction.ASSIGN, table.getModelObject()); + } else { + try { + final BulkActionResult bulkActionResult = groupRestClient.assign( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + + ((BasePage) pageRef.getPage()).setModalResult(true); + loadBulkActionResultPage(target, table.getModelObject(), bulkActionResult); + } catch (Exception e) { + LOG.error("Error assigning resources", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + modal.getFeedbackPanel().refresh(target); + } + } + } + }.feedbackPanelAutomaticReload(!(anyTO instanceof UserTO)), ActionLink.ActionType.ASSIGN, pageId); + } + + table.addCancelButton(modal); + add(table); + } + + private class AttributableStatusProvider extends AbstractStatusBeanProvider { + + private static final long serialVersionUID = 4586969457669796621L; + + AttributableStatusProvider() { + super(statusOnly ? "resourceName" : "connObjectLink"); + } + + @SuppressWarnings("unchecked") + @Override + public List<StatusBean> getStatusBeans() { + final List<String> resources = new ArrayList<>(); + for (ResourceTO resourceTO : resourceRestClient.getAll()) { + resources.add(resourceTO.getKey()); + } + + final List<ConnObjectWrapper> connObjects = statusUtils.getConnectorObjects(anyTO); + + final List<StatusBean> statusBeans = new ArrayList<>(connObjects.size() + 1); + + for (ConnObjectWrapper entry : connObjects) { + final StatusBean statusBean = statusUtils.getStatusBean(anyTO, + entry.getResourceName(), + entry.getConnObjectTO(), + anyTO instanceof GroupTO); + + statusBeans.add(statusBean); + resources.remove(entry.getResourceName()); + } + + if (statusOnly) { + final StatusBean syncope = new StatusBean(anyTO, "Syncope"); + + syncope.setConnObjectLink(((UserTO) anyTO).getUsername()); + + Status syncopeStatus = Status.UNDEFINED; + if (((UserTO) anyTO).getStatus() != null) { + try { + syncopeStatus = Status.valueOf(((UserTO) anyTO).getStatus().toUpperCase()); + } catch (IllegalArgumentException e) { + LOG.warn("Unexpected status found: {}", ((UserTO) anyTO).getStatus(), e); + } + } + syncope.setStatus(syncopeStatus); + + statusBeans.add(syncope); + } else { + for (String resource : resources) { + final StatusBean statusBean = statusUtils.getStatusBean(anyTO, + resource, + null, + anyTO instanceof GroupTO); + + statusBean.setLinked(false); + statusBeans.add(statusBean); + } + } + + return statusBeans; + } + } + + private void passwordManagement( + final AjaxRequestTarget target, + final ResourceAssociationAction type, + final Collection<StatusBean> selection) { + + final ClearIndicatingAjaxButton goon = new ClearIndicatingAjaxButton("continue", new ResourceModel("continue", + "Continue"), pageRef) { + + private static final long serialVersionUID = -2341391430136818027L; + + @Override + protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) { + try { + if (StringUtils.isNotBlank(password.getModelObject()) + && !password.getModelObject().equals(confirm.getModelObject())) { + throw new Exception(getString("passwordMismatch")); + } + + final BulkActionResult bulkActionResult; + switch (type) { +// case ASSIGN: +// bulkActionResult = userRestClient.assign( +// anyTO.getETagValue(), +// anyTO.getKey(), +// new ArrayList<>(selection), +// changepwd.getModelObject(), +// password.getModelObject()); +// break; +// case PROVISION: +// bulkActionResult = userRestClient.provision( +// anyTO.getETagValue(), +// anyTO.getKey(), +// new ArrayList<>(selection), +// changepwd.getModelObject(), +// password.getModelObject()); +// break; + default: + bulkActionResult = null; + // ignore + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + + if (bulkActionResult != null) { + loadBulkActionResultPage(target, selection, bulkActionResult); + } else { + + target.add(((BasePage) pageRef.getPage()).getFeedbackPanel()); + modal.close(target); + } + } catch (Exception e) { + LOG.error("Error provisioning resources", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + modal.getFeedbackPanel().refresh(target); + } + } + }.feedbackPanelAutomaticReload(false); + + pwdMgtForm.addOrReplace(goon); + + table.setVisible(false); + pwdMgtForm.setVisible(true).setEnabled(true); + + target.add(table); + target.add(pwdMgt); + } + + private void loadBulkActionResultPage( + final AjaxRequestTarget target, + final Collection<StatusBean> selection, + final BulkActionResult bulkActionResult) { + final List<String> resources = new ArrayList<>(selection.size()); + for (StatusBean statusBean : selection) { + resources.add(statusBean.getResourceName()); + } + + final List<ConnObjectWrapper> connObjects = statusUtils.getConnectorObjects(Collections.singletonList(anyTO), + resources); + + final List<StatusBean> statusBeans = new ArrayList<>(connObjects.size()); + + for (ConnObjectWrapper entry : connObjects) { + final StatusBean statusBean = statusUtils.getStatusBean(anyTO, + entry.getResourceName(), + entry.getConnObjectTO(), + anyTO instanceof GroupTO); + + statusBeans.add(statusBean); + } + + target.add(modal.setContent(new BulkActionResultModalPage<>( + modal, + pageRef, + statusBeans, + columns, + bulkActionResult, + "resourceName"))); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/e034afcd/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModalPage.java deleted file mode 100644 index 4f5e27a..0000000 --- a/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModalPage.java +++ /dev/null @@ -1,648 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.syncope.client.console.pages; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import org.apache.commons.lang3.StringUtils; -import org.apache.syncope.client.console.commons.Constants; -import org.apache.syncope.client.console.commons.status.AbstractStatusBeanProvider; -import org.apache.syncope.client.console.commons.status.ConnObjectWrapper; -import org.apache.syncope.client.console.commons.status.Status; -import org.apache.syncope.client.console.commons.status.StatusBean; -import org.apache.syncope.client.console.commons.status.StatusUtils; -import org.apache.syncope.client.console.panels.ActionDataTablePanel; -import org.apache.syncope.client.console.rest.GroupRestClient; -import org.apache.syncope.client.console.rest.ResourceRestClient; -import org.apache.syncope.client.console.rest.UserRestClient; -import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton; -import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal; -import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink; -import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel; -import org.apache.syncope.common.lib.to.AnyTO; -import org.apache.syncope.common.lib.to.BulkActionResult; -import org.apache.syncope.common.lib.to.ResourceTO; -import org.apache.syncope.common.lib.to.GroupTO; -import org.apache.syncope.common.lib.to.UserTO; -import org.apache.syncope.common.lib.types.ResourceAssociationAction; -import org.apache.wicket.PageReference; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; -import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator; -import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn; -import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; -import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider; -import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn; -import org.apache.wicket.markup.ComponentTag; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.html.form.Form; -import org.apache.wicket.markup.html.form.PasswordTextField; -import org.apache.wicket.markup.html.panel.Fragment; -import org.apache.wicket.markup.repeater.Item; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.Model; -import org.apache.wicket.model.ResourceModel; -import org.apache.wicket.model.StringResourceModel; - -public class StatusModalPage<T extends AnyTO> extends AbstractStatusModalPage { - - private static final long serialVersionUID = -9148734710505211261L; - - private final UserRestClient userRestClient = new UserRestClient(); - - private final GroupRestClient groupRestClient = new GroupRestClient(); - - private final ResourceRestClient resourceRestClient = new ResourceRestClient(); - - private final AnyTO anyTO; - - private int rowsPerPage = 10; - - private final StatusUtils statusUtils; - - private final boolean statusOnly; - - // -------------------------------- - // password management fields .. - // -------------------------------- - private final ClearIndicatingAjaxButton cancel; - - private final WebMarkupContainer pwdMgt; - - private final Form<?> pwdMgtForm; - - private final AjaxCheckBoxPanel changepwd; - - private final PasswordTextField password; - - private final PasswordTextField confirm; - // -------------------------------- - - private final ActionDataTablePanel<StatusBean, String> table; - - private final List<IColumn<StatusBean, String>> columns; - - public StatusModalPage( - final BaseModal<T> modal, - final PageReference pageRef, - final AnyTO attributableTO) { - - this(modal, pageRef, attributableTO, false); - } - - public StatusModalPage( - final BaseModal<T> modal, - final PageReference pageRef, - final AnyTO anyTO, - final boolean statusOnly) { - - super(modal, pageRef); - - this.statusOnly = statusOnly; - this.anyTO = anyTO; - - statusUtils = new StatusUtils(anyTO instanceof UserTO ? userRestClient : groupRestClient); - - add(new Label("displayName", anyTO.getKey() + " " - + (anyTO instanceof UserTO ? ((UserTO) anyTO).getUsername() : ((GroupTO) anyTO).getName()))); - - columns = new ArrayList<>(); - columns.add(new AbstractColumn<StatusBean, String>( - new StringResourceModel("resourceName", this, null), "resourceName") { - - private static final long serialVersionUID = 2054811145491901166L; - - @Override - public void populateItem( - final Item<ICellPopulator<StatusBean>> cellItem, - final String componentId, - final IModel<StatusBean> model) { - - cellItem.add(new Label(componentId, model.getObject().getResourceName()) { - - private static final long serialVersionUID = 8432079838783825801L; - - @Override - protected void onComponentTag(final ComponentTag tag) { - if (model.getObject().isLinked()) { - super.onComponentTag(tag); - } else { - tag.put("style", "color: #DDDDDD"); - } - } - }); - } - }); - - columns.add(new PropertyColumn<StatusBean, String>( - new StringResourceModel("connObjectLink", this, null), "connObjectLink", "connObjectLink")); - - columns.add(new AbstractColumn<StatusBean, String>( - new StringResourceModel("status", this, null)) { - - private static final long serialVersionUID = -3503023501954863131L; - - @Override - public String getCssClass() { - return "action"; - } - - @Override - public void populateItem( - final Item<ICellPopulator<StatusBean>> cellItem, - final String componentId, - final IModel<StatusBean> model) { - - if (model.getObject().isLinked()) { - cellItem.add(statusUtils.getStatusImagePanel(componentId, model.getObject(). - getStatus())); - } else { - cellItem.add(new Label(componentId, "")); - } - } - }); - - table = new ActionDataTablePanel<StatusBean, String>( - "resourceDatatable", - columns, - (ISortableDataProvider<StatusBean, String>) new AttributableStatusProvider(), - rowsPerPage, - pageRef) { - - private static final long serialVersionUID = 6510391461033818316L; - - @Override - public boolean isElementEnabled(final StatusBean element) { - return !statusOnly || element.getStatus() != Status.OBJECT_NOT_FOUND; - } - }; - table.setOutputMarkupId(true); - - final String pageId = anyTO instanceof GroupTO ? "Groups" : "Users"; - - final Fragment pwdMgtFragment = new Fragment("pwdMgtFields", "pwdMgtFragment", this); - addOrReplace(pwdMgtFragment); - - pwdMgt = new WebMarkupContainer("pwdMgt"); - pwdMgtFragment.add(pwdMgt.setOutputMarkupId(true)); - - pwdMgtForm = new Form("pwdMgtForm"); - pwdMgtForm.setVisible(false).setEnabled(false); - pwdMgt.add(pwdMgtForm); - - password = new PasswordTextField("password", new Model<String>()); - pwdMgtForm.add(password.setRequired(false).setEnabled(false)); - - confirm = new PasswordTextField("confirm", new Model<String>()); - pwdMgtForm.add(confirm.setRequired(false).setEnabled(false)); - - changepwd = new AjaxCheckBoxPanel("changepwd", "changepwd", new Model<>(false)); - pwdMgtForm.add(changepwd.setModelObject(false)); - pwdMgtForm.add(new Label("changePwdLabel", new ResourceModel("changePwdLabel", "Password propagation"))); - - changepwd.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { - - private static final long serialVersionUID = -1107858522700306810L; - - @Override - protected void onUpdate(final AjaxRequestTarget target) { - password.setEnabled(changepwd.getModelObject()); - confirm.setEnabled(changepwd.getModelObject()); - target.add(pwdMgt); - } - }); - - cancel = new ClearIndicatingAjaxButton("cancel", new ResourceModel("cancel"), pageRef) { - - private static final long serialVersionUID = -2341391430136818026L; - - @Override - protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) { - // ignore - modal.close(target); - } - }.feedbackPanelAutomaticReload(false); - - pwdMgtForm.add(cancel); - - final ClearIndicatingAjaxButton goon = new ClearIndicatingAjaxButton("continue", new ResourceModel("continue"), - pageRef) { - - private static final long serialVersionUID = -2341391430136818027L; - - @Override - protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) { - // none - } - }; - - pwdMgtForm.add(goon); - - if (statusOnly) { - table.addAction(new ActionLink<Serializable>() { - - private static final long serialVersionUID = -3722207913631435501L; - - @Override - public void onClick(final AjaxRequestTarget target, final Serializable ignore) { - try { - userRestClient.reactivate( - anyTO.getETagValue(), - anyTO.getKey(), - new ArrayList<>(table.getModelObject())); - - ((BasePage) pageRef.getPage()).setModalResult(true); - - modal.close(target); - } catch (Exception e) { - LOG.error("Error enabling resources", e); - error(getString(Constants.ERROR) + ": " + e.getMessage()); - modal.getFeedbackPanel().refresh(target); - } - } - }, ActionLink.ActionType.REACTIVATE, pageId); - - table.addAction(new ActionLink<Serializable>() { - - private static final long serialVersionUID = -3722207913631435501L; - - @Override - public void onClick(final AjaxRequestTarget target, final Serializable ignore) { - try { - userRestClient.suspend( - anyTO.getETagValue(), - anyTO.getKey(), - new ArrayList<>(table.getModelObject())); - - if (pageRef.getPage() instanceof BasePage) { - ((BasePage) pageRef.getPage()).setModalResult(true); - } - - modal.close(target); - } catch (Exception e) { - LOG.error("Error disabling resources", e); - error(getString(Constants.ERROR) + ": " + e.getMessage()); - modal.getFeedbackPanel().refresh(target); - } - } - }, ActionLink.ActionType.SUSPEND, pageId); - } else { - table.addAction(new ActionLink<Serializable>() { - - private static final long serialVersionUID = -3722207913631435501L; - - @Override - public void onClick(final AjaxRequestTarget target, final Serializable ignore) { - try { - if (anyTO instanceof UserTO) { - userRestClient.unlink( - anyTO.getETagValue(), - anyTO.getKey(), - new ArrayList<>(table.getModelObject())); - } else { - groupRestClient.unlink( - anyTO.getETagValue(), - anyTO.getKey(), - new ArrayList<>(table.getModelObject())); - } - - ((BasePage) pageRef.getPage()).setModalResult(true); - modal.close(target); - } catch (Exception e) { - LOG.error("Error unlinking resources", e); - error(getString(Constants.ERROR) + ": " + e.getMessage()); - modal.getFeedbackPanel().refresh(target); - } - } - }, ActionLink.ActionType.UNLINK, pageId); - - table.addAction(new ActionLink<Serializable>() { - - private static final long serialVersionUID = -3722207913631435501L; - - @Override - public void onClick(final AjaxRequestTarget target, final Serializable ignore) { - try { - if (anyTO instanceof UserTO) { - userRestClient.link( - anyTO.getETagValue(), - anyTO.getKey(), - new ArrayList<>(table.getModelObject())); - } else { - groupRestClient.link( - anyTO.getETagValue(), - anyTO.getKey(), - new ArrayList<>(table.getModelObject())); - } - - ((BasePage) pageRef.getPage()).setModalResult(true); - modal.close(target); - } catch (Exception e) { - LOG.error("Error linking resources", e); - error(getString(Constants.ERROR) + ": " + e.getMessage()); - modal.getFeedbackPanel().refresh(target); - } - } - }, ActionLink.ActionType.LINK, pageId); - - table.addAction(new ActionLink<Serializable>() { - - private static final long serialVersionUID = -3722207913631435501L; - - @Override - public void onClick(final AjaxRequestTarget target, final Serializable ignore) { - try { - BulkActionResult bulkActionResult; - if (anyTO instanceof UserTO) { - bulkActionResult = userRestClient.deprovision( - anyTO.getETagValue(), - anyTO.getKey(), - new ArrayList<>(table.getModelObject())); - } else { - bulkActionResult = groupRestClient.deprovision( - anyTO.getETagValue(), - anyTO.getKey(), - new ArrayList<>(table.getModelObject())); - } - - ((BasePage) pageRef.getPage()).setModalResult(true); - loadBulkActionResultPage(target, table.getModelObject(), bulkActionResult); - } catch (Exception e) { - LOG.error("Error de-provisioning user", e); - error(getString(Constants.ERROR) + ": " + e.getMessage()); - modal.getFeedbackPanel().refresh(target); - } - } - }, ActionLink.ActionType.DEPROVISION, pageId); - - table.addAction(new ActionLink<Serializable>() { - - private static final long serialVersionUID = -3722207913631435501L; - - @Override - public void onClick(final AjaxRequestTarget target, final Serializable ignore) { - - if (anyTO instanceof UserTO) { - StatusModalPage.this.passwordManagement( - target, ResourceAssociationAction.PROVISION, table.getModelObject()); - } else { - try { - final BulkActionResult bulkActionResult = groupRestClient.provision( - anyTO.getETagValue(), - anyTO.getKey(), - new ArrayList<>(table.getModelObject())); - - ((BasePage) pageRef.getPage()).setModalResult(true); - loadBulkActionResultPage(target, table.getModelObject(), bulkActionResult); - } catch (Exception e) { - LOG.error("Error provisioning user", e); - error(getString(Constants.ERROR) + ": " + e.getMessage()); - modal.getFeedbackPanel().refresh(target); - } - } - } - }.feedbackPanelAutomaticReload(!(anyTO instanceof UserTO)), ActionLink.ActionType.PROVISION, pageId); - - table.addAction(new ActionLink<Serializable>() { - - private static final long serialVersionUID = -3722207913631435501L; - - @Override - public void onClick(final AjaxRequestTarget target, final Serializable ignore) { - try { - final BulkActionResult bulkActionResult; - if (anyTO instanceof UserTO) { - bulkActionResult = userRestClient.unassign( - anyTO.getETagValue(), - anyTO.getKey(), - new ArrayList<>(table.getModelObject())); - } else { - bulkActionResult = groupRestClient.unassign( - anyTO.getETagValue(), - anyTO.getKey(), - new ArrayList<>(table.getModelObject())); - } - - ((BasePage) pageRef.getPage()).setModalResult(true); - loadBulkActionResultPage(target, table.getModelObject(), bulkActionResult); - } catch (Exception e) { - LOG.error("Error unassigning resources", e); - error(getString(Constants.ERROR) + ": " + e.getMessage()); - modal.getFeedbackPanel().refresh(target); - } - } - }, ActionLink.ActionType.UNASSIGN, pageId); - - table.addAction(new ActionLink<Serializable>() { - - private static final long serialVersionUID = -3722207913631435501L; - - @Override - public void onClick(final AjaxRequestTarget target, final Serializable ignore) { - if (anyTO instanceof UserTO) { - StatusModalPage.this.passwordManagement( - target, ResourceAssociationAction.ASSIGN, table.getModelObject()); - } else { - try { - final BulkActionResult bulkActionResult = groupRestClient.assign( - anyTO.getETagValue(), - anyTO.getKey(), - new ArrayList<>(table.getModelObject())); - - ((BasePage) pageRef.getPage()).setModalResult(true); - loadBulkActionResultPage(target, table.getModelObject(), bulkActionResult); - } catch (Exception e) { - LOG.error("Error assigning resources", e); - error(getString(Constants.ERROR) + ": " + e.getMessage()); - modal.getFeedbackPanel().refresh(target); - } - } - } - }.feedbackPanelAutomaticReload(!(anyTO instanceof UserTO)), ActionLink.ActionType.ASSIGN, pageId); - } - - table.addCancelButton(modal); - add(table); - } - - private class AttributableStatusProvider extends AbstractStatusBeanProvider { - - private static final long serialVersionUID = 4586969457669796621L; - - AttributableStatusProvider() { - super(statusOnly ? "resourceName" : "connObjectLink"); - } - - @SuppressWarnings("unchecked") - @Override - public List<StatusBean> getStatusBeans() { - final List<String> resources = new ArrayList<>(); - for (ResourceTO resourceTO : resourceRestClient.getAll()) { - resources.add(resourceTO.getKey()); - } - - final List<ConnObjectWrapper> connObjects = statusUtils.getConnectorObjects(anyTO); - - final List<StatusBean> statusBeans = new ArrayList<>(connObjects.size() + 1); - - for (ConnObjectWrapper entry : connObjects) { - final StatusBean statusBean = statusUtils.getStatusBean(anyTO, - entry.getResourceName(), - entry.getConnObjectTO(), - anyTO instanceof GroupTO); - - statusBeans.add(statusBean); - resources.remove(entry.getResourceName()); - } - - if (statusOnly) { - final StatusBean syncope = new StatusBean(anyTO, "Syncope"); - - syncope.setConnObjectLink(((UserTO) anyTO).getUsername()); - - Status syncopeStatus = Status.UNDEFINED; - if (((UserTO) anyTO).getStatus() != null) { - try { - syncopeStatus = Status.valueOf(((UserTO) anyTO).getStatus().toUpperCase()); - } catch (IllegalArgumentException e) { - LOG.warn("Unexpected status found: {}", ((UserTO) anyTO).getStatus(), e); - } - } - syncope.setStatus(syncopeStatus); - - statusBeans.add(syncope); - } else { - for (String resource : resources) { - final StatusBean statusBean = statusUtils.getStatusBean(anyTO, - resource, - null, - anyTO instanceof GroupTO); - - statusBean.setLinked(false); - statusBeans.add(statusBean); - } - } - - return statusBeans; - } - } - - private void passwordManagement( - final AjaxRequestTarget target, - final ResourceAssociationAction type, - final Collection<StatusBean> selection) { - - final ClearIndicatingAjaxButton goon = new ClearIndicatingAjaxButton("continue", new ResourceModel("continue", - "Continue"), pageRef) { - - private static final long serialVersionUID = -2341391430136818027L; - - @Override - protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) { - try { - if (StringUtils.isNotBlank(password.getModelObject()) - && !password.getModelObject().equals(confirm.getModelObject())) { - throw new Exception(getString("passwordMismatch")); - } - - final BulkActionResult bulkActionResult; - switch (type) { -// case ASSIGN: -// bulkActionResult = userRestClient.assign( -// anyTO.getETagValue(), -// anyTO.getKey(), -// new ArrayList<>(selection), -// changepwd.getModelObject(), -// password.getModelObject()); -// break; -// case PROVISION: -// bulkActionResult = userRestClient.provision( -// anyTO.getETagValue(), -// anyTO.getKey(), -// new ArrayList<>(selection), -// changepwd.getModelObject(), -// password.getModelObject()); -// break; - default: - bulkActionResult = null; - // ignore - } - - ((BasePage) pageRef.getPage()).setModalResult(true); - - if (bulkActionResult != null) { - loadBulkActionResultPage(target, selection, bulkActionResult); - } else { - - target.add(((BasePage) pageRef.getPage()).getFeedbackPanel()); - modal.close(target); - } - } catch (Exception e) { - LOG.error("Error provisioning resources", e); - error(getString(Constants.ERROR) + ": " + e.getMessage()); - modal.getFeedbackPanel().refresh(target); - } - } - }.feedbackPanelAutomaticReload(false); - - pwdMgtForm.addOrReplace(goon); - - table.setVisible(false); - pwdMgtForm.setVisible(true).setEnabled(true); - - target.add(table); - target.add(pwdMgt); - } - - private void loadBulkActionResultPage( - final AjaxRequestTarget target, - final Collection<StatusBean> selection, - final BulkActionResult bulkActionResult) { - final List<String> resources = new ArrayList<>(selection.size()); - for (StatusBean statusBean : selection) { - resources.add(statusBean.getResourceName()); - } - - final List<ConnObjectWrapper> connObjects = statusUtils.getConnectorObjects(Collections.singletonList(anyTO), - resources); - - final List<StatusBean> statusBeans = new ArrayList<>(connObjects.size()); - - for (ConnObjectWrapper entry : connObjects) { - final StatusBean statusBean = statusUtils.getStatusBean(anyTO, - entry.getResourceName(), - entry.getConnObjectTO(), - anyTO instanceof GroupTO); - - statusBeans.add(statusBean); - } - - target.add(modal.setContent(new BulkActionResultModalPage<>( - modal, - pageRef, - statusBeans, - columns, - bulkActionResult, - "resourceName"))); - } -} http://git-wip-us.apache.org/repos/asf/syncope/blob/e034afcd/client/console/src/main/java/org/apache/syncope/client/console/panels/AnySearchResultPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnySearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnySearchResultPanel.java index d68a9c4..7a19e6c 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnySearchResultPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnySearchResultPanel.java @@ -142,8 +142,8 @@ public class AnySearchResultPanel<T extends AnyTO> extends AbstractSearchResultP @Override public void onClick(final AjaxRequestTarget target, final AnyTO anyTO) { - send(AnySearchResultPanel.this, Broadcast.BREADTH, - new AjaxWizard.NewItemActionEvent<>(model.getObject(), target)); + send(AnySearchResultPanel.this, Broadcast.EXACT, + new AjaxWizard.EditItemActionEvent<>(model.getObject(), target)); } }, ActionLink.ActionType.EDIT, entitlement).add(new ActionLink<T>() { http://git-wip-us.apache.org/repos/asf/syncope/blob/e034afcd/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupSearchResultPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupSearchResultPanel.java index e803113..186e766 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupSearchResultPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupSearchResultPanel.java @@ -55,8 +55,6 @@ public final class GroupSearchResultPanel extends AnySearchResultPanel<GroupTO> private static final long serialVersionUID = -1100228004207271270L; - private final String entitlement = "GROUP_READ"; - private GroupSearchResultPanel( final String type, final String parentId, @@ -123,8 +121,8 @@ public final class GroupSearchResultPanel extends AnySearchResultPanel<GroupTO> @Override public void onClick(final AjaxRequestTarget target, final GroupTO anyTO) { - send(GroupSearchResultPanel.this, Broadcast.BREADTH, - new AjaxWizard.NewItemActionEvent<AnyTO>(model.getObject(), target)); + send(GroupSearchResultPanel.this, Broadcast.EXACT, + new AjaxWizard.EditItemActionEvent<AnyTO>(model.getObject(), target)); } }, ActionLink.ActionType.EDIT, entitlement).add(new ActionLink<GroupTO>() { http://git-wip-us.apache.org/repos/asf/syncope/blob/e034afcd/client/console/src/main/java/org/apache/syncope/client/console/panels/ListViewPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ListViewPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ListViewPanel.java index 229bcca..be47039 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/ListViewPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ListViewPanel.java @@ -18,30 +18,38 @@ */ package org.apache.syncope.client.console.panels; -import java.beans.IntrospectionException; -import java.beans.PropertyDescriptor; import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; import org.apache.commons.lang3.StringUtils; import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink; import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel; import org.apache.syncope.client.console.wizards.AjaxWizard; import org.apache.syncope.client.console.wizards.WizardMgtPanel; +import org.apache.wicket.Component; import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior; +import org.apache.wicket.core.util.lang.PropertyResolver; import org.apache.wicket.event.IEvent; import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.Check; +import org.apache.wicket.markup.html.form.CheckGroup; +import org.apache.wicket.markup.html.form.CheckGroupSelector; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.request.cycle.RequestCycle; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public final class ListViewPanel<T extends Serializable> extends WizardMgtPanel<T> { +public abstract class ListViewPanel<T extends Serializable> extends WizardMgtPanel<T> { private static final long serialVersionUID = -7982691107029848579L; @@ -50,6 +58,27 @@ public final class ListViewPanel<T extends Serializable> extends WizardMgtPanel< */ private static final Logger LOG = LoggerFactory.getLogger(ListViewPanel.class); + public enum CheckAvailability { + + /** + * No checks. + */ + NONE, + /** + * Enabled checks including check group selector. + */ + AVAILABLE, + /** + * Disabled checks. + */ + DISABLED + + } + + private final CheckGroupSelector groupSelector; + + private final Model<CheckAvailability> check; + private final List<T> listOfItems; /** @@ -67,12 +96,35 @@ public final class ListViewPanel<T extends Serializable> extends WizardMgtPanel< final Class<T> reference, final List<String> includes, final ActionLinksPanel.Builder<T> actions, + final CheckAvailability check, + final boolean reuseItem, + final IModel<? extends Collection<T>> model, final PageReference pageRef) { super(id, pageRef); setOutputMarkupId(true); + this.check = Model.of(check); + add(new Label("caption", new ResourceModel("listview.caption", StringUtils.EMPTY))); + final CheckGroup<T> checkGroup = new CheckGroup<>("group", model); + checkGroup.setOutputMarkupId(true); + checkGroup.add(new AjaxFormChoiceComponentUpdatingBehavior() { + + private static final long serialVersionUID = -151291731388673682L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + // ignore + } + }); + add(checkGroup); + + groupSelector = new CheckGroupSelector("groupselector", checkGroup); + add(groupSelector.setOutputMarkupId(true) + .setOutputMarkupPlaceholderTag(true) + .setVisible(this.check.getObject() == CheckAvailability.AVAILABLE)); + final List<String> toBeIncluded; if (includes == null || includes.isEmpty()) { toBeIncluded = new ArrayList<String>(); @@ -98,16 +150,7 @@ public final class ListViewPanel<T extends Serializable> extends WizardMgtPanel< } } - final ListView<String> names = new ListView<String>("names", toBeIncluded) { - - private static final long serialVersionUID = 1L; - - @Override - protected void populateItem(final ListItem<String> item) { - item.add(new Label("name", new ResourceModel(item.getModelObject(), item.getModelObject()))); - } - }; - add(names); + add(header(toBeIncluded)); final ListView<T> beans = new ListView<T>("beans", listOfItems) { @@ -115,6 +158,12 @@ public final class ListViewPanel<T extends Serializable> extends WizardMgtPanel< @Override protected void populateItem(final ListItem<T> beanItem) { + beanItem.add(new Check<T>("check", beanItem.getModel(), checkGroup).setOutputMarkupId(true) + .setOutputMarkupPlaceholderTag(true) + .setVisible(ListViewPanel.this.check.getObject() == CheckAvailability.AVAILABLE + || ListViewPanel.this.check.getObject() == CheckAvailability.DISABLED) + .setEnabled(ListViewPanel.this.check.getObject() == CheckAvailability.AVAILABLE)); + final T bean = beanItem.getModelObject(); final ListView<String> fields = new ListView<String>("fields", toBeIncluded) { @@ -123,23 +172,7 @@ public final class ListViewPanel<T extends Serializable> extends WizardMgtPanel< @Override protected void populateItem(final ListItem<String> fieldItem) { - try { - LOG.debug("Processing field {}", fieldItem.getModelObject()); - - final Object value = new PropertyDescriptor(fieldItem.getModelObject(), bean.getClass()). - getReadMethod().invoke(bean); - - LOG.debug("Field value {}", value); - - fieldItem.add(value == null - ? new Label("field", StringUtils.EMPTY) - : new Label("field", new ResourceModel(value.toString(), value.toString()))); - - } catch (IntrospectionException | IllegalAccessException | IllegalArgumentException - | InvocationTargetException e) { - LOG.error("Error retrieving value for field {}", fieldItem.getModelObject(), e); - fieldItem.add(new Label("field", StringUtils.EMPTY)); - } + fieldItem.add(getValueComponent(fieldItem.getModelObject(), bean)); } }; beanItem.add(fields); @@ -147,36 +180,69 @@ public final class ListViewPanel<T extends Serializable> extends WizardMgtPanel< } }; beans.setOutputMarkupId(true); - beans.setReuseItems(true); - add(beans); + beans.setReuseItems(reuseItem); + beans.setRenderBodyOnly(true); + checkGroup.add(beans); } - public static <T extends Serializable> ListViewPanel.Builder<T> builder( - final Class<T> reference, final PageReference pageRef) { - return new ListViewPanel.Builder<T>(reference, pageRef); + private ListView<String> header(final List<String> labels) { + return new ListView<String>("names", labels) { + + private static final long serialVersionUID = 1L; + + @Override + protected void populateItem(final ListItem<String> item) { + item.add(new Label("name", new ResourceModel(item.getModelObject(), item.getModelObject()))); + } + }; + } + + public void setCheckAvailability(final CheckAvailability check) { + // used to perform selectable enabling check condition + this.check.setObject(check); + + final AjaxRequestTarget target = RequestCycle.get().find(AjaxRequestTarget.class); + + // reload group selector + target.add(groupSelector.setVisible(check == CheckAvailability.AVAILABLE)); + // reload the list view panel + target.add(ListViewPanel.this); } + protected abstract Component getValueComponent(final String key, final T bean); + /** * ListViewPanel builder. * * @param <T> list item reference type. */ - public static final class Builder<T extends Serializable> extends WizardMgtPanel.Builder<T> { + public static class Builder<T extends Serializable> extends WizardMgtPanel.Builder<T> { private static final long serialVersionUID = 1L; + private IModel<? extends Collection<T>> model = new Model<>(); + private final List<String> includes = new ArrayList<>(); private final ActionLinksPanel.Builder<T> actions; private List<T> items; - private Builder(final Class<T> reference, final PageReference pageRef) { + private CheckAvailability check = CheckAvailability.NONE; + + private boolean reuseItem = true; + + public Builder(final Class<T> reference, final PageReference pageRef) { super(reference, pageRef); this.items = null; this.actions = ActionLinksPanel.<T>builder(pageRef); } + public Builder<T> setModel(final IModel<? extends Collection<T>> model) { + this.model = model; + return this; + } + /** * Sets list of items. * @@ -207,6 +273,15 @@ public final class ListViewPanel<T extends Serializable> extends WizardMgtPanel< return this; } + public Builder<T> withChecks(final CheckAvailability check) { + this.check = check; + return this; + } + + public void setReuseItem(final boolean reuseItem) { + this.reuseItem = reuseItem; + } + /** * Gives fields to be shown. It could be used to give an order as well. * @@ -236,9 +311,43 @@ public final class ListViewPanel<T extends Serializable> extends WizardMgtPanel< return this; } + /** + * Overridable method to generate field value rendering component. + * + * @param key field key. + * @param bean source bean. + * @return field rendering component. + */ + protected Component getValueComponent(final String key, final T bean) { + LOG.debug("Processing field {}", key); + + Object value; + try { + value = PropertyResolver.getPropertyGetter(key, bean).invoke(bean); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + LOG.error("Error retrieving value for field {}", key, e); + value = StringUtils.EMPTY; + } + + LOG.debug("Field value {}", value); + + return value == null + ? new Label("field", StringUtils.EMPTY) + : new Label("field", new ResourceModel(value.toString(), value.toString())); + } + @Override protected WizardMgtPanel<T> newInstance(final String id) { - return new ListViewPanel<T>(id, items, reference, includes, actions, pageRef); + return new ListViewPanel<T>(id, items, reference, includes, actions, check, reuseItem, model, pageRef) { + + private static final long serialVersionUID = 1L; + + @Override + protected Component getValueComponent(final String key, final T bean) { + return Builder.this.getValueComponent(key, bean); + } + + }; } } @@ -249,7 +358,7 @@ public final class ListViewPanel<T extends Serializable> extends WizardMgtPanel< final T item = ((AjaxWizard.NewItemEvent<T>) event.getPayload()).getItem(); final AjaxRequestTarget target = ((AjaxWizard.NewItemEvent<T>) event.getPayload()).getTarget(); - + if (event.getPayload() instanceof AjaxWizard.NewItemFinishEvent) { if (item != null && !this.listOfItems.contains(item)) { this.listOfItems.add(item); http://git-wip-us.apache.org/repos/asf/syncope/blob/e034afcd/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceModal.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceModal.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceModal.java index 0c6d38c..401f90f 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceModal.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceModal.java @@ -88,7 +88,7 @@ public class ResourceModal extends AbstractResourceModal { //-------------------------------- // Resource provision panels //-------------------------------- - final ListViewPanel.Builder<ProvisionTO> builder = ListViewPanel.builder(ProvisionTO.class, pageRef); + final ListViewPanel.Builder<ProvisionTO> builder = new ListViewPanel.Builder<>(ProvisionTO.class, pageRef); builder.setItems(model.getObject().getProvisions()); builder.includes("anyType", "objectClass");
