[SYNCOPE-156] Realm page now displays user groups and any object
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/518f7bef Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/518f7bef Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/518f7bef Branch: refs/heads/SYNCOPE-156 Commit: 518f7bef2c019191b8a20a0ace8862f7b4573d48 Parents: 7eca0ab Author: giacomolm <[email protected]> Authored: Thu Jul 30 10:01:17 2015 +0200 Committer: giacomolm <[email protected]> Committed: Thu Jul 30 10:01:17 2015 +0200 ---------------------------------------------------------------------- .../client/console/commons/AnyDataProvider.java | 16 +- .../client/console/commons/Constants.java | 12 + .../pages/AnyDisplayAttributesModalPage.java | 61 ++ .../pages/DisplayAttributesModalPage.java | 236 +++++++ .../console/pages/EditRealmModalPage.java | 41 ++ .../pages/GroupDisplayAttributesModalPage.java | 61 ++ .../console/pages/ProvisioningModalPage.java | 4 +- .../client/console/pages/RealmModalPage.java | 142 ++++ .../syncope/client/console/pages/Realms.java | 84 ++- .../client/console/pages/StatusModalPage.java | 641 +++++++++++++++++++ .../pages/UserDisplayAttributesModalPage.java | 62 ++ .../panels/AbstractSearchResultPanel.java | 18 +- .../console/panels/AjaxDataTablePanel.java | 4 + .../syncope/client/console/panels/Any.java | 35 - .../console/panels/AnySearchResultPanel.java | 264 ++++++++ .../client/console/panels/AnyTypeMenuItem.java | 43 ++ .../console/panels/GroupSearchResultPanel.java | 234 +++++++ .../syncope/client/console/panels/Realm.java | 100 ++- .../client/console/panels/RealmDetails.java | 7 +- .../console/panels/UserSearchResultPanel.java | 277 ++++++++ .../console/rest/AbstractAnyRestClient.java | 6 +- .../console/rest/AnyObjectRestClient.java | 96 +++ .../client/console/rest/AnyTypeRestClient.java | 49 ++ .../client/console/rest/GroupRestClient.java | 8 +- .../client/console/rest/RealmRestClient.java | 5 +- .../client/console/rest/UserRestClient.java | 8 +- .../html/repeater/data/table/ActionColumn.java | 59 ++ .../html/repeater/data/table/AttrColumn.java | 84 +++ .../META-INF/resources/css/AdminLTE.css | 4 + .../META-INF/resources/css/syncopeConsole.css | 134 ++-- .../pages/DisplayAttributesModalPage.html | 118 ++++ .../pages/DisplayAttributesModalPage.properties | 32 + .../client/console/pages/RealmModalPage.html | 70 ++ .../syncope/client/console/pages/Realms.html | 13 +- .../console/panels/AjaxDataTablePanel.html | 2 +- .../syncope/client/console/panels/Any.html | 29 - .../client/console/panels/AnyTypeMenuItem.html | 29 + .../syncope/client/console/panels/Realm.html | 64 +- .../client/console/panels/RealmDetails.html | 36 +- .../markup/html/form/ActionLinksPanel.html | 12 +- .../pages/DisplayAttributesModalPage.java | 2 +- .../client/console/pages/EditUserModalPage.java | 2 +- 42 files changed, 2954 insertions(+), 250 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java index bd4183b..e13840c 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/AnyDataProvider.java @@ -42,9 +42,12 @@ public class AnyDataProvider extends SortableDataProvider<AnyTO, String> { private final AbstractAnyRestClient restClient; - private final String realm = "/"; + private final String realm; - public AnyDataProvider(final AbstractAnyRestClient restClient, final int paginatorRows, final boolean filtered) { + private final String type; + + public AnyDataProvider(final AbstractAnyRestClient restClient, final int paginatorRows, final boolean filtered, + final String realm, final String type) { super(); this.restClient = restClient; @@ -55,6 +58,9 @@ public class AnyDataProvider extends SortableDataProvider<AnyTO, String> { setSort("key", SortOrder.ASCENDING); this.comparator = new SortableAnyProviderComparator(this); + + this.realm = realm; + this.type = type; } public void setFIQL(final String fiql) { @@ -70,9 +76,9 @@ public class AnyDataProvider extends SortableDataProvider<AnyTO, String> { if (filtered) { result = fiql == null ? Collections.<AnyTO>emptyList() - : restClient.search(realm, fiql, (page < 0 ? 0 : page) + 1, paginatorRows, getSort()); + : restClient.search(realm, fiql, (page < 0 ? 0 : page) + 1, paginatorRows, getSort(), type); } else { - result = restClient.list(realm, (page < 0 ? 0 : page) + 1, paginatorRows, getSort()); + result = restClient.list(realm, (page < 0 ? 0 : page) + 1, paginatorRows, getSort(), type); } Collections.sort(result, comparator); @@ -86,7 +92,7 @@ public class AnyDataProvider extends SortableDataProvider<AnyTO, String> { if (filtered) { result = fiql == null ? 0 - : restClient.searchCount(realm, fiql); + : restClient.searchCount(realm, fiql, type); } else { result = restClient.count(realm); } http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java index 98339ec..804f9fe 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java @@ -54,6 +54,12 @@ public final class Constants { public static final String PREF_USER_VIR_SCHEMA_PAGINATOR_ROWS = "user.virtual.schema.paginator.rows"; + public static final String PREF_GROUP_DETAILS_VIEW = "group.details.view"; + + public static final String PREF_GROUP_ATTRIBUTES_VIEW = "group.attributes.view"; + + public static final String PREF_GROUP_DERIVED_ATTRIBUTES_VIEW = "group.derived.attributes.view"; + public static final String PREF_GROUP_PLAIN_SCHEMA_PAGINATOR_ROWS = "group.schema.paginator.rows"; public static final String PREF_GROUP_DER_SCHEMA_PAGINATOR_ROWS = "group.derived.schema.paginator.rows"; @@ -91,6 +97,12 @@ public final class Constants { public static final String PAGEPARAM_CURRENT_PAGE = "_current_page"; public static final String PREF_POLICY_PAGINATOR_ROWS = "policy.paginator.rows"; + + public static final String PREF_ANY_DETAILS_VIEW = "any.details.view"; + + public static final String PREF_ANY_ATTRIBUTES_VIEW = "any.attributes.view"; + + public static final String PREF_ANY_DERIVED_ATTRIBUTES_VIEW = "any.derived.attributes.view"; /** * ConnId's GuardedString is not in the classpath. http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/AnyDisplayAttributesModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/AnyDisplayAttributesModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/AnyDisplayAttributesModalPage.java new file mode 100644 index 0000000..63223a0 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/AnyDisplayAttributesModalPage.java @@ -0,0 +1,61 @@ +/* + * 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.commons.Constants; +import org.apache.syncope.common.lib.to.AnyObjectTO; +import org.apache.wicket.PageReference; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; + +/** + * Modal window with Display user attributes form. + */ +@SuppressWarnings({ "unchecked", "rawtypes" }) +public class AnyDisplayAttributesModalPage extends DisplayAttributesModalPage { + + private static final long serialVersionUID = 5194630813773543054L; + + public static final String[] ANY_DEFAULT_SELECTION = { "key" }; + + public AnyDisplayAttributesModalPage(final PageReference pageRef, final ModalWindow window, + final List<String> schemaNames, final List<String> dSchemaNames) { + super(pageRef, window, schemaNames, dSchemaNames); + } + + @Override + public String getPrefDetailView() { + return Constants.PREF_ANY_DETAILS_VIEW; + } + + @Override + public String getPrefAttributeView() { + return Constants.PREF_ANY_ATTRIBUTES_VIEW; + } + + @Override + public String getPrefDerivedAttributeView() { + return Constants.PREF_ANY_DERIVED_ATTRIBUTES_VIEW; + } + + @Override + public Class getTOClass() { + return AnyObjectTO.class; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.java new file mode 100644 index 0000000..769cb45 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/DisplayAttributesModalPage.java @@ -0,0 +1,236 @@ +/* + * 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.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.syncope.client.console.PreferenceManager; +import org.apache.syncope.common.lib.search.SearchableFields; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxRequestTarget; +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.Check; +import org.apache.wicket.markup.html.form.CheckGroup; +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.Fragment; +import org.apache.wicket.model.CompoundPropertyModel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.LoadableDetachableModel; +import org.apache.wicket.model.PropertyModel; +import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.spring.injection.annot.SpringBean; + +/** + * Modal window with Display attributes form. + */ +@SuppressWarnings({ "unchecked", "rawtypes" }) +public abstract class DisplayAttributesModalPage extends BaseModalPage { + + private static final long serialVersionUID = -4274117450918385110L; + + /** + * Max allowed selections. + */ + private static final int MAX_SELECTIONS = 9; + + @SpringBean + private PreferenceManager prefMan; + + private final List<String> selectedDetails; + + private final List<String> selectedPlainSchemas; + + private final List<String> selectedDerSchemas; + + public DisplayAttributesModalPage(final PageReference pageRef, final ModalWindow window, + final List<String> schemaNames, final List<String> dSchemaNames) { + + super(); + + final IModel<List<String>> fnames = new LoadableDetachableModel<List<String>>() { + + private static final long serialVersionUID = 5275935387613157437L; + + @Override + protected List<String> load() { + return SearchableFields.get(getTOClass()); + } + }; + + final IModel<List<String>> names = new LoadableDetachableModel<List<String>>() { + + private static final long serialVersionUID = 5275935387613157437L; + + @Override + protected List<String> load() { + return schemaNames; + } + }; + + final IModel<List<String>> dsnames = new LoadableDetachableModel<List<String>>() { + + private static final long serialVersionUID = 5275935387613157437L; + + @Override + protected List<String> load() { + return dSchemaNames; + } + }; + + final Form form = new Form(FORM); + form.setModel(new CompoundPropertyModel(this)); + + selectedDetails = prefMan.getList(getRequest(), getPrefDetailView()); + + selectedPlainSchemas = prefMan.getList(getRequest(), getPrefAttributeView()); + + selectedDerSchemas = prefMan.getList(getRequest(), getPrefDerivedAttributeView()); + + final CheckGroup dgroup = new CheckGroup("dCheckGroup", new PropertyModel(this, "selectedDetails")); + form.add(dgroup); + + final ListView<String> details = new ListView<String>("details", fnames) { + + private static final long serialVersionUID = 9101744072914090143L; + + @Override + protected void populateItem(final ListItem<String> item) { + item.add(new Check("dcheck", item.getModel())); + item.add(new Label("dname", new ResourceModel(item.getModelObject(), item.getModelObject()))); + } + }; + dgroup.add(details); + + if (names.getObject() == null || names.getObject().isEmpty()) { + final Fragment fragment = new Fragment("plainSchemas", "emptyFragment", form); + form.add(fragment); + + selectedPlainSchemas.clear(); + } else { + final Fragment fragment = new Fragment("plainSchemas", "sfragment", form); + form.add(fragment); + + final CheckGroup sgroup = new CheckGroup("psCheckGroup", new PropertyModel(this, "selectedPlainSchemas")); + fragment.add(sgroup); + + final ListView<String> schemas = new ListView<String>("plainSchemas", names) { + + private static final long serialVersionUID = 9101744072914090143L; + + @Override + protected void populateItem(final ListItem<String> item) { + item.add(new Check("scheck", item.getModel())); + item.add(new Label("sname", new ResourceModel(item.getModelObject(), item.getModelObject()))); + } + }; + sgroup.add(schemas); + } + + if (dsnames.getObject() == null || dsnames.getObject().isEmpty()) { + final Fragment fragment = new Fragment("dschemas", "emptyFragment", form); + form.add(fragment); + + selectedDerSchemas.clear(); + } else { + final Fragment fragment = new Fragment("dschemas", "dsfragment", form); + form.add(fragment); + + final CheckGroup dsgroup = new CheckGroup("dsCheckGroup", new PropertyModel(this, "selectedDerSchemas")); + fragment.add(dsgroup); + + final ListView<String> derSchemas = new ListView<String>("derSchemas", dsnames) { + + private static final long serialVersionUID = 9101744072914090143L; + + @Override + protected void populateItem(final ListItem<String> item) { + item.add(new Check("dscheck", item.getModel())); + item.add(new Label("dsname", new ResourceModel(item.getModelObject(), item.getModelObject()))); + } + }; + dsgroup.add(derSchemas); + } + + final AjaxButton submit = new IndicatingAjaxButton(SUBMIT, new ResourceModel(SUBMIT)) { + + private static final long serialVersionUID = -4804368561204623354L; + + @Override + protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + if (selectedDetails.size() + selectedPlainSchemas.size() + selectedDerSchemas.size() + > MAX_SELECTIONS) { + + error(getString("tooManySelections")); + onError(target, form); + } else { + final Map<String, List<String>> prefs = new HashMap<>(); + + prefs.put(getPrefDetailView(), selectedDetails); + + prefs.put(getPrefAttributeView(), selectedPlainSchemas); + + prefs.put(getPrefDerivedAttributeView(), selectedDerSchemas); + + prefMan.setList(getRequest(), getResponse(), prefs); + + ((BasePage) pageRef.getPage()).setModalResult(true); + + window.close(target); + } + } + + @Override + protected void onError(final AjaxRequestTarget target, final Form<?> form) { + feedbackPanel.refresh(target); + } + }; + + form.add(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); + } + }; + + cancel.setDefaultFormProcessing(false); + form.add(cancel); + + add(form); + } + + public abstract String getPrefDetailView(); + + public abstract String getPrefAttributeView(); + + public abstract String getPrefDerivedAttributeView(); + + public abstract Class getTOClass(); + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/EditRealmModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/EditRealmModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/EditRealmModalPage.java new file mode 100644 index 0000000..248162e --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/EditRealmModalPage.java @@ -0,0 +1,41 @@ +/* + * 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.common.lib.to.AnyTO; +import org.apache.syncope.common.lib.to.RealmTO; +import org.apache.wicket.PageReference; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; + +public class EditRealmModalPage<T extends AnyTO> extends RealmModalPage { + + private static final long serialVersionUID = -4285220460543213901L; + + public EditRealmModalPage( + final PageReference pageRef, + final ModalWindow window, + final RealmTO realmTO, + final String parentPath, + final String entitlement) { + + super(pageRef, window, realmTO, parentPath, entitlement); + + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/GroupDisplayAttributesModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/GroupDisplayAttributesModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/GroupDisplayAttributesModalPage.java new file mode 100644 index 0000000..0e5e10f --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/GroupDisplayAttributesModalPage.java @@ -0,0 +1,61 @@ +/* + * 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.commons.Constants; +import org.apache.syncope.common.lib.to.GroupTO; +import org.apache.wicket.PageReference; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; + +/** + * Modal window with Display group attributes form. + */ +@SuppressWarnings({ "unchecked", "rawtypes" }) +public class GroupDisplayAttributesModalPage extends DisplayAttributesModalPage { + + private static final long serialVersionUID = 5194630813773543054L; + + public static final String[] GROUP_DEFAULT_SELECTION = { "key", "name" }; + + public GroupDisplayAttributesModalPage(final PageReference pageRef, final ModalWindow window, + final List<String> schemaNames, final List<String> dSchemaNames) { + super(pageRef, window, schemaNames, dSchemaNames); + } + + @Override + public String getPrefDetailView() { + return Constants.PREF_GROUP_DETAILS_VIEW; + } + + @Override + public String getPrefAttributeView() { + return Constants.PREF_GROUP_ATTRIBUTES_VIEW; + } + + @Override + public String getPrefDerivedAttributeView() { + return Constants.PREF_GROUP_DERIVED_ATTRIBUTES_VIEW; + } + + @Override + public Class getTOClass() { + return GroupTO.class; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/ProvisioningModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/ProvisioningModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/ProvisioningModalPage.java index 9937e36..6e44d62 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/pages/ProvisioningModalPage.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/ProvisioningModalPage.java @@ -198,10 +198,10 @@ public class ProvisioningModalPage<T extends AnyTO> extends AbstractStatusModalP final List<T> subjects = new ArrayList<>(); if (anyTypeKind == AnyTypeKind.USER) { subjects.addAll((List<T>) userRestClient.search( - realm, fiql, 1, ROWS_PER_PAGE, new SortParam<>("key", true))); + realm, fiql, 1, ROWS_PER_PAGE, new SortParam<>("key", true), AnyTypeKind.USER.toString())); } else { subjects.addAll((List<T>) groupRestClient.search( - realm, fiql, 1, ROWS_PER_PAGE, new SortParam<>("key", true))); + realm, fiql, 1, ROWS_PER_PAGE, new SortParam<>("key", true), AnyTypeKind.GROUP.toString())); } final List<ConnObjectWrapper> connObjects = statusUtils.getConnectorObjects( http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/RealmModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/RealmModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/RealmModalPage.java new file mode 100644 index 0000000..5b8526d --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/RealmModalPage.java @@ -0,0 +1,142 @@ +/* + * 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 static org.apache.syncope.client.console.pages.AbstractBasePage.CANCEL; +import static org.apache.wicket.Component.ENABLE; + +import org.apache.syncope.client.console.SyncopeConsoleSession; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.panels.RealmDetails; +import org.apache.syncope.client.console.rest.RealmRestClient; +import org.apache.syncope.common.lib.to.AnyTO; +import org.apache.syncope.common.lib.to.RealmTO; +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.ResourceModel; +import org.apache.wicket.spring.injection.annot.SpringBean; + +public class RealmModalPage<T extends AnyTO> extends BaseModalPage { + + private static final long serialVersionUID = -4285220460543213901L; + + private static final int ROWS_PER_PAGE = 10; + + protected RealmTO realmTO; + + private final PageReference pageRef; + + private final ModalWindow window; + + @SpringBean + private RealmRestClient realmRestClient; + + private final String parentPath; + + public RealmModalPage( + final PageReference pageRef, + final ModalWindow window, + final RealmTO realmTO, + final String parentPath, + final String entitlement) { + + super(); + + this.pageRef = pageRef; + this.window = window; + this.realmTO = realmTO; + this.parentPath = parentPath; + + final Form<RealmTO> form = new Form<RealmTO>("RealmForm"); + form.setModel(new CompoundPropertyModel<RealmTO>(realmTO)); + + RealmDetails realmDetail = new RealmDetails("details", realmTO); + if (SyncopeConsoleSession.get().owns(entitlement)) { + MetaDataRoleAuthorizationStrategy.authorize(realmDetail, ENABLE, entitlement); + } + form.add(realmDetail); + + final AjaxButton submit = getOnSubmit(); + form.add(submit); + form.setDefaultButton(submit); + + final AjaxButton cancel = new AjaxButton(CANCEL, new ResourceModel(CANCEL)) { + + private static final long serialVersionUID = 530608535790823587L; + + @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); + } + + protected AjaxButton getOnSubmit() { + return new IndicatingAjaxButton(APPLY, new ResourceModel(SUBMIT)) { + + private static final long serialVersionUID = -958724007591692537L; + + @Override + protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + try { + submitAction(target, form); + + if (pageRef.getPage() instanceof BasePage) { + ((BasePage) pageRef.getPage()).setModalResult(true); + } + + closeAction(target, form); + } catch (Exception e) { + LOG.error("While creating or updating user", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + } + } + + @Override + protected void onError(final AjaxRequestTarget target, final Form<?> form) { + feedbackPanel.refresh(target); + } + }; + } + + protected void submitAction(final AjaxRequestTarget target, final Form<?> form) { + final RealmTO updatedRealmTO = (RealmTO) form.getModelObject(); + realmRestClient.create(this.parentPath, updatedRealmTO); + } + + protected void closeAction(final AjaxRequestTarget target, final Form<?> form) { + this.window.close(target); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java index daee99c..50378ed 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java @@ -18,6 +18,8 @@ */ package org.apache.syncope.client.console.pages; +import static org.apache.wicket.Component.ENABLE; + import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; @@ -25,14 +27,20 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.syncope.client.console.SyncopeConsoleSession; import org.apache.syncope.client.console.panels.Realm; import org.apache.syncope.client.console.rest.RealmRestClient; +import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink; import org.apache.syncope.common.lib.to.RealmTO; +import org.apache.syncope.common.lib.types.Entitlement; import org.apache.wicket.MarkupContainer; +import org.apache.wicket.Page; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxLink; +import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy; import org.apache.wicket.event.Broadcast; import org.apache.wicket.event.IEvent; +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.panel.Fragment; @@ -54,9 +62,13 @@ public class Realms extends BasePage { private final WebMarkupContainer content; + private final ModalWindow editModalWin; + + protected RealmTO currentRealm; + public Realms(final PageParameters parameters) { super(parameters); - + final List<RealmTO> realms = realmRestClient.list(); Collections.sort(realms, new RealmNameComparator()); @@ -68,6 +80,40 @@ public class Realms extends BasePage { content.add(new Label("header", "Root realm")); content.add(new Label("body", "Root realm")); + + //create new realms + final AjaxLink<Void> createLink = new ClearIndicatingAjaxLink<Void>("createLink", getPageReference()) { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + protected void onClickInternal(final AjaxRequestTarget target) { + editModalWin.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + return new RealmModalPage(Realms.this.getPageReference(), editModalWin, new RealmTO(), + Realms.this.getCurrentRealm().getFullPath(), Entitlement.REALM_CREATE); + } + }); + + editModalWin.show(target); + } + }; + if (SyncopeConsoleSession.get().owns(Entitlement.REALM_CREATE)) { + MetaDataRoleAuthorizationStrategy.authorize(createLink, ENABLE, Entitlement.REALM_CREATE); + } + content.add(createLink); + + // Modal window for editing realms + editModalWin = new ModalWindow("editModal"); + editModalWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + editModalWin.setCookieName("edit-modal"); + + content.add(editModalWin); + setCurrentRealm(realms.get(0)); } private void add(final Map<Long, List<RealmTO>> parentMap, final Long key, final MarkupContainer container) { @@ -83,6 +129,7 @@ public class Realms extends BasePage { @Override public void onClick(final AjaxRequestTarget target) { + Realms.this.setCurrentRealm(realm); send(Realms.this, Broadcast.EXACT, new ControlSidebarClick<>(realm, target)); } }; @@ -148,11 +195,44 @@ public class Realms extends BasePage { @SuppressWarnings("unchecked") final ControlSidebarClick<RealmTO> controlSidebarClick = ControlSidebarClick.class.cast(event.getPayload()); content.addOrReplace(new Label("header", controlSidebarClick.getObj().getName())); - content.addOrReplace(new Realm("body", controlSidebarClick.getObj())); + content.addOrReplace(new Realm("body", controlSidebarClick.getObj(), getPageReference())); controlSidebarClick.getTarget().add(content); } } + public void setCurrentRealm(final RealmTO realmTO) { + this.currentRealm = realmTO; + setupEditModalPage(currentRealm); + } + + public RealmTO getCurrentRealm() { + return this.currentRealm; + } + + public void setupEditModalPage(final RealmTO realmTO) { + final AjaxLink<Void> edit = new ClearIndicatingAjaxLink<Void>("edit", getPageReference()) { + + private static final long serialVersionUID = 1L; + + @Override + protected void onClickInternal(final AjaxRequestTarget target) { + editModalWin.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + return new EditRealmModalPage(Realms.this.getPageReference(), editModalWin, realmTO, + Realms.this.getCurrentRealm().getFullPath(), Entitlement.REALM_UPDATE); + } + }); + + editModalWin.show(target); + } + }; + content.addOrReplace(edit); + } + private static class ControlSidebarClick<T> { private final AjaxRequestTarget target; http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/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..6ebb7be --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModalPage.java @@ -0,0 +1,641 @@ +/* + * 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.AnyTO; +import org.apache.syncope.common.lib.to.BulkActionResult; +import org.apache.syncope.common.lib.to.ResourceTO; +import org.apache.syncope.common.lib.to.GroupTO; +import org.apache.syncope.common.lib.to.UserTO; +import org.apache.syncope.common.lib.types.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 AnyTO> extends AbstractStatusModalPage { + + private static final long serialVersionUID = -9148734710505211261L; + + private final AnyTO anyTO; + + private int rowsPerPage = 10; + + private final StatusUtils statusUtils; + + private final boolean statusOnly; + + // -------------------------------- + // password management fields .. + // -------------------------------- + private final ClearIndicatingAjaxButton cancel; + + private final WebMarkupContainer pwdMgt; + + private final Form<?> pwdMgtForm; + + private final AjaxCheckBoxPanel changepwd; + + private final PasswordTextField password; + + private final PasswordTextField confirm; + // -------------------------------- + + private final PageReference pageRef; + + private final ModalWindow window; + + private final ActionDataTablePanel<StatusBean, String> table; + + private final List<IColumn<StatusBean, String>> columns; + + public StatusModalPage( + final PageReference pageRef, + final ModalWindow window, + final AnyTO attributableTO) { + + this(pageRef, window, attributableTO, false); + } + + public StatusModalPage( + final PageReference pageRef, + final ModalWindow window, + final AnyTO anyTO, + final boolean statusOnly) { + + super(); + + this.pageRef = pageRef; + this.window = window; + this.statusOnly = statusOnly; + this.anyTO = anyTO; + + statusUtils = new StatusUtils(anyTO instanceof UserTO ? userRestClient : groupRestClient); + + add(new Label("displayName", anyTO.getKey() + " " + + (anyTO instanceof UserTO ? ((UserTO) anyTO).getUsername() : ((GroupTO) anyTO).getName()))); + + columns = new ArrayList<>(); + columns.add(new AbstractColumn<StatusBean, String>( + new StringResourceModel("resourceName", this, null), "resourceName") { + + private static final long serialVersionUID = 2054811145491901166L; + + @Override + public void populateItem( + final Item<ICellPopulator<StatusBean>> cellItem, + final String componentId, + final IModel<StatusBean> model) { + + cellItem.add(new Label(componentId, model.getObject().getResourceName()) { + + private static final long serialVersionUID = 8432079838783825801L; + + @Override + protected void onComponentTag(final ComponentTag tag) { + if (model.getObject().isLinked()) { + super.onComponentTag(tag); + } else { + tag.put("style", "color: #DDDDDD"); + } + } + }); + } + }); + + columns.add(new PropertyColumn<StatusBean, String>( + new StringResourceModel("accountLink", this, null), "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 = anyTO instanceof GroupTO ? "Groups" : "Users"; + + final Fragment pwdMgtFragment = new Fragment("pwdMgtFields", "pwdMgtFragment", this); + addOrReplace(pwdMgtFragment); + + pwdMgt = new WebMarkupContainer("pwdMgt"); + pwdMgtFragment.add(pwdMgt.setOutputMarkupId(true)); + + pwdMgtForm = new Form("pwdMgtForm"); + pwdMgtForm.setVisible(false).setEnabled(false); + pwdMgt.add(pwdMgtForm); + + password = new PasswordTextField("password", new Model<String>()); + pwdMgtForm.add(password.setRequired(false).setEnabled(false)); + + confirm = new PasswordTextField("confirm", new Model<String>()); + pwdMgtForm.add(confirm.setRequired(false).setEnabled(false)); + + changepwd = new AjaxCheckBoxPanel("changepwd", "changepwd", new Model<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( + anyTO.getETagValue(), + anyTO.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( + anyTO.getETagValue(), + anyTO.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 (anyTO instanceof UserTO) { + userRestClient.unlink( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } else { + groupRestClient.unlink( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + 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 (anyTO instanceof UserTO) { + userRestClient.link( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } else { + groupRestClient.link( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + 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 (anyTO instanceof UserTO) { + bulkActionResult = userRestClient.deprovision( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } else { + bulkActionResult = groupRestClient.deprovision( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + loadBulkActionResultPage(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 (anyTO instanceof UserTO) { + StatusModalPage.this.passwordManagement( + target, ResourceAssociationActionType.PROVISION, table.getModelObject()); + } else { + try { + final BulkActionResult bulkActionResult = groupRestClient.provision( + anyTO.getETagValue(), + anyTO.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(!(anyTO 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 (anyTO instanceof UserTO) { + bulkActionResult = userRestClient.unassign( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } else { + bulkActionResult = groupRestClient.unassign( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(table.getModelObject())); + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + loadBulkActionResultPage(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 (anyTO instanceof UserTO) { + StatusModalPage.this.passwordManagement( + target, ResourceAssociationActionType.ASSIGN, table.getModelObject()); + } else { + try { + final BulkActionResult bulkActionResult = groupRestClient.assign( + anyTO.getETagValue(), + anyTO.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(!(anyTO 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(anyTO); + + final List<StatusBean> statusBeans = new ArrayList<StatusBean>(connObjects.size() + 1); + + for (ConnObjectWrapper entry : connObjects) { + final StatusBean statusBean = statusUtils.getStatusBean(anyTO, + entry.getResourceName(), + entry.getConnObjectTO(), + anyTO instanceof GroupTO); + + statusBeans.add(statusBean); + resources.remove(entry.getResourceName()); + } + + if (statusOnly) { + final StatusBean syncope = new StatusBean(anyTO, "Syncope"); + + syncope.setConnObjectLink(((UserTO) anyTO).getUsername()); + + Status syncopeStatus = Status.UNDEFINED; + if (((UserTO) anyTO).getStatus() != null) { + try { + syncopeStatus = Status.valueOf(((UserTO) anyTO).getStatus().toUpperCase()); + } catch (IllegalArgumentException e) { + LOG.warn("Unexpected status found: {}", ((UserTO) anyTO).getStatus(), e); + } + } + syncope.setStatus(syncopeStatus); + + statusBeans.add(syncope); + } else { + for (String resource : resources) { + final StatusBean statusBean = statusUtils.getStatusBean(anyTO, + resource, + null, + anyTO instanceof GroupTO); + + statusBean.setLinked(false); + statusBeans.add(statusBean); + } + } + + return statusBeans; + } + } + + private void passwordManagement( + final AjaxRequestTarget target, + final 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( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(selection), + changepwd.getModelObject(), + password.getModelObject()); + break; + case PROVISION: + bulkActionResult = userRestClient.provision( + anyTO.getETagValue(), + anyTO.getKey(), + new ArrayList<>(selection), + changepwd.getModelObject(), + password.getModelObject()); + break; + default: + bulkActionResult = null; + // ignore + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + + if (bulkActionResult != null) { + loadBulkActionResultPage(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(anyTO), resources); + + final List<StatusBean> statusBeans = new ArrayList<StatusBean>(connObjects.size()); + + for (ConnObjectWrapper entry : connObjects) { + final StatusBean statusBean = statusUtils.getStatusBean(anyTO, + entry.getResourceName(), + entry.getConnObjectTO(), + anyTO instanceof GroupTO); + + statusBeans.add(statusBean); + } + + setResponsePage(new BulkActionResultModalPage<StatusBean, String>( + window, + statusBeans, + columns, + bulkActionResult, + "resourceName")); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/pages/UserDisplayAttributesModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/UserDisplayAttributesModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/UserDisplayAttributesModalPage.java new file mode 100644 index 0000000..0eeaa42 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/UserDisplayAttributesModalPage.java @@ -0,0 +1,62 @@ +/* + * 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.commons.Constants; +import org.apache.syncope.common.lib.to.UserTO; +import org.apache.wicket.PageReference; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; + +/** + * Modal window with Display user attributes form. + */ +@SuppressWarnings({ "unchecked", "rawtypes" }) +public class UserDisplayAttributesModalPage extends DisplayAttributesModalPage { + + private static final long serialVersionUID = 5194630813773543054L; + + public static final String[] USER_DEFAULT_SELECTION = { "key", "username", "status" }; + + public UserDisplayAttributesModalPage(final PageReference pageRef, final ModalWindow window, + final List<String> schemaNames, final List<String> dSchemaNames) { + super(pageRef, window, schemaNames, dSchemaNames); + } + + @Override + public String getPrefDetailView() { + return Constants.PREF_USERS_DETAILS_VIEW; + } + + @Override + public String getPrefAttributeView() { + return Constants.PREF_USERS_ATTRIBUTES_VIEW; + } + + @Override + public String getPrefDerivedAttributeView() { + return Constants.PREF_USERS_DERIVED_ATTRIBUTES_VIEW; + } + + @Override + public Class getTOClass() { + return UserTO.class; + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java index 20f62d5..d91c083 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java @@ -147,8 +147,19 @@ public abstract class AbstractSearchResultPanel extends Panel implements IEventS */ protected final AbstractBasePage page; + /** + * Realm related to current panel. + */ + private final String realm; + + /** + * Any type related to current panel. + */ + private final String type; + protected <T extends AnyTO> AbstractSearchResultPanel(final String id, final boolean filtered, - final String fiql, final PageReference pageRef, final AbstractAnyRestClient restClient) { + final String fiql, final PageReference pageRef, final AbstractAnyRestClient restClient, + final String realm, final String type) { super(id); @@ -186,6 +197,9 @@ public abstract class AbstractSearchResultPanel extends Panel implements IEventS add(container); rows = prefMan.getPaginatorRows(getRequest(), Constants.PREF_USERS_PAGINATOR_ROWS); + + this.realm = realm; + this.type = type; } protected void initResultTable() { @@ -238,7 +252,7 @@ public abstract class AbstractSearchResultPanel extends Panel implements IEventS } private void updateResultTable(final boolean create, final int rows) { - dataProvider = new AnyDataProvider(restClient, rows, filtered); + dataProvider = new AnyDataProvider(restClient, rows, filtered, realm, type); dataProvider.setFIQL(fiql); final int currentPage = resultTable != null http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java index daaaa23..7c77228 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java @@ -28,6 +28,7 @@ import org.apache.syncope.client.console.commons.Constants; import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.CheckGroupColumn; import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton; import org.apache.syncope.client.console.pages.BulkActionModalPage; +import org.apache.wicket.AttributeModifier; import org.apache.wicket.Page; import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -110,6 +111,9 @@ public class AjaxDataTablePanel<T, S> extends DataTablePanel<T, S> { columns.add(0, new CheckGroupColumn<T, S>(group)); dataTable = new AjaxFallbackDefaultDataTable<>("dataTable", columns, dataProvider, rowsPerPage); + dataTable.add(new AttributeModifier("class", + "ui-widget ui-widget-content table-hover table table-striped table-bordered")); + group.add(dataTable); fragment.add(new ClearIndicatingAjaxButton("bulkActionLink", bulkActionForm, pageRef) { http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/panels/Any.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/Any.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/Any.java deleted file mode 100644 index 8d99606..0000000 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/Any.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.syncope.client.console.panels; - -import org.apache.wicket.markup.html.panel.Panel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class Any extends Panel { - - private static final long serialVersionUID = -1100228004207271270L; - - protected static final Logger LOG = LoggerFactory.getLogger(Any.class); - - public Any(final String id) { - super(id); - } - -} http://git-wip-us.apache.org/repos/asf/syncope/blob/518f7bef/client/console/src/main/java/org/apache/syncope/client/console/panels/AnySearchResultPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnySearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnySearchResultPanel.java new file mode 100644 index 0000000..21f7609 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnySearchResultPanel.java @@ -0,0 +1,264 @@ +/* + * 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.panels; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.pages.AnyDisplayAttributesModalPage; +import org.apache.syncope.client.console.rest.AbstractAnyRestClient; +import org.apache.syncope.client.console.rest.AnyObjectRestClient; +import org.apache.syncope.client.console.rest.SchemaRestClient; +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.AttrColumn; +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.AnyTO; +import org.apache.syncope.common.lib.to.AnyTypeClassTO; +import org.apache.syncope.common.lib.to.AnyObjectTO; +import org.apache.syncope.common.lib.types.SchemaType; +import org.apache.wicket.Page; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +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.markup.html.basic.Label; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.spring.injection.annot.SpringBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.ReflectionUtils; + +public class AnySearchResultPanel extends AbstractSearchResultPanel { + + private static final long serialVersionUID = -1100228004207271270L; + + protected static final Logger LOG = LoggerFactory.getLogger(AnySearchResultPanel.class); + + private String customMarkupId; + + @SpringBean + protected SchemaRestClient schemaRestClient; + + protected final List<String> schemaNames; + + protected final List<String> dSchemaNames; + + protected final String pageID = "Any"; + + private final String entitlement = "USER_LIST"; + + public AnySearchResultPanel(final String type, final String parentId, final String markupId, final boolean filtered, + final String fiql, final PageReference callerRef, final AbstractAnyRestClient restClient, + final List<AnyTypeClassTO> anyTypeClassTOs, final String realm) { + super(parentId, filtered, fiql, callerRef, restClient, realm, type); + setCustomMarkupId(markupId); + add(new Label("name", type)); + + this.schemaNames = new ArrayList<String>(); + for (AnyTypeClassTO anyTypeClassTO : anyTypeClassTOs) { + this.schemaNames.addAll(anyTypeClassTO.getPlainSchemas()); + } + this.dSchemaNames = new ArrayList<String>(); + for (AnyTypeClassTO anyTypeClassTO : anyTypeClassTOs) { + this.dSchemaNames.addAll(anyTypeClassTO.getDerSchemas()); + } + + initResultTable(); + } + + public String getCustomMarkupId() { + return customMarkupId; + } + + public void setCustomMarkupId(final String markupId) { + this.customMarkupId = markupId; + } + + @Override + protected List<IColumn<AnyTO, String>> getColumns() { + + final List<IColumn<AnyTO, String>> columns = + new ArrayList<IColumn<AnyTO, String>>(); + + for (String name : prefMan.getList(getRequest(), Constants.PREF_ANY_DETAILS_VIEW)) { + final Field field = ReflectionUtils.findField(AnyObjectTO.class, name); + + if ("token".equalsIgnoreCase(name)) { + columns.add(new PropertyColumn<AnyTO, String>(new ResourceModel(name, name), name, name)); + } else if (field != null && field.getType().equals(Date.class)) { + columns.add(new PropertyColumn<AnyTO, String>(new ResourceModel(name, name), name, name)); + } else { + columns.add( + new PropertyColumn<AnyTO, String>(new ResourceModel(name, name), name, name)); + } + } + + for (String name : prefMan.getList(getRequest(), Constants.PREF_ANY_ATTRIBUTES_VIEW)) { + if (schemaNames.contains(name)) { + columns.add(new AttrColumn(name, SchemaType.PLAIN)); + } + } + + for (String name : prefMan.getList(getRequest(), Constants.PREF_ANY_DERIVED_ATTRIBUTES_VIEW)) { + if (dSchemaNames.contains(name)) { + columns.add(new AttrColumn(name, SchemaType.DERIVED)); + } + } + + // Add defaults in case of no selection + if (columns.isEmpty()) { + for (String name : AnyDisplayAttributesModalPage.ANY_DEFAULT_SELECTION) { + columns.add( + new PropertyColumn<AnyTO, String>(new ResourceModel(name, name), name, name)); + } + + } + + columns.add(new ActionColumn<AnyTO, String>(new ResourceModel("actions", "")) { + + private static final long serialVersionUID = -3503023501954863131L; + + @Override + public ActionLinksPanel getActions(final String componentId, final IModel<AnyTO> model) { + + final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, page.getPageReference()); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(final AjaxRequestTarget target) { + editmodal.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + // SYNCOPE-294: re-read anyTO before edit + AnyObjectTO anyTO = ((AnyObjectRestClient) restClient).read(model.getObject().getKey()); + return null; + } + }); + + editmodal.show(target); + } + }, ActionLink.ActionType.EDIT, entitlement); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(final AjaxRequestTarget target) { + try { + final AnyObjectTO anyTO = (AnyObjectTO) restClient. + delete(model.getObject().getETagValue(), model.getObject().getKey()); + + page.setModalResult(true); + + editmodal.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + return null; + } + }); + + editmodal.show(target); + } catch (SyncopeClientException scce) { + error(getString(Constants.OPERATION_ERROR) + ": " + scce.getMessage()); + feedbackPanel.refresh(target); + } + } + }, ActionLink.ActionType.DELETE, entitlement); + + return panel; + } + + @Override + public ActionLinksPanel getHeader(final String componentId) { + final ActionLinksPanel panel = new ActionLinksPanel(componentId, new Model(), page.getPageReference()); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(final AjaxRequestTarget target) { + displaymodal.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + return new AnyDisplayAttributesModalPage( + page.getPageReference(), displaymodal, schemaNames, dSchemaNames); + } + }); + + displaymodal.show(target); + } + }, ActionLink.ActionType.CHANGE_VIEW, entitlement); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(final AjaxRequestTarget target) { + if (target != null) { + target.add(container); + } + } + }, ActionLink.ActionType.RELOAD, entitlement); + + return panel; + } + }); + + return columns; + } + + @Override + protected <T extends AnyTO> Collection<ActionLink.ActionType> getBulkActions() { + final List<ActionLink.ActionType> bulkActions = new ArrayList<ActionLink.ActionType>(); + + bulkActions.add(ActionLink.ActionType.DELETE); + bulkActions.add(ActionLink.ActionType.SUSPEND); + bulkActions.add(ActionLink.ActionType.REACTIVATE); + + return bulkActions; + } + + @Override + protected String getPageId() { + return pageID; + } +}
