You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2015/02/13 12:44:43 UTC
[39/51] [partial] syncope git commit: [SYNCOPE-620] Re-organization
completed
http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/Schema.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Schema.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Schema.java
new file mode 100644
index 0000000..c47edcd
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Schema.java
@@ -0,0 +1,467 @@
+/*
+ * 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.util.AbstractMap.SimpleEntry;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.PreferenceManager;
+import org.apache.syncope.client.console.commons.SchemaModalPageFactory;
+import org.apache.syncope.client.console.commons.SelectChoiceRenderer;
+import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.panels.JQueryUITabbedPanel;
+import org.apache.syncope.client.console.rest.SchemaRestClient;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.common.lib.to.AbstractSchemaTO;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.wicket.AttributeModifier;
+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.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.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
+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.PropertyColumn;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
+import org.apache.wicket.extensions.markup.html.tabs.ITab;
+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.panel.Panel;
+import org.apache.wicket.markup.repeater.Item;
+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.spring.injection.annot.SpringBean;
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
+import org.springframework.util.ReflectionUtils;
+
+/**
+ * Schema WebPage.
+ */
+@SuppressWarnings({ "unchecked", "rawtypes" })
+public class Schema extends BasePage {
+
+ private static final long serialVersionUID = 8091922398776299403L;
+
+ private static final Map<SchemaType, List<String>> COL_NAMES = new HashMap<SchemaType, List<String>>() {
+
+ private static final long serialVersionUID = 3109256773218160485L;
+
+ {
+ put(SchemaType.PLAIN, Arrays.asList(new String[] { "key", "type",
+ "mandatoryCondition", "uniqueConstraint", "multivalue", "readonly" }));
+ put(SchemaType.DERIVED, Arrays.asList(new String[] { "key", "expression" }));
+ put(SchemaType.VIRTUAL, Arrays.asList(new String[] { "key", "readonly" }));
+ }
+ };
+
+ private static final Map<Map.Entry<AttributableType, SchemaType>, String> PAGINATOR_ROWS_KEYS =
+ new HashMap<Map.Entry<AttributableType, SchemaType>, String>() {
+
+ private static final long serialVersionUID = 3109256773218160485L;
+
+ {
+ put(new SimpleEntry<>(AttributableType.CONFIGURATION, SchemaType.PLAIN),
+ Constants.PREF_CONF_SCHEMA_PAGINATOR_ROWS);
+ put(new SimpleEntry<>(AttributableType.USER, SchemaType.PLAIN),
+ Constants.PREF_USER_SCHEMA_PAGINATOR_ROWS);
+ put(new SimpleEntry<>(AttributableType.USER, SchemaType.DERIVED),
+ Constants.PREF_USER_DER_SCHEMA_PAGINATOR_ROWS);
+ put(new SimpleEntry<>(AttributableType.USER, SchemaType.VIRTUAL),
+ Constants.PREF_USER_VIR_SCHEMA_PAGINATOR_ROWS);
+ put(new SimpleEntry<>(AttributableType.MEMBERSHIP, SchemaType.PLAIN),
+ Constants.PREF_MEMBERSHIP_SCHEMA_PAGINATOR_ROWS);
+ put(new SimpleEntry<>(AttributableType.MEMBERSHIP, SchemaType.DERIVED),
+ Constants.PREF_MEMBERSHIP_DER_SCHEMA_PAGINATOR_ROWS);
+ put(new SimpleEntry<>(AttributableType.MEMBERSHIP, SchemaType.VIRTUAL),
+ Constants.PREF_MEMBERSHIP_VIR_SCHEMA_PAGINATOR_ROWS);
+ put(new SimpleEntry<>(AttributableType.ROLE, SchemaType.PLAIN),
+ Constants.PREF_ROLE_SCHEMA_PAGINATOR_ROWS);
+ put(new SimpleEntry<>(AttributableType.ROLE, SchemaType.DERIVED),
+ Constants.PREF_ROLE_DER_SCHEMA_PAGINATOR_ROWS);
+ put(new SimpleEntry<>(AttributableType.ROLE, SchemaType.VIRTUAL),
+ Constants.PREF_ROLE_VIR_SCHEMA_PAGINATOR_ROWS);
+ }
+ };
+
+ private static final int WIN_WIDTH = 600;
+
+ private static final int WIN_HEIGHT = 200;
+
+ private static final int PLAIN_WIN_HEIGHT = 500;
+
+ @SpringBean
+ private SchemaRestClient restClient;
+
+ @SpringBean
+ private PreferenceManager prefMan;
+
+ private final String allowedCreateRoles = xmlRolesReader.getEntitlement("Schema", "create");
+
+ private final String allowedReadRoles = xmlRolesReader.getEntitlement("Schema", "read");
+
+ private final String allowedDeleteRoles = xmlRolesReader.getEntitlement("Schema", "delete");
+
+ public Schema() {
+ super();
+
+ for (final AttributableType attrType : AttributableType.values()) {
+ final String attrTypeAsString = attrType.name().toLowerCase();
+
+ List<ITab> tabs = new ArrayList<>();
+
+ for (final SchemaType schemaType : SchemaType.values()) {
+ if (attrType != AttributableType.CONFIGURATION || schemaType == SchemaType.PLAIN) {
+ final String schemaTypeAsString = schemaType.name().toLowerCase();
+
+ tabs.add(new AbstractTab(new Model<>(getString(schemaTypeAsString))) {
+
+ private static final long serialVersionUID = -5861786415855103549L;
+
+ @Override
+ public WebMarkupContainer getPanel(final String panelId) {
+ return new SchemaTypePanel(panelId, attrType, schemaType);
+ }
+ });
+ }
+ }
+
+ add(new JQueryUITabbedPanel(attrTypeAsString + "Tabs", tabs));
+ }
+ }
+
+ private <T extends AbstractSchemaModalPage> List<IColumn> getColumns(
+ final WebMarkupContainer webContainer, final ModalWindow modalWindow,
+ final AttributableType attributableType, final SchemaType schemaType,
+ final Collection<String> fields) {
+
+ List<IColumn> columns = new ArrayList<IColumn>();
+
+ for (final String field : fields) {
+ final Field clazzField = ReflectionUtils.findField(schemaType.getToClass(), field);
+
+ if (clazzField != null) {
+ if (clazzField.getType().equals(Boolean.class) || clazzField.getType().equals(boolean.class)) {
+ columns.add(new AbstractColumn<AbstractSchemaTO, String>(new ResourceModel(field)) {
+
+ private static final long serialVersionUID = 8263694778917279290L;
+
+ @Override
+ public void populateItem(final Item<ICellPopulator<AbstractSchemaTO>> item,
+ final String componentId, final IModel<AbstractSchemaTO> model) {
+
+ BeanWrapper bwi = new BeanWrapperImpl(model.getObject());
+ Object obj = bwi.getPropertyValue(field);
+
+ item.add(new Label(componentId, ""));
+ item.add(new AttributeModifier("class", new Model<String>(obj.toString())));
+ }
+
+ @Override
+ public String getCssClass() {
+ return "small_fixedsize";
+ }
+ });
+ } else {
+ IColumn column = new PropertyColumn(new ResourceModel(field), field, field) {
+
+ private static final long serialVersionUID = 3282547854226892169L;
+
+ @Override
+ public String getCssClass() {
+ String css = super.getCssClass();
+ if ("key".equals(field)) {
+ css = StringUtils.isBlank(css)
+ ? "medium_fixedsize"
+ : css + " medium_fixedsize";
+ }
+ return css;
+ }
+ };
+ columns.add(column);
+ }
+ }
+ }
+
+ columns.add(new AbstractColumn<AbstractSchemaTO, String>(new ResourceModel("actions", "")) {
+
+ private static final long serialVersionUID = 2054811145491901166L;
+
+ @Override
+ public String getCssClass() {
+ return "action";
+ }
+
+ @Override
+ public void populateItem(final Item<ICellPopulator<AbstractSchemaTO>> item, final String componentId,
+ final IModel<AbstractSchemaTO> model) {
+
+ final AbstractSchemaTO schemaTO = model.getObject();
+
+ final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, getPageReference());
+
+ panel.addWithRoles(new ActionLink() {
+
+ private static final long serialVersionUID = -3722207913631435501L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+ modalWindow.setPageCreator(new ModalWindow.PageCreator() {
+
+ private static final long serialVersionUID = -7834632442532690940L;
+
+ @Override
+ public Page createPage() {
+ AbstractSchemaModalPage page = SchemaModalPageFactory.getSchemaModalPage(
+ attributableType, schemaType);
+
+ page.setSchemaModalPage(Schema.this.getPageReference(), modalWindow, schemaTO, false);
+
+ return page;
+ }
+ });
+
+ modalWindow.show(target);
+ }
+ }, ActionType.EDIT, allowedReadRoles);
+
+ panel.addWithRoles(new ActionLink() {
+
+ private static final long serialVersionUID = -3722207913631435501L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+
+ switch (schemaType) {
+ case DERIVED:
+ restClient.deleteDerSchema(attributableType, schemaTO.getKey());
+ break;
+
+ case VIRTUAL:
+ restClient.deleteVirSchema(attributableType, schemaTO.getKey());
+ break;
+
+ default:
+ restClient.deletePlainSchema(attributableType, schemaTO.getKey());
+ break;
+ }
+
+ info(getString(Constants.OPERATION_SUCCEEDED));
+ feedbackPanel.refresh(target);
+
+ target.add(webContainer);
+ }
+ }, ActionType.DELETE, allowedDeleteRoles);
+
+ item.add(panel);
+ }
+ });
+
+ return columns;
+ }
+
+ private Form<Void> getPaginatorForm(final WebMarkupContainer webContainer,
+ final AjaxFallbackDefaultDataTable dataTable,
+ final String formname, final SchemaTypePanel schemaTypePanel, final String rowsPerPagePrefName) {
+
+ Form<Void> form = new Form<Void>(formname);
+
+ final DropDownChoice<Integer> rowChooser = new DropDownChoice<Integer>("rowsChooser",
+ new PropertyModel<Integer>(schemaTypePanel, "pageRows"), prefMan.getPaginatorChoices(),
+ new SelectChoiceRenderer<Integer>());
+
+ rowChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+ private static final long serialVersionUID = -1107858522700306810L;
+
+ @Override
+ protected void onUpdate(final AjaxRequestTarget target) {
+ prefMan.set(getRequest(), getResponse(), rowsPerPagePrefName, rowChooser.getInput());
+ dataTable.setItemsPerPage(rowChooser.getModelObject());
+
+ target.add(webContainer);
+ }
+ });
+
+ form.add(rowChooser);
+
+ return form;
+ }
+
+ private <T extends AbstractSchemaModalPage> AjaxLink<Void> getCreateSchemaLink(final ModalWindow modalWindow,
+ final AttributableType attrType, final SchemaType schemaType, final String winLinkName) {
+
+ AjaxLink<Void> link = new ClearIndicatingAjaxLink<Void>(winLinkName, getPageReference()) {
+
+ private static final long serialVersionUID = -7978723352517770644L;
+
+ @Override
+ protected void onClickInternal(final AjaxRequestTarget target) {
+ modalWindow.setPageCreator(new ModalWindow.PageCreator() {
+
+ private static final long serialVersionUID = -7834632442532690940L;
+
+ @Override
+ public Page createPage() {
+ T page = SchemaModalPageFactory.getSchemaModalPage(attrType, schemaType);
+ page.setSchemaModalPage(Schema.this.getPageReference(), modalWindow, null, true);
+
+ return page;
+ }
+ });
+
+ modalWindow.show(target);
+ }
+ };
+
+ MetaDataRoleAuthorizationStrategy.authorize(link, ENABLE, allowedCreateRoles);
+
+ return link;
+
+ }
+
+ private class SchemaProvider extends SortableDataProvider<AbstractSchemaTO, String> {
+
+ private static final long serialVersionUID = -185944053385660794L;
+
+ private final SortableDataProviderComparator<AbstractSchemaTO> comparator;
+
+ private final AttributableType attrType;
+
+ private final SchemaType schemaType;
+
+ public SchemaProvider(final AttributableType attrType, final SchemaType schemaType) {
+ super();
+
+ this.attrType = attrType;
+ this.schemaType = schemaType;
+
+ // Default sorting
+ setSort("key", SortOrder.ASCENDING);
+
+ comparator = new SortableDataProviderComparator<>(this);
+ }
+
+ @Override
+ public Iterator<AbstractSchemaTO> iterator(final long first, final long count) {
+ @SuppressWarnings("unchecked")
+ List<AbstractSchemaTO> list =
+ (List<AbstractSchemaTO>) restClient.getSchemas(this.attrType, this.schemaType);
+
+ Collections.sort(list, comparator);
+
+ return list.subList((int) first, (int) first + (int) count).iterator();
+ }
+
+ @Override
+ public long size() {
+ return restClient.getSchemas(this.attrType, this.schemaType).size();
+ }
+
+ @Override
+ public IModel<AbstractSchemaTO> model(final AbstractSchemaTO object) {
+ return new CompoundPropertyModel<AbstractSchemaTO>(object);
+ }
+ }
+
+ private class SchemaTypePanel extends Panel {
+
+ private static final long serialVersionUID = 2854050613688773575L;
+
+ private int pageRows;
+
+ private final AttributableType attrType;
+
+ private final SchemaType schemaType;
+
+ public SchemaTypePanel(final String id, final AttributableType attrType, final SchemaType schemaType) {
+ super(id);
+
+ this.attrType = attrType;
+ this.schemaType = schemaType;
+
+ setup();
+ }
+
+ private void setup() {
+ ModalWindow editSchemaWin = new ModalWindow("editSchemaWin");
+ editSchemaWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+ editSchemaWin.setInitialWidth(WIN_WIDTH);
+ if (schemaType == SchemaType.PLAIN) {
+ editSchemaWin.setInitialHeight(PLAIN_WIN_HEIGHT);
+ } else {
+ editSchemaWin.setInitialHeight(WIN_HEIGHT);
+ }
+ editSchemaWin.setCookieName("editSchemaWin");
+ editSchemaWin.setMarkupId("editSchemaWin");
+ add(editSchemaWin);
+
+ WebMarkupContainer schemaWrapContainer = new WebMarkupContainer("schemaWrapContainer");
+ schemaWrapContainer.setOutputMarkupId(true);
+ if (schemaType != SchemaType.VIRTUAL) {
+ schemaWrapContainer.add(new AttributeModifier("style", "width:auto;"));
+ }
+ add(schemaWrapContainer);
+
+ WebMarkupContainer schemaContainer = new WebMarkupContainer("schemaContainer");
+ schemaContainer.setOutputMarkupId(true);
+ schemaWrapContainer.add(schemaContainer);
+ setWindowClosedCallback(editSchemaWin, schemaContainer);
+
+ final String paginatorRowsKey = PAGINATOR_ROWS_KEYS.get(
+ new SimpleEntry<AttributableType, SchemaType>(attrType, schemaType));
+ pageRows = prefMan.getPaginatorRows(getRequest(), paginatorRowsKey);
+
+ List<IColumn> tableCols = getColumns(schemaContainer, editSchemaWin, attrType,
+ schemaType, COL_NAMES.get(schemaType));
+ final AjaxFallbackDefaultDataTable table = new AjaxFallbackDefaultDataTable("datatable", tableCols,
+ new SchemaProvider(attrType, schemaType), pageRows);
+ table.setOutputMarkupId(true);
+ schemaContainer.add(table);
+
+ schemaWrapContainer.add(getPaginatorForm(schemaContainer, table, "paginatorForm", this, paginatorRowsKey));
+
+ add(getCreateSchemaLink(editSchemaWin, attrType, schemaType, "createSchemaLink"));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/SecurityQuestionModalPage.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/SecurityQuestionModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/SecurityQuestionModalPage.java
new file mode 100644
index 0000000..12bfc2b
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/SecurityQuestionModalPage.java
@@ -0,0 +1,111 @@
+/*
+ * 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.rest.SecurityQuestionRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.SecurityQuestionTO;
+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.form.Form;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+class SecurityQuestionModalPage extends BaseModalPage {
+
+ private static final long serialVersionUID = -6709838862698327502L;
+
+ @SpringBean
+ private SecurityQuestionRestClient restClient;
+
+ public SecurityQuestionModalPage(final PageReference pageRef, final ModalWindow window,
+ final SecurityQuestionTO securityQuestionTO, final boolean createFlag) {
+
+ final Form<SecurityQuestionTO> form =
+ new Form<SecurityQuestionTO>(FORM, new CompoundPropertyModel<SecurityQuestionTO>(securityQuestionTO));
+
+ final AjaxTextFieldPanel contentFieldPanel =
+ new AjaxTextFieldPanel("content", "content", new PropertyModel<String>(securityQuestionTO, "content"));
+ contentFieldPanel.setRequired(true);
+ form.add(contentFieldPanel);
+
+ AjaxButton submit = new IndicatingAjaxButton(APPLY, new Model<String>(getString(SUBMIT))) {
+
+ private static final long serialVersionUID = -958724007591692537L;
+
+ @Override
+ protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+ try {
+ if (createFlag) {
+ restClient.create(securityQuestionTO);
+ } else {
+ restClient.update(securityQuestionTO);
+ }
+ info(getString(Constants.OPERATION_SUCCEEDED));
+
+ Configuration callerPage = (Configuration) pageRef.getPage();
+ callerPage.setModalResult(true);
+
+ window.close(target);
+ } catch (SyncopeClientException scee) {
+ error(getString(Constants.ERROR) + ": " + scee.getMessage());
+ feedbackPanel.refresh(target);
+ }
+ }
+
+ @Override
+ protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+ feedbackPanel.refresh(target);
+ }
+ };
+
+ 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);
+ }
+ };
+
+ cancel.setDefaultFormProcessing(false);
+
+ String allowedRoles = createFlag
+ ? xmlRolesReader.getEntitlement("SecurityQuestion", "create")
+ : xmlRolesReader.getEntitlement("SecurityQuestion", "update");
+ MetaDataRoleAuthorizationStrategy.authorize(submit, ENABLE, allowedRoles);
+
+ form.add(submit);
+ form.setDefaultButton(submit);
+
+ 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/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
new file mode 100644
index 0000000..9d0ede2
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModalPage.java
@@ -0,0 +1,644 @@
+/*
+ * 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.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.wicket.ajax.markup.html.ClearIndicatingAjaxButton;
+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.AbstractSubjectTO;
+import org.apache.syncope.common.lib.to.BulkActionResult;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.ResourceAssociationActionType;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+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 AbstractSubjectTO> extends AbstractStatusModalPage {
+
+ private static final long serialVersionUID = -9148734710505211261L;
+
+ private final AbstractSubjectTO subjectTO;
+
+ private int rowsPerPage = 10;
+
+ final StatusUtils statusUtils;
+
+ final boolean statusOnly;
+
+ // --------------------------------
+ // password management fields ..
+ // --------------------------------
+ final ClearIndicatingAjaxButton cancel;
+
+ final WebMarkupContainer pwdMgt;
+
+ final Form<?> pwdMgtForm;
+
+ final AjaxCheckBoxPanel changepwd;
+
+ final PasswordTextField password;
+
+ final PasswordTextField confirm;
+ // --------------------------------
+
+ final PageReference pageRef;
+
+ final ModalWindow window;
+
+ final ActionDataTablePanel<StatusBean, String> table;
+
+ final List<IColumn<StatusBean, String>> columns;
+
+ public StatusModalPage(
+ final PageReference pageRef,
+ final ModalWindow window,
+ final AbstractSubjectTO attributableTO) {
+
+ this(pageRef, window, attributableTO, false);
+ }
+
+ public StatusModalPage(
+ final PageReference pageRef,
+ final ModalWindow window,
+ final AbstractSubjectTO subjectTO,
+ final boolean statusOnly) {
+
+ super();
+
+ this.pageRef = pageRef;
+ this.window = window;
+ this.statusOnly = statusOnly;
+ this.subjectTO = subjectTO;
+
+ statusUtils = new StatusUtils(subjectTO instanceof UserTO ? userRestClient : roleRestClient);
+
+ add(new Label("displayName", subjectTO.getKey() + " "
+ + (subjectTO instanceof UserTO ? ((UserTO) subjectTO).getUsername() : ((RoleTO) subjectTO).getName())));
+
+ columns = new ArrayList<>();
+ columns.add(new AbstractColumn<StatusBean, String>(
+ new StringResourceModel("resourceName", this, null, "Resource name"), "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("accountLink", this, null, "Account link"), "accountLink", "accountLink"));
+
+ 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 = subjectTO instanceof RoleTO ? "Roles" : "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<Boolean>(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
+ window.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() {
+
+ private static final long serialVersionUID = -3722207913631435501L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+ try {
+ userRestClient.reactivate(
+ subjectTO.getETagValue(),
+ subjectTO.getKey(),
+ new ArrayList<>(table.getModelObject()));
+
+ ((BasePage) pageRef.getPage()).setModalResult(true);
+
+ window.close(target);
+ } catch (Exception e) {
+ LOG.error("Error enabling resources", e);
+ error(getString(Constants.ERROR) + ": " + e.getMessage());
+ feedbackPanel.refresh(target);
+ }
+ }
+ }, ActionLink.ActionType.REACTIVATE, pageId);
+
+ table.addAction(new ActionLink() {
+
+ private static final long serialVersionUID = -3722207913631435501L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+ try {
+ userRestClient.suspend(
+ subjectTO.getETagValue(),
+ subjectTO.getKey(),
+ new ArrayList<>(table.getModelObject()));
+
+ if (pageRef.getPage() instanceof BasePage) {
+ ((BasePage) pageRef.getPage()).setModalResult(true);
+ }
+
+ window.close(target);
+ } catch (Exception e) {
+ LOG.error("Error disabling resources", e);
+ error(getString(Constants.ERROR) + ": " + e.getMessage());
+ feedbackPanel.refresh(target);
+ }
+ }
+ }, ActionLink.ActionType.SUSPEND, pageId);
+ } else {
+ table.addAction(new ActionLink() {
+
+ private static final long serialVersionUID = -3722207913631435501L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+ try {
+ if (subjectTO instanceof UserTO) {
+ userRestClient.unlink(
+ subjectTO.getETagValue(),
+ subjectTO.getKey(),
+ new ArrayList<>(table.getModelObject()));
+ } else {
+ roleRestClient.unlink(
+ subjectTO.getETagValue(),
+ subjectTO.getKey(),
+ new ArrayList<>(table.getModelObject()));
+ }
+
+ ((BasePage) pageRef.getPage()).setModalResult(true);
+ window.close(target);
+ } catch (Exception e) {
+ LOG.error("Error unlinking resources", e);
+ error(getString(Constants.ERROR) + ": " + e.getMessage());
+ feedbackPanel.refresh(target);
+ }
+ }
+ }, ActionLink.ActionType.UNLINK, pageId);
+
+ table.addAction(new ActionLink() {
+
+ private static final long serialVersionUID = -3722207913631435501L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+ try {
+ if (subjectTO instanceof UserTO) {
+ userRestClient.link(
+ subjectTO.getETagValue(),
+ subjectTO.getKey(),
+ new ArrayList<>(table.getModelObject()));
+ } else {
+ roleRestClient.link(
+ subjectTO.getETagValue(),
+ subjectTO.getKey(),
+ new ArrayList<>(table.getModelObject()));
+ }
+
+ ((BasePage) pageRef.getPage()).setModalResult(true);
+ window.close(target);
+ } catch (Exception e) {
+ LOG.error("Error linking resources", e);
+ error(getString(Constants.ERROR) + ": " + e.getMessage());
+ feedbackPanel.refresh(target);
+ }
+ }
+ }, ActionLink.ActionType.LINK, pageId);
+
+ table.addAction(new ActionLink() {
+
+ private static final long serialVersionUID = -3722207913631435501L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+ try {
+ BulkActionResult bulkActionResult;
+ if (subjectTO instanceof UserTO) {
+ bulkActionResult = userRestClient.deprovision(
+ subjectTO.getETagValue(),
+ subjectTO.getKey(),
+ new ArrayList<>(table.getModelObject()));
+ } else {
+ bulkActionResult = roleRestClient.deprovision(
+ subjectTO.getETagValue(),
+ subjectTO.getKey(),
+ new ArrayList<>(table.getModelObject()));
+ }
+
+ ((BasePage) pageRef.getPage()).setModalResult(true);
+ loadBulkActionResultPage(table.getModelObject(), bulkActionResult);
+ } catch (Exception e) {
+ LOG.error("Error de-provisioning user", e);
+ error(getString(Constants.ERROR) + ": " + e.getMessage());
+ feedbackPanel.refresh(target);
+ }
+ }
+ }, ActionLink.ActionType.DEPROVISION, pageId);
+
+ table.addAction(new ActionLink() {
+
+ private static final long serialVersionUID = -3722207913631435501L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+
+ if (subjectTO instanceof UserTO) {
+ StatusModalPage.this.passwordManagement(
+ target, ResourceAssociationActionType.PROVISION, table.getModelObject());
+ } else {
+ try {
+ final BulkActionResult bulkActionResult = roleRestClient.provision(
+ subjectTO.getETagValue(),
+ subjectTO.getKey(),
+ new ArrayList<>(table.getModelObject()));
+
+ ((BasePage) pageRef.getPage()).setModalResult(true);
+ loadBulkActionResultPage(table.getModelObject(), bulkActionResult);
+ } catch (Exception e) {
+ LOG.error("Error provisioning user", e);
+ error(getString(Constants.ERROR) + ": " + e.getMessage());
+ feedbackPanel.refresh(target);
+ }
+ }
+ }
+ }.feedbackPanelAutomaticReload(!(subjectTO instanceof UserTO)), ActionLink.ActionType.PROVISION, pageId);
+
+ table.addAction(new ActionLink() {
+
+ private static final long serialVersionUID = -3722207913631435501L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+ try {
+ final BulkActionResult bulkActionResult;
+ if (subjectTO instanceof UserTO) {
+ bulkActionResult = userRestClient.unassign(
+ subjectTO.getETagValue(),
+ subjectTO.getKey(),
+ new ArrayList<>(table.getModelObject()));
+ } else {
+ bulkActionResult = roleRestClient.unassign(
+ subjectTO.getETagValue(),
+ subjectTO.getKey(),
+ new ArrayList<>(table.getModelObject()));
+ }
+
+ ((BasePage) pageRef.getPage()).setModalResult(true);
+ loadBulkActionResultPage(table.getModelObject(), bulkActionResult);
+ } catch (Exception e) {
+ LOG.error("Error unassigning resources", e);
+ error(getString(Constants.ERROR) + ": " + e.getMessage());
+ feedbackPanel.refresh(target);
+ }
+ }
+ }, ActionLink.ActionType.UNASSIGN, pageId);
+
+ table.addAction(new ActionLink() {
+
+ private static final long serialVersionUID = -3722207913631435501L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+ if (subjectTO instanceof UserTO) {
+ StatusModalPage.this.passwordManagement(
+ target, ResourceAssociationActionType.ASSIGN, table.getModelObject());
+ } else {
+ try {
+ final BulkActionResult bulkActionResult = roleRestClient.assign(
+ subjectTO.getETagValue(),
+ subjectTO.getKey(),
+ new ArrayList<>(table.getModelObject()));
+
+ ((BasePage) pageRef.getPage()).setModalResult(true);
+ loadBulkActionResultPage(table.getModelObject(), bulkActionResult);
+ } catch (Exception e) {
+ LOG.error("Error assigning resources", e);
+ error(getString(Constants.ERROR) + ": " + e.getMessage());
+ feedbackPanel.refresh(target);
+ }
+ }
+ }
+ }.feedbackPanelAutomaticReload(!(subjectTO instanceof UserTO)), ActionLink.ActionType.ASSIGN, pageId);
+ }
+
+ table.addCancelButton(window);
+ add(table);
+ }
+
+ private class AttributableStatusProvider extends AbstractStatusBeanProvider {
+
+ private static final long serialVersionUID = 4586969457669796621L;
+
+ public AttributableStatusProvider() {
+ super(statusOnly ? "resourceName" : "accountLink");
+ }
+
+ @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(subjectTO);
+
+ final List<StatusBean> statusBeans = new ArrayList<StatusBean>(connObjects.size() + 1);
+
+ for (ConnObjectWrapper entry : connObjects) {
+ final StatusBean statusBean = statusUtils.getStatusBean(
+ subjectTO,
+ entry.getResourceName(),
+ entry.getConnObjectTO(),
+ subjectTO instanceof RoleTO);
+
+ statusBeans.add(statusBean);
+ resources.remove(entry.getResourceName());
+ }
+
+ if (statusOnly) {
+ final StatusBean syncope = new StatusBean(subjectTO, "Syncope");
+
+ syncope.setAccountLink(((UserTO) subjectTO).getUsername());
+
+ Status syncopeStatus = Status.UNDEFINED;
+ if (((UserTO) subjectTO).getStatus() != null) {
+ try {
+ syncopeStatus = Status.valueOf(((UserTO) subjectTO).getStatus().toUpperCase());
+ } catch (IllegalArgumentException e) {
+ LOG.warn("Unexpected status found: {}", ((UserTO) subjectTO).getStatus(), e);
+ }
+ }
+ syncope.setStatus(syncopeStatus);
+
+ statusBeans.add(syncope);
+ } else {
+ for (String resource : resources) {
+ final StatusBean statusBean = statusUtils.getStatusBean(
+ subjectTO,
+ resource,
+ null,
+ subjectTO instanceof RoleTO);
+
+ statusBean.setLinked(false);
+ statusBeans.add(statusBean);
+ }
+ }
+
+ return statusBeans;
+ }
+ }
+
+ private void passwordManagement(
+ final AjaxRequestTarget target,
+ final ResourceAssociationActionType 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(
+ subjectTO.getETagValue(),
+ subjectTO.getKey(),
+ new ArrayList<>(selection),
+ changepwd.getModelObject(),
+ password.getModelObject());
+ break;
+ case PROVISION:
+ bulkActionResult = userRestClient.provision(
+ subjectTO.getETagValue(),
+ subjectTO.getKey(),
+ new ArrayList<>(selection),
+ changepwd.getModelObject(),
+ password.getModelObject());
+ break;
+ default:
+ bulkActionResult = null;
+ // ignore
+ }
+
+ ((BasePage) pageRef.getPage()).setModalResult(true);
+
+ if (bulkActionResult != null) {
+ loadBulkActionResultPage(selection, bulkActionResult);
+ } else {
+
+ target.add(((BasePage) pageRef.getPage()).getFeedbackPanel());
+ window.close(target);
+ }
+ } catch (Exception e) {
+ LOG.error("Error provisioning resources", e);
+ error(getString(Constants.ERROR) + ": " + e.getMessage());
+ feedbackPanel.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 Collection<StatusBean> selection, final BulkActionResult bulkActionResult) {
+ final List<String> resources = new ArrayList<String>(selection.size());
+ for (StatusBean statusBean : selection) {
+ resources.add(statusBean.getResourceName());
+ }
+
+ final List<ConnObjectWrapper> connObjects =
+ statusUtils.getConnectorObjects(Collections.singletonList(subjectTO), resources);
+
+ final List<StatusBean> statusBeans = new ArrayList<StatusBean>(connObjects.size());
+
+ for (ConnObjectWrapper entry : connObjects) {
+ final StatusBean statusBean = statusUtils.getStatusBean(
+ subjectTO,
+ entry.getResourceName(),
+ entry.getConnObjectTO(),
+ subjectTO instanceof RoleTO);
+
+ statusBeans.add(statusBean);
+ }
+
+ setResponsePage(new BulkActionResultModalPage<StatusBean, String>(
+ window,
+ statusBeans,
+ columns,
+ bulkActionResult,
+ "resourceName"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/SyncTaskModalPage.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/SyncTaskModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/SyncTaskModalPage.java
new file mode 100644
index 0000000..544f670
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/SyncTaskModalPage.java
@@ -0,0 +1,73 @@
+/*
+ * 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.List;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.common.lib.to.SchedTaskTO;
+import org.apache.syncope.common.lib.to.SyncTaskTO;
+import org.apache.syncope.common.lib.types.MatchingRule;
+import org.apache.syncope.common.lib.types.UnmatchingRule;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.model.PropertyModel;
+
+/**
+ * Modal window with Sync Task form.
+ */
+public class SyncTaskModalPage extends AbstractSyncTaskModalPage {
+
+ private static final long serialVersionUID = 2148403203517274669L;
+
+ public SyncTaskModalPage(final ModalWindow window, final SyncTaskTO taskTO, final PageReference pageRef) {
+
+ super(window, taskTO, pageRef);
+
+ // set default Matching rule
+ ((DropDownChoice) matchingRule.getField()).setDefaultModelObject(taskTO.getMatchingRule() == null
+ ? MatchingRule.UPDATE
+ : taskTO.getMatchingRule());
+ profile.add(matchingRule);
+
+ // set default Unmatching rule
+ ((DropDownChoice) unmatchingRule.getField()).setDefaultModelObject(taskTO.getUnmatchingRule() == null
+ ? UnmatchingRule.PROVISION
+ : taskTO.getUnmatchingRule());
+ profile.add(unmatchingRule);
+
+ final AjaxCheckBoxPanel fullReconciliation = new AjaxCheckBoxPanel("fullReconciliation",
+ getString("fullReconciliation"), new PropertyModel<Boolean>(taskTO, "fullReconciliation"));
+ profile.add(fullReconciliation);
+ }
+
+ @Override
+ protected List<String> getSyncActions() {
+ return taskRestClient.getSyncActionsClasses();
+ }
+
+ @Override
+ public void submitAction(final SchedTaskTO taskTO) {
+ if (taskTO.getKey() > 0) {
+ taskRestClient.updateSyncTask((SyncTaskTO) taskTO);
+ } else {
+ taskRestClient.createSyncTask((SyncTaskTO) taskTO);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/TaskModalPage.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/TaskModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/TaskModalPage.java
new file mode 100644
index 0000000..c251d87
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/TaskModalPage.java
@@ -0,0 +1,253 @@
+/*
+ * 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.SortableDataProviderComparator;
+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.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.NotificationTaskTO;
+import org.apache.syncope.common.lib.to.PropagationTaskTO;
+import org.apache.syncope.common.lib.to.SchedTaskTO;
+import org.apache.syncope.common.lib.to.SyncTaskTO;
+import org.apache.syncope.common.lib.to.TaskExecTO;
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+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.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.springframework.util.StringUtils;
+
+/**
+ * Modal window with Task form (to stop and start execution).
+ */
+public abstract class TaskModalPage extends BaseModalPage {
+
+ private static final long serialVersionUID = -4110576026663173545L;
+
+ protected WebMarkupContainer profile;
+
+ protected WebMarkupContainer executions;
+
+ protected Form<AbstractTaskTO> form;
+
+ public TaskModalPage(final AbstractTaskTO taskTO) {
+ final ModalWindow taskExecMessageWin = new ModalWindow("taskExecMessageWin");
+ taskExecMessageWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+ taskExecMessageWin.setCookieName("task-exec-message-win-modal");
+ add(taskExecMessageWin);
+
+ form = new Form<>(FORM);
+ form.setModel(new CompoundPropertyModel<>(taskTO));
+ add(form);
+
+ profile = new WebMarkupContainer("profile");
+ profile.setOutputMarkupId(true);
+ form.add(profile);
+
+ executions = new WebMarkupContainer("executionContainer");
+ executions.setOutputMarkupId(true);
+ form.add(executions);
+
+ final Label idLabel = new Label("idLabel", new ResourceModel("key"));
+ profile.add(idLabel);
+
+ final AjaxTextFieldPanel id =
+ new AjaxTextFieldPanel("key", getString("key"), new PropertyModel<String>(taskTO, "key"));
+
+ id.setEnabled(false);
+ profile.add(id);
+
+ final List<IColumn<TaskExecTO, String>> columns = new ArrayList<>();
+
+ final int paginatorRows = 10;
+
+ columns.add(new PropertyColumn<TaskExecTO, String>(new ResourceModel("key"), "key", "key"));
+ columns.add(new DatePropertyColumn<TaskExecTO>(new ResourceModel("startDate"), "startDate", "startDate"));
+ columns.add(new DatePropertyColumn<TaskExecTO>(new ResourceModel("endDate"), "endDate", "endDate"));
+ columns.add(new PropertyColumn<TaskExecTO, String>(new ResourceModel("status"), "status", "status"));
+ columns.add(new ActionColumn<TaskExecTO, String>(new ResourceModel("actions", "")) {
+
+ private static final long serialVersionUID = 2054811145491901166L;
+
+ @Override
+ public ActionLinksPanel getActions(final String componentId, final IModel<TaskExecTO> model) {
+
+ final TaskExecTO 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) {
+ taskExecMessageWin.setPageCreator(new ModalWindow.PageCreator() {
+
+ private static final long serialVersionUID = -7834632442532690940L;
+
+ @Override
+ public Page createPage() {
+ return new ExecMessageModalPage(model.getObject().getMessage());
+ }
+ });
+ taskExecMessageWin.show(target);
+ }
+ }, ActionLink.ActionType.EDIT, TASKS, StringUtils.hasText(model.getObject().getMessage()));
+
+ panel.add(new ActionLink() {
+
+ private static final long serialVersionUID = -3722207913631435501L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target) {
+ try {
+ taskRestClient.deleteExecution(taskExecutionTO.getKey());
+
+ taskTO.getExecutions().remove(taskExecutionTO);
+
+ info(getString(Constants.OPERATION_SUCCEEDED));
+ } catch (SyncopeClientException scce) {
+ error(scce.getMessage());
+ }
+
+ feedbackPanel.refresh(target);
+ target.add(executions);
+ }
+ }, ActionLink.ActionType.DELETE, TASKS);
+
+ 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 AjaxFallbackDefaultDataTable<TaskExecTO, String> currentTable =
+ new AjaxFallbackDefaultDataTable<TaskExecTO, String>("executionsTable", columns,
+ new TaskExecutionsProvider(getCurrentTaskExecution(taskTO)), paginatorRows);
+ currentTable.setOutputMarkupId(true);
+ target.add(currentTable);
+ executions.addOrReplace(currentTable);
+ }
+ }
+ }, ActionLink.ActionType.RELOAD, TASKS, "list");
+
+ return panel;
+ }
+ });
+
+ final AjaxFallbackDefaultDataTable<TaskExecTO, String> table =
+ new AjaxFallbackDefaultDataTable<TaskExecTO, String>("executionsTable", columns,
+ new TaskExecutionsProvider(getCurrentTaskExecution(taskTO)), paginatorRows);
+
+ executions.add(table);
+ }
+
+ protected static class TaskExecutionsProvider extends SortableDataProvider<TaskExecTO, String> {
+
+ private static final long serialVersionUID = 8943636537120648961L;
+
+ private SortableDataProviderComparator<TaskExecTO> comparator;
+
+ private AbstractTaskTO taskTO;
+
+ public TaskExecutionsProvider(final AbstractTaskTO taskTO) {
+ //Default sorting
+ this.taskTO = taskTO;
+ setSort("startDate", SortOrder.DESCENDING);
+ comparator = new SortableDataProviderComparator<TaskExecTO>(this);
+ }
+
+ @Override
+ public Iterator<TaskExecTO> iterator(final long first, final long count) {
+
+ List<TaskExecTO> list = taskTO.getExecutions();
+
+ Collections.sort(list, comparator);
+
+ return list.subList((int) first, (int) first + (int) count).iterator();
+ }
+
+ @Override
+ public long size() {
+ return taskTO.getExecutions().size();
+ }
+
+ @Override
+ public IModel<TaskExecTO> model(final TaskExecTO taskExecution) {
+
+ return new AbstractReadOnlyModel<TaskExecTO>() {
+
+ private static final long serialVersionUID = 7485475149862342421L;
+
+ @Override
+ public TaskExecTO getObject() {
+ return taskExecution;
+ }
+ };
+ }
+ }
+
+ private AbstractTaskTO getCurrentTaskExecution(final AbstractTaskTO taskTO) {
+ final AbstractTaskTO currentTask = taskTO.getKey() == 0
+ ? taskTO
+ : taskTO instanceof PropagationTaskTO
+ ? taskRestClient.readPropagationTask(taskTO.getKey())
+ : taskTO instanceof NotificationTaskTO
+ ? taskRestClient.readNotificationTask(taskTO.getKey())
+ : taskTO instanceof SyncTaskTO
+ ? taskRestClient.readSchedTask(SyncTaskTO.class, taskTO.getKey())
+ : taskRestClient.readSchedTask(SchedTaskTO.class, taskTO.getKey());
+
+ taskTO.getExecutions().clear();
+ taskTO.getExecutions().addAll(currentTask.getExecutions());
+ return taskTO;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java
new file mode 100644
index 0000000..296c365
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java
@@ -0,0 +1,230 @@
+/*
+ * 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.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
+import org.apache.syncope.client.console.panels.NotificationTasks;
+import org.apache.syncope.client.console.panels.PropagationTasks;
+import org.apache.syncope.client.console.panels.PushTasksPanel;
+import org.apache.syncope.client.console.panels.SchedTasks;
+import org.apache.syncope.client.console.panels.SyncTasksPanel;
+import org.apache.syncope.client.console.rest.BaseRestClient;
+import org.apache.syncope.client.console.rest.TaskRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.SchedTaskTO;
+import org.apache.syncope.common.lib.to.TaskExecTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+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.ISortableDataProvider;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.model.AbstractReadOnlyModel;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+
+public class Tasks extends BasePage {
+
+ private static final long serialVersionUID = 5289215853622289061L;
+
+ public Tasks() {
+ super();
+
+ add(new PropagationTasks("propagation", getPageReference()));
+ add(new NotificationTasks("notification", getPageReference()));
+ add(new SchedTasks("sched", getPageReference()));
+ add(new SyncTasksPanel("sync", getPageReference()));
+ add(new PushTasksPanel("push", getPageReference()));
+
+ getPageReference();
+ }
+
+ @Override
+ public void setWindowClosedCallback(final ModalWindow window, final WebMarkupContainer container) {
+
+ super.setWindowClosedCallback(window, container);
+ }
+
+ public static class TaskExecutionsProvider extends SortableDataProvider<TaskExecTO, String> {
+
+ private static final long serialVersionUID = -5401263348984206145L;
+
+ private SortableDataProviderComparator<TaskExecTO> comparator;
+
+ private AbstractTaskTO taskTO;
+
+ public TaskExecutionsProvider(final AbstractTaskTO taskTO) {
+ super();
+
+ //Default sorting
+ this.taskTO = taskTO;
+ setSort("startDate", SortOrder.DESCENDING);
+ comparator = new SortableDataProviderComparator<TaskExecTO>(this);
+ }
+
+ @Override
+ public Iterator<TaskExecTO> iterator(final long first, final long count) {
+
+ List<TaskExecTO> list = getTaskDB();
+
+ Collections.sort(list, comparator);
+
+ return list.subList((int) first, (int) first + (int) count).iterator();
+ }
+
+ @Override
+ public long size() {
+ return getTaskDB().size();
+ }
+
+ @Override
+ public IModel<TaskExecTO> model(final TaskExecTO taskExecution) {
+
+ return new AbstractReadOnlyModel<TaskExecTO>() {
+
+ private static final long serialVersionUID = 7485475149862342421L;
+
+ @Override
+ public TaskExecTO getObject() {
+ return taskExecution;
+ }
+ };
+ }
+
+ public List<TaskExecTO> getTaskDB() {
+ return taskTO.getExecutions();
+ }
+ }
+
+ public static class TasksProvider<T extends AbstractTaskTO> extends SortableDataProvider<T, String> {
+
+ private static final long serialVersionUID = -20112718133295756L;
+
+ private SortableDataProviderComparator<T> comparator;
+
+ private TaskRestClient restClient;
+
+ private int paginatorRows;
+
+ private String id;
+
+ private Class<T> reference;
+
+ public TasksProvider(
+ final TaskRestClient restClient, final int paginatorRows, final String id, final Class<T> reference) {
+
+ super();
+
+ //Default sorting
+ setSort("key", SortOrder.DESCENDING);
+ comparator = new SortableDataProviderComparator<>(this);
+ this.paginatorRows = paginatorRows;
+ this.restClient = restClient;
+ this.id = id;
+ this.reference = reference;
+ }
+
+ @Override
+ public Iterator<T> iterator(final long first, final long count) {
+ final List<T> tasks = new ArrayList<>();
+
+ final int page = ((int) first / paginatorRows);
+
+ for (T task : restClient.list(reference, (page < 0 ? 0 : page) + 1, paginatorRows, getSort())) {
+ if (task instanceof SchedTaskTO && ((SchedTaskTO) task).getLastExec() == null
+ && task.getExecutions() != null && !task.getExecutions().isEmpty()) {
+
+ Collections.sort(task.getExecutions(), new Comparator<TaskExecTO>() {
+
+ @Override
+ public int compare(final TaskExecTO left, final TaskExecTO right) {
+ return left.getStartDate().compareTo(right.getStartDate());
+ }
+ });
+
+ ((SchedTaskTO) task).setLastExec(task.getExecutions().get(task.getExecutions().size() - 1).
+ getStartDate());
+ }
+ tasks.add(task);
+ }
+
+ Collections.sort(tasks, comparator);
+ return tasks.iterator();
+ }
+
+ @Override
+ public long size() {
+ return restClient.count(id);
+ }
+
+ @Override
+ public IModel<T> model(final T object) {
+ return new CompoundPropertyModel<>(object);
+ }
+ }
+
+ /**
+ * Update task table.
+ *
+ * @param columns columns.
+ * @param dataProvider data provider.
+ * @param container container.
+ * @param currentPage current page index.
+ * @param pageRef page reference
+ * @param restClient syncope base rest client
+ * @return data table.
+ */
+ public static AjaxDataTablePanel<AbstractTaskTO, String> updateTaskTable(
+ final List<IColumn<AbstractTaskTO, String>> columns,
+ final TasksProvider<? extends AbstractTaskTO> dataProvider,
+ final WebMarkupContainer container,
+ final int currentPage,
+ final PageReference pageRef,
+ final BaseRestClient restClient) {
+
+ @SuppressWarnings("unchecked")
+ final AjaxDataTablePanel<AbstractTaskTO, String> table = new AjaxDataTablePanel<>(
+ "datatable",
+ columns,
+ (ISortableDataProvider<AbstractTaskTO, String>) dataProvider,
+ dataProvider.paginatorRows,
+ Arrays.asList(new ActionLink.ActionType[] {
+ ActionLink.ActionType.DELETE, ActionLink.ActionType.DRYRUN, ActionLink.ActionType.EXECUTE }),
+ restClient,
+ "key",
+ TASKS,
+ pageRef);
+
+ table.setCurrentPage(currentPage);
+ table.setOutputMarkupId(true);
+
+ container.addOrReplace(table);
+
+ return table;
+ }
+}