http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/ReportModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/ReportModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/ReportModalPage.java new file mode 100644 index 0000000..0ef7c6a --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/ReportModalPage.java @@ -0,0 +1,640 @@ +/* + * 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.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.DateFormatROModel; +import org.apache.syncope.client.console.commons.HttpResourceStream; +import org.apache.syncope.client.console.commons.SortableDataProviderComparator; +import org.apache.syncope.client.console.wicket.ajax.form.AbstractAjaxDownloadBehavior; +import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton; +import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn; +import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn; +import org.apache.syncope.client.console.wicket.markup.html.CrontabContainer; +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.wicket.markup.html.form.AjaxTextFieldPanel; +import org.apache.syncope.common.lib.SyncopeClientException; +import org.apache.syncope.common.lib.report.AbstractReportletConf; +import org.apache.syncope.common.lib.report.ReportletConf; +import org.apache.syncope.common.lib.to.ReportExecTO; +import org.apache.syncope.common.lib.to.ReportTO; +import org.apache.syncope.common.lib.types.ReportExecExportFormat; +import org.apache.syncope.common.lib.types.ReportExecStatus; +import org.apache.wicket.Component; +import org.apache.wicket.Page; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.attributes.AjaxCallListener; +import org.apache.wicket.ajax.attributes.AjaxRequestAttributes; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.ajax.markup.html.AjaxLink; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; +import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable; +import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder; +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; +import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn; +import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider; +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.IChoiceRenderer; +import org.apache.wicket.markup.html.form.ListChoice; +import org.apache.wicket.model.AbstractReadOnlyModel; +import org.apache.wicket.model.CompoundPropertyModel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.PropertyModel; +import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.util.resource.IResourceStream; +import org.springframework.util.StringUtils; + +public class ReportModalPage extends BaseModalPage { + + private static final long serialVersionUID = -5747628615211127644L; + + private static final String ADD_BUTTON_ID = "addButton"; + + private static final String EDIT_BUTTON_ID = "editButton"; + + private static final String REMOVE_BUTTON_ID = "removeButton"; + + private static final String UP_BUTTON_ID = "upButton"; + + private static final String DOWN_BUTTON_ID = "downButton"; + + private static final int EXEC_EXPORT_WIN_HEIGHT = 100; + + private static final int EXEC_EXPORT_WIN_WIDTH = 400; + + private static final int REPORTLET_CONF_WIN_HEIGHT = 500; + + private static final int REPORTLET_CONF_WIN_WIDTH = 800; + + private final ReportTO reportTO; + + private final Form<ReportTO> form; + + private ReportExecExportFormat exportFormat; + + private long exportExecId; + + private AbstractReportletConf modalReportletConf; + + private String modalReportletConfOldName; + + private ListChoice<AbstractReportletConf> reportlets; + + public ReportModalPage(final ModalWindow window, final ReportTO reportTO, final PageReference callerPageRef) { + super(); + this.reportTO = reportTO; + + form = new Form<ReportTO>(FORM); + form.setModel(new CompoundPropertyModel<ReportTO>(reportTO)); + add(form); + + setupProfile(); + setupExecutions(); + + final CrontabContainer crontab = new CrontabContainer("crontab", new PropertyModel<String>(reportTO, + "cronExpression"), reportTO.getCronExpression()); + form.add(crontab); + + final AjaxButton submit = + new ClearIndicatingAjaxButton(APPLY, new ResourceModel(APPLY), getPageReference()) { + + private static final long serialVersionUID = -958724007591692537L; + + @Override + protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) { + ReportTO toSubmit = (ReportTO) form.getModelObject(); + toSubmit.setCronExpression(StringUtils.hasText(toSubmit.getCronExpression()) + ? crontab.getCronExpression() + : null); + + try { + if (toSubmit.getKey() > 0) { + reportRestClient.update(toSubmit); + } else { + reportRestClient.create(toSubmit); + } + + ((BasePage) callerPageRef.getPage()).setModalResult(true); + + window.close(target); + } catch (SyncopeClientException e) { + LOG.error("While creating or updating report", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + } + } + + @Override + protected void onError(final AjaxRequestTarget target, final Form<?> form) { + feedbackPanel.refresh(target); + } + }; + + if (reportTO.getKey() > 0) { + MetaDataRoleAuthorizationStrategy.authorize(submit, RENDER, + xmlRolesReader.getEntitlement("Reports", "update")); + } else { + MetaDataRoleAuthorizationStrategy.authorize(submit, RENDER, + xmlRolesReader.getEntitlement("Reports", "create")); + } + + form.add(submit); + + final AjaxButton cancel = + new ClearIndicatingAjaxButton(CANCEL, new ResourceModel(CANCEL), getPageReference()) { + + private static final long serialVersionUID = -958724007591692537L; + + @Override + protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) { + window.close(target); + } + }; + + cancel.setDefaultFormProcessing(false); + form.add(cancel); + } + + private void setupProfile() { + final WebMarkupContainer profile = new WebMarkupContainer("profile"); + profile.setOutputMarkupId(true); + form.add(profile); + + final ModalWindow reportletConfWin = new ModalWindow("reportletConfWin"); + reportletConfWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + reportletConfWin.setCookieName("reportlet-conf-win-modal"); + reportletConfWin.setInitialHeight(REPORTLET_CONF_WIN_HEIGHT); + reportletConfWin.setInitialWidth(REPORTLET_CONF_WIN_WIDTH); + reportletConfWin.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() { + + private static final long serialVersionUID = 8804221891699487139L; + + @Override + public void onClose(final AjaxRequestTarget target) { + int foundIdx = -1; + if (modalReportletConfOldName != null) { + for (int i = 0; i < reportTO.getReportletConfs().size() && foundIdx == -1; i++) { + if (reportTO.getReportletConfs().get(i).getName().equals(modalReportletConfOldName)) { + foundIdx = i; + } + } + } + if (modalReportletConf != null) { + if (foundIdx == -1) { + reportTO.getReportletConfs().add(modalReportletConf); + } else { + reportTO.getReportletConfs().set(foundIdx, modalReportletConf); + } + } + + target.add(reportlets); + } + }); + add(reportletConfWin); + + final Label idLabel = new Label("idLabel", new ResourceModel("key")); + profile.add(idLabel); + + final AjaxTextFieldPanel key = + new AjaxTextFieldPanel("key", getString("key"), new PropertyModel<String>(reportTO, "key")); + key.setEnabled(false); + profile.add(key); + + final Label nameLabel = new Label("nameLabel", new ResourceModel("name")); + profile.add(nameLabel); + + final AjaxTextFieldPanel name = + new AjaxTextFieldPanel("name", getString("name"), new PropertyModel<String>(reportTO, "name")); + profile.add(name); + + final AjaxTextFieldPanel lastExec = new AjaxTextFieldPanel("lastExec", getString("lastExec"), + new DateFormatROModel(new PropertyModel<String>(reportTO, "lastExec"))); + lastExec.setEnabled(false); + profile.add(lastExec); + + final AjaxTextFieldPanel nextExec = new AjaxTextFieldPanel("nextExec", getString("nextExec"), + new DateFormatROModel(new PropertyModel<String>(reportTO, "nextExec"))); + nextExec.setEnabled(false); + profile.add(nextExec); + + reportlets = new ListChoice<AbstractReportletConf>("reportletConfs", new Model<AbstractReportletConf>(), + reportTO.getReportletConfs(), new IChoiceRenderer<ReportletConf>() { + + private static final long serialVersionUID = 1048000918946220007L; + + @Override + public Object getDisplayValue(final ReportletConf object) { + return object.getName(); + } + + @Override + public String getIdValue(final ReportletConf object, final int index) { + return object.getName(); + } + }) { + + private static final long serialVersionUID = 4022366881854379834L; + + @Override + protected CharSequence getDefaultChoice(final String selectedValue) { + return null; + } + }; + + reportlets.setNullValid(true); + profile.add(reportlets); + reportlets.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { + + private static final long serialVersionUID = -1107858522700306810L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + target.add(reportlets); + } + }); + + profile.add(new AjaxLink<Void>(ADD_BUTTON_ID) { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(final AjaxRequestTarget target) { + reportletConfWin.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + modalReportletConfOldName = null; + modalReportletConf = null; + return new ReportletConfModalPage(null, reportletConfWin, + ReportModalPage.this.getPageReference()); + } + }); + reportletConfWin.show(target); + } + }); + + profile.add(new AjaxLink<Void>(EDIT_BUTTON_ID) { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(final AjaxRequestTarget target) { + if (reportlets.getModelObject() != null) { + reportletConfWin.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + modalReportletConfOldName = reportlets.getModelObject().getName(); + modalReportletConf = null; + return new ReportletConfModalPage(reportlets.getModelObject(), reportletConfWin, + ReportModalPage.this.getPageReference()); + } + }); + reportletConfWin.show(target); + } + } + }); + + profile.add(new AjaxLink<Void>(REMOVE_BUTTON_ID) { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(final AjaxRequestTarget target) { + reportTO.getReportletConfs().remove(reportlets.getModelObject()); + reportlets.setModelObject(null); + target.add(reportlets); + } + + @Override + protected void updateAjaxAttributes(final AjaxRequestAttributes attributes) { + if (reportlets.getModelObject() != null) { + + super.updateAjaxAttributes(attributes); + + final AjaxCallListener ajaxCallListener = new AjaxCallListener() { + + private static final long serialVersionUID = 7160235486520935153L; + + @Override + public CharSequence getPrecondition(final Component component) { + return "if (!confirm('" + getString("confirmDelete") + "')) {return false;}"; + } + }; + attributes.getAjaxCallListeners().add(ajaxCallListener); + } + } + }); + + profile.add(new AjaxLink<Void>(UP_BUTTON_ID) { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(final AjaxRequestTarget target) { + if (reportlets.getModelObject() != null) { + moveUp(reportlets.getModelObject()); + target.add(reportlets); + } + } + }); + + profile.add(new AjaxLink<Void>(DOWN_BUTTON_ID) { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(final AjaxRequestTarget target) { + if (reportlets.getModelObject() != null) { + moveDown(reportlets.getModelObject()); + target.add(reportlets); + } + } + }); + } + + private void moveUp(final AbstractReportletConf item) { + final List<AbstractReportletConf> list = reportTO.getReportletConfs(); + int newPosition = list.indexOf(item) - 1; + if (newPosition > -1) { + list.remove(item); + list.add(newPosition, item); + } + } + + private void moveDown(final AbstractReportletConf item) { + final List<AbstractReportletConf> list = reportTO.getReportletConfs(); + int newPosition = list.indexOf(item) + 1; + if (newPosition < list.size()) { + list.remove(item); + list.add(newPosition, item); + } + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private void setupExecutions() { + final WebMarkupContainer executions = new WebMarkupContainer("executionContainer"); + executions.setOutputMarkupId(true); + form.add(executions); + + final ModalWindow reportExecMessageWin = new ModalWindow("reportExecMessageWin"); + reportExecMessageWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + reportExecMessageWin.setCookieName("report-exec-message-win-modal"); + add(reportExecMessageWin); + + final ModalWindow reportExecExportWin = new ModalWindow("reportExecExportWin"); + reportExecExportWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + reportExecExportWin.setCookieName("report-exec-export-win-modal"); + reportExecExportWin.setInitialHeight(EXEC_EXPORT_WIN_HEIGHT); + reportExecExportWin.setInitialWidth(EXEC_EXPORT_WIN_WIDTH); + reportExecExportWin.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() { + + private static final long serialVersionUID = 8804221891699487139L; + + @Override + public void onClose(final AjaxRequestTarget target) { + AjaxExportDownloadBehavior behavior = new AjaxExportDownloadBehavior(ReportModalPage.this.exportFormat, + ReportModalPage.this.exportExecId); + executions.add(behavior); + behavior.initiate(target); + } + }); + add(reportExecExportWin); + + final List<IColumn> columns = new ArrayList<IColumn>(); + columns.add(new PropertyColumn(new ResourceModel("key"), "key", "key")); + columns.add(new DatePropertyColumn(new ResourceModel("startDate"), "startDate", "startDate")); + columns.add(new DatePropertyColumn(new ResourceModel("endDate"), "endDate", "endDate")); + columns.add(new PropertyColumn(new ResourceModel("status"), "status", "status")); + columns.add(new ActionColumn<ReportExecTO, String>(new ResourceModel("actions", "")) { + + private static final long serialVersionUID = 2054811145491901166L; + + @Override + public ActionLinksPanel getActions(final String componentId, final IModel<ReportExecTO> model) { + + final ReportExecTO taskExecutionTO = model.getObject(); + + final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, getPageReference()); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + reportExecMessageWin.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + return new ExecMessageModalPage(model.getObject().getMessage()); + } + }); + reportExecMessageWin.show(target); + } + }, ActionLink.ActionType.EDIT, "Reports", StringUtils.hasText(model.getObject().getMessage())); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + reportExecExportWin.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + ReportModalPage.this.exportExecId = model.getObject().getKey(); + return new ReportExecResultDownloadModalPage(reportExecExportWin, + ReportModalPage.this.getPageReference()); + } + }); + reportExecExportWin.show(target); + } + }, ActionLink.ActionType.EXPORT, "Reports", ReportExecStatus.SUCCESS.name().equals( + model.getObject().getStatus())); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + try { + reportRestClient.deleteExecution(taskExecutionTO.getKey()); + + reportTO.getExecutions().remove(taskExecutionTO); + + info(getString(Constants.OPERATION_SUCCEEDED)); + } catch (SyncopeClientException scce) { + error(scce.getMessage()); + } + + feedbackPanel.refresh(target); + target.add(executions); + } + }, ActionLink.ActionType.DELETE, "Reports"); + + return panel; + } + + @Override + public Component getHeader(final String componentId) { + final ActionLinksPanel panel = new ActionLinksPanel(componentId, new Model(), getPageReference()); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(final AjaxRequestTarget target) { + if (target != null) { + final ReportTO currentReportTO = reportTO.getKey() == 0 + ? reportTO + : reportRestClient.read(reportTO.getKey()); + reportTO.getExecutions().clear(); + reportTO.getExecutions().addAll(currentReportTO.getExecutions()); + final AjaxFallbackDefaultDataTable currentTable = + new AjaxFallbackDefaultDataTable("executionsTable", columns, + new ReportExecutionsProvider(reportTO), 10); + currentTable.setOutputMarkupId(true); + target.add(currentTable); + executions.addOrReplace(currentTable); + } + } + }, ActionLink.ActionType.RELOAD, TASKS, "list"); + + return panel; + } + }); + + final AjaxFallbackDefaultDataTable table = new AjaxFallbackDefaultDataTable("executionsTable", columns, + new ReportExecutionsProvider(reportTO), 10); + executions.add(table); + } + + public void setExportFormat(final ReportExecExportFormat exportFormat) { + this.exportFormat = exportFormat; + } + + public void setModalReportletConf(final AbstractReportletConf modalReportletConf) { + this.modalReportletConf = modalReportletConf; + } + + private static class ReportExecutionsProvider extends SortableDataProvider<ReportExecTO, String> { + + private static final long serialVersionUID = 2118096121691420539L; + + private final SortableDataProviderComparator<ReportExecTO> comparator; + + private final ReportTO reportTO; + + public ReportExecutionsProvider(final ReportTO reportTO) { + super(); + this.reportTO = reportTO; + setSort("startDate", SortOrder.DESCENDING); + comparator = new SortableDataProviderComparator<ReportExecTO>(this); + } + + @Override + public Iterator<ReportExecTO> iterator(final long first, final long count) { + + List<ReportExecTO> list = reportTO.getExecutions(); + + Collections.sort(list, comparator); + + return list.subList((int) first, (int) first + (int) count).iterator(); + } + + @Override + public long size() { + return reportTO.getExecutions().size(); + } + + @Override + public IModel<ReportExecTO> model(final ReportExecTO taskExecution) { + + return new AbstractReadOnlyModel<ReportExecTO>() { + + private static final long serialVersionUID = 7485475149862342421L; + + @Override + public ReportExecTO getObject() { + return taskExecution; + } + }; + } + } + + private class AjaxExportDownloadBehavior extends AbstractAjaxDownloadBehavior { + + private static final long serialVersionUID = 3109256773218160485L; + + private final ReportExecExportFormat exportFormat; + + private final long exportExecId; + + private HttpResourceStream stream; + + public AjaxExportDownloadBehavior(final ReportExecExportFormat exportFormat, final long exportExecId) { + super(); + this.exportFormat = exportFormat; + this.exportExecId = exportExecId; + } + + private void createResourceStream() { + if (stream == null) { + stream = new HttpResourceStream(reportRestClient.exportExecutionResult(exportExecId, exportFormat)); + } + } + + @Override + protected String getFileName() { + createResourceStream(); + return stream == null + ? null + : stream.getFilename(); + } + + @Override + protected IResourceStream getResourceStream() { + createResourceStream(); + return stream; + } + } +}
http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/ReportletConfModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/ReportletConfModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/ReportletConfModalPage.java new file mode 100644 index 0000000..e7155ca --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/ReportletConfModalPage.java @@ -0,0 +1,362 @@ +/* + * 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.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.panels.RoleSearchPanel; +import org.apache.syncope.client.console.panels.UserSearchPanel; +import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton; +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.client.console.wicket.markup.html.form.AjaxTextFieldPanel; +import org.apache.syncope.client.console.wicket.markup.html.form.CheckBoxMultipleChoiceFieldPanel; +import org.apache.syncope.client.console.wicket.markup.html.form.DateTimeFieldPanel; +import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel; +import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel; +import org.apache.syncope.client.console.wicket.markup.html.form.SpinnerFieldPanel; +import org.apache.syncope.common.lib.SyncopeConstants; +import org.apache.syncope.common.lib.annotation.FormAttributeField; +import org.apache.syncope.common.lib.report.AbstractReportletConf; +import org.apache.syncope.common.lib.types.AttributableType; +import org.apache.wicket.Component; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.DropDownChoice; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; +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.PropertyModel; +import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.model.util.ListModel; +import org.apache.wicket.util.visit.IVisit; +import org.apache.wicket.util.visit.IVisitor; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.PropertyAccessorFactory; +import org.springframework.util.ClassUtils; + +public class ReportletConfModalPage extends BaseModalPage { + + private static final long serialVersionUID = 3910027601200382958L; + + private static final String[] EXCLUDE_PROPERTIES = + new String[] { "serialVersionUID", "class", "name", "reportletClassName" }; + + private AbstractReportletConf reportletConf; + + private final AjaxTextFieldPanel name; + + private WebMarkupContainer propertiesContainer; + + private ListView<String> propView; + + public ReportletConfModalPage(final AbstractReportletConf reportletConf, final ModalWindow window, + final PageReference pageRef) { + + this.reportletConf = reportletConf; + + final Form form = new Form(FORM); + add(form); + + propertiesContainer = new WebMarkupContainer("container"); + propertiesContainer.setOutputMarkupId(true); + form.add(propertiesContainer); + + name = new AjaxTextFieldPanel("name", "name", this.reportletConf == null + ? new Model<String>() + : new PropertyModel<String>(this.reportletConf, "name")); + name.setOutputMarkupId(true); + name.addRequiredLabel(); + form.add(name); + + final AjaxDropDownChoicePanel<String> reportletClass = new AjaxDropDownChoicePanel<String>("reportletClass", + "reportletClass", new IModel<String>() { + + private static final long serialVersionUID = -2316468110411802130L; + + @Override + public String getObject() { + return ReportletConfModalPage.this.reportletConf == null + ? null + : ReportletConfModalPage.this.reportletConf.getClass().getName(); + } + + @Override + public void setObject(final String object) { + try { + Class<?> reportletClass = Class.forName(object); + ReportletConfModalPage.this.reportletConf = (AbstractReportletConf) reportletClass. + newInstance(); + propertiesContainer.replace(buildPropView()); + } catch (Exception e) { + LOG.error("Cannot find or initialize {}", object, e); + } + } + + @Override + public void detach() { + } + }); + reportletClass.setStyleSheet("long_dynamicsize"); + reportletClass.setChoices(reportRestClient.getReportletConfClasses()); + ((DropDownChoice) reportletClass.getField()).setNullValid(true); + reportletClass.addRequiredLabel(); + reportletClass.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { + + private static final long serialVersionUID = 5538299138211283825L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + ((DropDownChoice) reportletClass.getField()).setNullValid(false); + target.add(reportletClass.getField()); + target.add(propertiesContainer); + } + }); + form.add(reportletClass); + + propertiesContainer.add(buildPropView()); + + final AjaxButton submit = new AjaxButton(APPLY, new ResourceModel(APPLY)) { + + private static final long serialVersionUID = -958724007591692537L; + + @Override + protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + final BeanWrapper wrapper = PropertyAccessorFactory. + forBeanPropertyAccess(ReportletConfModalPage.this.reportletConf); + wrapper.setPropertyValue("name", name.getField().getInput()); + + // Iterate over properties in order to find UserSearchPanel instances and manually update + // this.reportletConf with select search criteria - this is needed because UserSearchPanel + // does not comply with usual Wicket model paradigm. + ReportletConfModalPage.this.propView.visitChildren(new IVisitor<Component, Void>() { + + @Override + public void component(final Component component, final IVisit<Void> ivisit) { + if (component instanceof UserSearchPanel) { + // using component.getDefaultModelObjectAsString() to fetch field name (set above) + wrapper.setPropertyValue(component.getDefaultModelObjectAsString(), + ((UserSearchPanel) component).buildFIQL()); + } + } + }); + + ((ReportModalPage) pageRef.getPage()).setModalReportletConf(ReportletConfModalPage.this.reportletConf); + window.close(target); + } + + @Override + protected void onError(final AjaxRequestTarget target, final Form<?> form) { + feedbackPanel.refresh(target); + } + }; + form.add(submit); + + final AjaxButton cancel = new ClearIndicatingAjaxButton(CANCEL, new ResourceModel(CANCEL), pageRef) { + + private static final long serialVersionUID = -958724007591692537L; + + @Override + protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) { + window.close(target); + } + }; + + cancel.setDefaultFormProcessing(false); + form.add(cancel); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private FieldPanel buildSinglePanel(final Class<?> type, final String fieldName, final String id) { + FieldPanel result = null; + PropertyModel model = new PropertyModel(ReportletConfModalPage.this.reportletConf, fieldName); + if (ClassUtils.isAssignable(Boolean.class, type)) { + result = new AjaxCheckBoxPanel(id, fieldName, model); + } else if (ClassUtils.isAssignable(Number.class, type)) { + result = new SpinnerFieldPanel<Number>(id, fieldName, + (Class<Number>) ClassUtils.resolvePrimitiveIfNecessary(type), model, null, null); + } else if (Date.class.equals(type)) { + result = new DateTimeFieldPanel(id, fieldName, model, SyncopeConstants.DEFAULT_DATE_PATTERN); + } else if (type.isEnum()) { + result = new AjaxDropDownChoicePanel(id, fieldName, model).setChoices( + Arrays.asList(type.getEnumConstants())); + } + + // treat as String if nothing matched above + if (result == null) { + result = new AjaxTextFieldPanel(id, fieldName, model); + } + + return result; + } + + private ListView<String> buildPropView() { + LoadableDetachableModel<List<String>> propViewModel = new LoadableDetachableModel<List<String>>() { + + private static final long serialVersionUID = 5275935387613157437L; + + @Override + protected List<String> load() { + List<String> result = new ArrayList<String>(); + if (ReportletConfModalPage.this.reportletConf != null) { + for (Field field : ReportletConfModalPage.this.reportletConf.getClass().getDeclaredFields()) { + if (!ArrayUtils.contains(EXCLUDE_PROPERTIES, field.getName())) { + result.add(field.getName()); + } + } + } + + return result; + } + }; + + propView = new ListView<String>("propView", propViewModel) { + + private static final long serialVersionUID = 9101744072914090143L; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + protected void populateItem(final ListItem<String> item) { + final String fieldName = item.getModelObject(); + + Label label = new Label("key", fieldName); + item.add(label); + + Field field = null; + try { + field = ReportletConfModalPage.this.reportletConf.getClass().getDeclaredField(fieldName); + } catch (Exception e) { + LOG.error("Could not find field {} in class {}", + fieldName, ReportletConfModalPage.this.reportletConf.getClass(), e); + } + if (field == null) { + return; + } + + FormAttributeField annotation = field.getAnnotation(FormAttributeField.class); + + BeanWrapper wrapper = PropertyAccessorFactory. + forBeanPropertyAccess(ReportletConfModalPage.this.reportletConf); + + Panel panel; + + if (String.class.equals(field.getType()) && annotation != null && annotation.userSearch()) { + panel = new UserSearchPanel.Builder("value"). + fiql((String) wrapper.getPropertyValue(fieldName)).required(false).build(); + // This is needed in order to manually update this.reportletConf with search panel selections + panel.setDefaultModel(new Model<String>(fieldName)); + } else if (String.class.equals(field.getType()) && annotation != null && annotation.roleSearch()) { + panel = new RoleSearchPanel.Builder("value"). + fiql((String) wrapper.getPropertyValue(fieldName)).required(false).build(); + // This is needed in order to manually update this.reportletConf with search panel selections + panel.setDefaultModel(new Model<String>(fieldName)); + } else if (List.class.equals(field.getType())) { + Class<?> listItemType = String.class; + if (field.getGenericType() instanceof ParameterizedType) { + listItemType = + (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]; + } + + if (listItemType.equals(String.class) && annotation != null) { + List<String> choices; + switch (annotation.schema()) { + case UserPlainSchema: + choices = schemaRestClient.getPlainSchemaNames(AttributableType.USER); + break; + + case UserDerivedSchema: + choices = schemaRestClient.getDerSchemaNames(AttributableType.USER); + break; + + case UserVirtualSchema: + choices = schemaRestClient.getVirSchemaNames(AttributableType.USER); + break; + + case RolePlainSchema: + choices = schemaRestClient.getPlainSchemaNames(AttributableType.ROLE); + break; + + case RoleDerivedSchema: + choices = schemaRestClient.getDerSchemaNames(AttributableType.ROLE); + break; + + case RoleVirtualSchema: + choices = schemaRestClient.getVirSchemaNames(AttributableType.ROLE); + break; + + case MembershipPlainSchema: + choices = schemaRestClient.getPlainSchemaNames(AttributableType.MEMBERSHIP); + break; + + case MembershipDerivedSchema: + choices = schemaRestClient.getDerSchemaNames(AttributableType.MEMBERSHIP); + break; + + case MembershipVirtualSchema: + choices = schemaRestClient.getVirSchemaNames(AttributableType.MEMBERSHIP); + break; + + default: + choices = Collections.emptyList(); + } + + panel = new AjaxPalettePanel("value", new PropertyModel<List<String>>( + ReportletConfModalPage.this.reportletConf, fieldName), new ListModel<String>(choices), + true); + } else if (listItemType.isEnum()) { + panel = new CheckBoxMultipleChoiceFieldPanel("value", new PropertyModel( + ReportletConfModalPage.this.reportletConf, fieldName), + new ListModel(Arrays.asList(listItemType.getEnumConstants()))); + } else { + if (((List) wrapper.getPropertyValue(fieldName)).isEmpty()) { + ((List) wrapper.getPropertyValue(fieldName)).add(null); + } + + panel = new MultiFieldPanel("value", new PropertyModel<List>( + ReportletConfModalPage.this.reportletConf, fieldName), + buildSinglePanel(field.getType(), fieldName, "panel")); + } + } else { + panel = buildSinglePanel(field.getType(), fieldName, "value"); + } + + item.add(panel); + } + }; + + return propView; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/Reports.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Reports.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Reports.java new file mode 100644 index 0000000..a7b9c6c --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Reports.java @@ -0,0 +1,412 @@ +/* + * 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.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.PreferenceManager; +import org.apache.syncope.client.console.commons.SortableDataProviderComparator; +import org.apache.syncope.client.console.panels.LoggerCategoryPanel; +import org.apache.syncope.client.console.panels.SelectedEventsPanel; +import org.apache.syncope.client.console.rest.LoggerRestClient; +import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink; +import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn; +import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn; +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.common.lib.SyncopeClientException; +import org.apache.syncope.common.lib.to.EventCategoryTO; +import org.apache.syncope.common.lib.to.ReportTO; +import org.apache.syncope.common.lib.types.AuditElements.Result; +import org.apache.syncope.common.lib.types.AuditLoggerName; +import org.apache.wicket.Component; +import org.apache.wicket.Page; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.ajax.markup.html.AjaxLink; +import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy; +import org.apache.wicket.event.IEvent; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable; +import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder; +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; +import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn; +import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.form.DropDownChoice; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.model.AbstractReadOnlyModel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.PropertyModel; +import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.model.util.ListModel; +import org.apache.wicket.request.mapper.parameter.PageParameters; +import org.apache.wicket.spring.injection.annot.SpringBean; +import org.springframework.util.CollectionUtils; + +/** + * Auditing and Reporting. + */ +public class Reports extends BasePage { + + private static final long serialVersionUID = -2071214196989178694L; + + private static final int WIN_HEIGHT = 500; + + private static final int WIN_WIDTH = 700; + + @SpringBean + private LoggerRestClient loggerRestClient; + + @SpringBean + private PreferenceManager prefMan; + + private WebMarkupContainer reportContainer; + + private WebMarkupContainer auditContainer; + + private int paginatorRows; + + private final ModalWindow window; + + public Reports(final PageParameters parameters) { + super(parameters); + + window = new ModalWindow("reportWin"); + window.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + window.setInitialHeight(WIN_HEIGHT); + window.setInitialWidth(WIN_WIDTH); + window.setCookieName("view-report-win"); + add(window); + + setupReport(); + setupAudit(); + } + + private void setupReport() { + reportContainer = new WebMarkupContainer("reportContainer"); + setWindowClosedCallback(window, reportContainer); + + MetaDataRoleAuthorizationStrategy.authorize(reportContainer, RENDER, + xmlRolesReader.getEntitlement("Reports", "list")); + + paginatorRows = prefMan.getPaginatorRows(getRequest(), Constants.PREF_REPORT_PAGINATOR_ROWS); + + List<IColumn<ReportTO, String>> columns = new ArrayList<>(); + columns.add(new PropertyColumn<ReportTO, String>(new ResourceModel("key"), "key", "key")); + columns.add(new PropertyColumn<ReportTO, String>(new ResourceModel("name"), "name", "name")); + columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("lastExec"), "lastExec", "lastExec")); + columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("nextExec"), "nextExec", "nextExec")); + columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("startDate"), "startDate", "startDate")); + columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("endDate"), "endDate", "endDate")); + columns.add(new PropertyColumn<ReportTO, String>( + new ResourceModel("latestExecStatus"), "latestExecStatus", "latestExecStatus")); + columns.add(new ActionColumn<ReportTO, String>(new ResourceModel("actions", "")) { + + private static final long serialVersionUID = 2054811145491901166L; + + @Override + public ActionLinksPanel getActions(final String componentId, final IModel<ReportTO> model) { + + final ReportTO reportTO = model.getObject(); + + final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, getPageReference()); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + + window.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + return new ReportModalPage(window, reportTO, Reports.this.getPageReference()); + } + }); + + window.show(target); + } + }, ActionLink.ActionType.EDIT, "Reports"); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + try { + reportRestClient.startExecution(reportTO.getKey()); + getSession().info(getString(Constants.OPERATION_SUCCEEDED)); + } catch (SyncopeClientException scce) { + error(scce.getMessage()); + } + + feedbackPanel.refresh(target); + target.add(reportContainer); + } + }, ActionLink.ActionType.EXECUTE, "Reports"); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + try { + reportRestClient.delete(reportTO.getKey()); + info(getString(Constants.OPERATION_SUCCEEDED)); + } catch (SyncopeClientException scce) { + error(scce.getMessage()); + } + target.add(reportContainer); + feedbackPanel.refresh(target); + } + }, ActionLink.ActionType.DELETE, "Reports"); + + return panel; + } + + @Override + public Component getHeader(final String componentId) { + final ActionLinksPanel panel = new ActionLinksPanel(componentId, new Model(), getPageReference()); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(final AjaxRequestTarget target) { + if (target != null) { + target.add(reportContainer); + } + } + }, ActionLink.ActionType.RELOAD, TASKS, "list"); + + return panel; + } + }); + + final AjaxFallbackDefaultDataTable<ReportTO, String> reportTable = + new AjaxFallbackDefaultDataTable<>("reportTable", columns, new ReportProvider(), paginatorRows); + + reportContainer.add(reportTable); + reportContainer.setOutputMarkupId(true); + + add(reportContainer); + + @SuppressWarnings("rawtypes") + Form paginatorForm = new Form("paginatorForm"); + + MetaDataRoleAuthorizationStrategy.authorize(paginatorForm, RENDER, + xmlRolesReader.getEntitlement("Reports", "list")); + + @SuppressWarnings({ "unchecked", "rawtypes" }) + final DropDownChoice rowsChooser = new DropDownChoice("rowsChooser", new PropertyModel(this, "paginatorRows"), + prefMan.getPaginatorChoices()); + + rowsChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { + + private static final long serialVersionUID = -1107858522700306810L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + prefMan.set(getRequest(), getResponse(), Constants.PREF_REPORT_PAGINATOR_ROWS, + String.valueOf(paginatorRows)); + reportTable.setItemsPerPage(paginatorRows); + + target.add(reportContainer); + } + }); + + paginatorForm.add(rowsChooser); + add(paginatorForm); + + AjaxLink<Void> createLink = new ClearIndicatingAjaxLink<Void>("createLink", getPageReference()) { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + protected void onClickInternal(final AjaxRequestTarget target) { + window.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + return new ReportModalPage(window, new ReportTO(), Reports.this.getPageReference()); + } + }); + + window.show(target); + } + }; + + MetaDataRoleAuthorizationStrategy.authorize(createLink, RENDER, xmlRolesReader.getEntitlement("Reports", + "create")); + + add(createLink); + } + + @SuppressWarnings("rawtypes") + private void setupAudit() { + auditContainer = new WebMarkupContainer("auditContainer"); + auditContainer.setOutputMarkupId(true); + add(auditContainer); + + MetaDataRoleAuthorizationStrategy.authorize( + auditContainer, RENDER, xmlRolesReader.getEntitlement("Audit", "list")); + + final Form form = new Form("auditForm"); + auditContainer.add(form); + + final List<String> events = new ArrayList<>(); + + final List<AuditLoggerName> audits = loggerRestClient.listAudits(); + for (AuditLoggerName audit : audits) { + events.add(AuditLoggerName.buildEvent( + audit.getType(), + audit.getCategory(), + audit.getSubcategory(), + audit.getEvent(), + audit.getResult())); + } + + final ListModel<String> model = new ListModel<>(new ArrayList<>(events)); + + form.add(new LoggerCategoryPanel( + "events", loggerRestClient.listEvents(), model, getPageReference(), "Reports") { + + private static final long serialVersionUID = 6113164334533550277L; + + @Override + protected String[] getListRoles() { + return new String[] { + xmlRolesReader.getEntitlement("Audit", "list") + }; + } + + @Override + protected String[] getChangeRoles() { + return new String[] { + xmlRolesReader.getEntitlement("Audit", "enable"), + xmlRolesReader.getEntitlement("Audit", "disable") + }; + } + + @Override + public void onEventAction(final IEvent<?> event) { + if (event.getPayload() instanceof SelectedEventsPanel.EventSelectionChanged) { + + final SelectedEventsPanel.EventSelectionChanged eventSelectionChanged = + (SelectedEventsPanel.EventSelectionChanged) event.getPayload(); + + for (String toBeRemoved : eventSelectionChanged.getToBeRemoved()) { + if (events.contains(toBeRemoved)) { + final Map.Entry<EventCategoryTO, Result> eventCategory = + AuditLoggerName.parseEventCategory(toBeRemoved); + + final AuditLoggerName auditLoggerName = new AuditLoggerName( + eventCategory.getKey().getType(), + eventCategory.getKey().getCategory(), + eventCategory.getKey().getSubcategory(), + CollectionUtils.isEmpty(eventCategory.getKey().getEvents()) + ? null : eventCategory.getKey().getEvents().iterator().next(), + eventCategory.getValue()); + + loggerRestClient.disableAudit(auditLoggerName); + events.remove(toBeRemoved); + } + } + + for (String toBeAdded : eventSelectionChanged.getToBeAdded()) { + if (!events.contains(toBeAdded)) { + final Map.Entry<EventCategoryTO, Result> eventCategory = + AuditLoggerName.parseEventCategory(toBeAdded); + + final AuditLoggerName auditLoggerName = new AuditLoggerName( + eventCategory.getKey().getType(), + eventCategory.getKey().getCategory(), + eventCategory.getKey().getSubcategory(), + CollectionUtils.isEmpty(eventCategory.getKey().getEvents()) + ? null : eventCategory.getKey().getEvents().iterator().next(), + eventCategory.getValue()); + + loggerRestClient.enableAudit(auditLoggerName); + events.add(toBeAdded); + } + } + } + } + }); + } + + private class ReportProvider extends SortableDataProvider<ReportTO, String> { + + private static final long serialVersionUID = -2311716167583335852L; + + private final SortableDataProviderComparator<ReportTO> comparator; + + public ReportProvider() { + super(); + + //Default sorting + setSort("key", SortOrder.ASCENDING); + comparator = new SortableDataProviderComparator<>(this); + } + + @Override + public Iterator<ReportTO> iterator(final long first, final long count) { + final int page = ((int) first / paginatorRows); + + final List<ReportTO> list = + reportRestClient.list((page < 0 ? 0 : page) + 1, paginatorRows, getSort()); + Collections.sort(list, comparator); + return list.iterator(); + } + + @Override + public long size() { + return reportRestClient.count(); + } + + @Override + public IModel<ReportTO> model(final ReportTO configuration) { + + return new AbstractReadOnlyModel<ReportTO>() { + + private static final long serialVersionUID = 4921104837546595602L; + + @Override + public ReportTO getObject() { + return configuration; + } + }; + } + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/RequestPasswordResetModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/RequestPasswordResetModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/RequestPasswordResetModalPage.java new file mode 100644 index 0000000..d8b762f --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/RequestPasswordResetModalPage.java @@ -0,0 +1,153 @@ +/* + * 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 org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.Mode; +import org.apache.syncope.client.console.rest.SecurityQuestionRestClient; +import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel; +import org.apache.syncope.common.lib.to.SecurityQuestionTO; +import org.apache.syncope.common.lib.to.UserTO; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; +import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.form.StatelessForm; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.spring.injection.annot.SpringBean; + +public class RequestPasswordResetModalPage extends BaseModalPage { + + private static final long serialVersionUID = -8419445804421211904L; + + @SpringBean + private SecurityQuestionRestClient securityQuestionRestClient; + + public RequestPasswordResetModalPage(final ModalWindow window) { + super(); + setOutputMarkupId(true); + + final boolean handleSecurityQuestion = userSelfRestClient.isPwdResetRequiringSecurityQuestions(); + + final StatelessForm<?> form = new StatelessForm<Object>(FORM); + form.setOutputMarkupId(true); + + final Label securityQuestionLabel = new Label("securityQuestionLabel", getString("securityQuestion")); + securityQuestionLabel.setOutputMarkupPlaceholderTag(true); + securityQuestionLabel.setVisible(handleSecurityQuestion); + form.add(securityQuestionLabel); + final AjaxTextFieldPanel securityQuestion = + new AjaxTextFieldPanel("securityQuestion", "securityQuestion", new Model<String>()); + securityQuestion.setReadOnly(true); + securityQuestion.setRequired(true); + securityQuestion.getField().setOutputMarkupId(true); + securityQuestion.setOutputMarkupPlaceholderTag(true); + securityQuestion.setVisible(handleSecurityQuestion); + form.add(securityQuestion); + + final AjaxTextFieldPanel username = + new AjaxTextFieldPanel("username", "username", new Model<String>()); + username.setRequired(true); + username.getField().setOutputMarkupId(true); + if (handleSecurityQuestion) { + username.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_BLUR) { + + private static final long serialVersionUID = -1107858522700306810L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + getFeedbackMessages().clear(); + target.add(feedbackPanel); + try { + SecurityQuestionTO read = securityQuestionRestClient.readByUser(username.getModelObject()); + securityQuestion.setModelObject(read.getContent()); + } catch (Exception e) { + LOG.error("While fetching security question for {}", username.getModelObject(), e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + securityQuestion.setModelObject(null); + } finally { + target.add(securityQuestion); + } + } + }); + } + form.add(username); + + final Label securityAnswerLabel = new Label("securityAnswerLabel", getString("securityAnswer")); + securityAnswerLabel.setOutputMarkupPlaceholderTag(true); + securityAnswerLabel.setVisible(handleSecurityQuestion); + form.add(securityAnswerLabel); + final AjaxTextFieldPanel securityAnswer = + new AjaxTextFieldPanel("securityAnswer", "securityAnswer", new Model<String>()); + securityAnswer.setRequired(handleSecurityQuestion); + securityAnswer.setOutputMarkupPlaceholderTag(true); + securityAnswer.setVisible(handleSecurityQuestion); + form.add(securityAnswer); + + final AjaxButton submit = new IndicatingAjaxButton(APPLY, new ResourceModel(SUBMIT, SUBMIT)) { + + private static final long serialVersionUID = -4804368561204623354L; + + @Override + protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + try { + userSelfRestClient.requestPasswordReset(username.getModelObject(), securityAnswer.getModelObject()); + + setResponsePage(new ResultStatusModalPage.Builder(window, new UserTO()). + mode(Mode.SELF).build()); + } catch (Exception e) { + LOG.error("While requesting password reset for {}", username.getModelObject(), e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + } + } + + @Override + protected void onError(final AjaxRequestTarget target, final Form<?> form) { + feedbackPanel.refresh(target); + } + }; + form.add(submit); + form.setDefaultButton(submit); + + final AjaxButton cancel = new IndicatingAjaxButton(CANCEL, new ResourceModel(CANCEL)) { + + private static final long serialVersionUID = -958724007591692537L; + + @Override + protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + window.close(target); + } + + @Override + protected void onError(final AjaxRequestTarget target, final Form<?> form) { + // do nothing + } + }; + cancel.setDefaultFormProcessing(false); + form.add(cancel); + + add(form); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/ResourceModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/ResourceModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/ResourceModalPage.java new file mode 100644 index 0000000..d6f69cf --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/ResourceModalPage.java @@ -0,0 +1,214 @@ +/* + * 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 org.apache.commons.lang3.StringUtils; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.panels.AnnotatedBeanPanel; +import org.apache.syncope.client.console.panels.ResourceConnConfPanel; +import org.apache.syncope.client.console.panels.ResourceDetailsPanel; +import org.apache.syncope.client.console.panels.ResourceMappingPanel; +import org.apache.syncope.client.console.panels.ResourceSecurityPanel; +import org.apache.syncope.common.lib.to.MappingItemTO; +import org.apache.syncope.common.lib.to.ResourceTO; +import org.apache.syncope.common.lib.types.AttributableType; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; +import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy; +import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +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.Model; +import org.apache.wicket.model.ResourceModel; + +/** + * Modal window with Resource form. + */ +public class ResourceModalPage extends BaseModalPage { + + private static final long serialVersionUID = 1734415311027284221L; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public ResourceModalPage(final PageReference pageRef, final ModalWindow window, final ResourceTO resourceTO, + final boolean createFlag) { + + super(); + + this.add(new Label("new", StringUtils.isBlank(resourceTO.getKey()) + ? new ResourceModel("new") + : new Model(StringUtils.EMPTY))); + this.add(new Label("name", StringUtils.isBlank(resourceTO.getKey()) + ? StringUtils.EMPTY + : resourceTO.getKey())); + + final Form<ResourceTO> form = new Form<>(FORM); + form.setModel(new CompoundPropertyModel<>(resourceTO)); + + //-------------------------------- + // Resource details panel + //-------------------------------- + form.add(new ResourceDetailsPanel("details", resourceTO, + resourceRestClient.getPropagationActionsClasses(), createFlag)); + + form.add(new AnnotatedBeanPanel("systeminformation", resourceTO)); + //-------------------------------- + + //-------------------------------- + // Resource mapping panels + //-------------------------------- + form.add(new ResourceMappingPanel("umapping", resourceTO, AttributableType.USER)); + form.add(new ResourceMappingPanel("rmapping", resourceTO, AttributableType.ROLE)); + //-------------------------------- + + //-------------------------------- + // Resource connector configuration panel + //-------------------------------- + ResourceConnConfPanel resourceConnConfPanel = new ResourceConnConfPanel("connconf", resourceTO, createFlag); + MetaDataRoleAuthorizationStrategy.authorize( + resourceConnConfPanel, ENABLE, xmlRolesReader.getEntitlement("Connectors", "read")); + form.add(resourceConnConfPanel); + //-------------------------------- + + //-------------------------------- + // Resource security panel + //-------------------------------- + form.add(new ResourceSecurityPanel("security", resourceTO)); + //-------------------------------- + + final AjaxButton submit = new IndicatingAjaxButton(APPLY, new ResourceModel(SUBMIT, SUBMIT)) { + + private static final long serialVersionUID = -958724007591692537L; + + @Override + protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + final ResourceTO resourceTO = (ResourceTO) form.getDefaultModelObject(); + + boolean accountIdError = false; + + if (resourceTO.getUmapping() == null || resourceTO.getUmapping().getItems().isEmpty()) { + resourceTO.setUmapping(null); + } else { + int uAccountIdCount = 0; + for (MappingItemTO item : resourceTO.getUmapping().getItems()) { + if (item.isAccountid()) { + uAccountIdCount++; + } + } + accountIdError = uAccountIdCount != 1; + } + + if (resourceTO.getRmapping() == null || resourceTO.getRmapping().getItems().isEmpty()) { + resourceTO.setRmapping(null); + } else { + int rAccountIdCount = 0; + for (MappingItemTO item : resourceTO.getRmapping().getItems()) { + if (item.isAccountid()) { + rAccountIdCount++; + } + } + accountIdError |= rAccountIdCount != 1; + } + + if (accountIdError) { + error(getString("accountIdValidation")); + feedbackPanel.refresh(target); + } else { + try { + if (createFlag) { + resourceRestClient.create(resourceTO); + } else { + resourceRestClient.update(resourceTO); + } + + if (pageRef != null && pageRef.getPage() instanceof AbstractBasePage) { + ((AbstractBasePage) pageRef.getPage()).setModalResult(true); + } + window.close(target); + } catch (Exception e) { + LOG.error("Failure managing resource {}", resourceTO, e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + } + } + } + + @Override + protected void onError(final AjaxRequestTarget target, final Form<?> form) { + feedbackPanel.refresh(target); + } + }; + + form.add(submit); + form.setDefaultButton(submit); + + final AjaxButton cancel = new IndicatingAjaxButton(CANCEL, new ResourceModel(CANCEL)) { + + private static final long serialVersionUID = -958724007591692537L; + + @Override + protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + window.close(target); + } + + @Override + protected void onError(final AjaxRequestTarget target, final Form<?> form) { + } + }; + + cancel.setDefaultFormProcessing(false); + form.add(cancel); + + add(form); + + MetaDataRoleAuthorizationStrategy.authorize( + submit, ENABLE, xmlRolesReader.getEntitlement("Resources", createFlag ? "create" : "update")); + } + + /** + * Generic resource event. + */ + public static class ResourceEvent { + + /** + * Request target. + */ + private final AjaxRequestTarget target; + + /** + * Constructor. + * + * @param target request target. + */ + public ResourceEvent(final AjaxRequestTarget target) { + this.target = target; + } + + /** + * Target getter. + * + * @return request target. + */ + public AjaxRequestTarget getTarget() { + return target; + } + } +}
