This is an automated email from the ASF dual-hosted git repository. ilgrosso pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/syncope.git
commit a355b0800f124dbd53aff374e63d12b6e87efd35 Author: Francesco Chicchiriccò <[email protected]> AuthorDate: Mon Jun 28 16:26:29 2021 +0200 [SYNCOPE-1545] WA > Sessions --- .../client/console/commons/AMConstants.java | 2 + .../apache/syncope/client/console/pages/WA.java | 31 +-- .../console/panels/SRARouteDirectoryPanel.java | 2 - .../console/panels/WASessionDirectoryPanel.java | 209 +++++++++++++++++++++ .../client/console/panels/WASessionPanel.java | 91 +++++++++ .../syncope/client/console/rest/WASession.java | 71 +++++++ .../client/console/rest/WASessionDeserializer.java | 83 ++++++++ .../client/console/rest/WASessionRestClient.java | 106 +++++++++++ .../panels/WASessionDirectoryPanel.properties | 22 +++ .../WASessionDirectoryPanel_fr_CA.properties | 22 +++ .../panels/WASessionDirectoryPanel_it.properties | 22 +++ .../panels/WASessionDirectoryPanel_ja.properties | 22 +++ .../WASessionDirectoryPanel_pt_BR.properties | 22 +++ .../panels/WASessionDirectoryPanel_ru.properties | 22 +++ .../client/console/panels/WASessionPanel.html | 36 ++++ .../client/console/rest/BaseRestClient.java | 4 +- .../syncope/common/lib/types/AMEntitlement.java | 4 + 17 files changed, 752 insertions(+), 19 deletions(-) diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/commons/AMConstants.java b/client/am/console/src/main/java/org/apache/syncope/client/console/commons/AMConstants.java index 564227c..7b2eb35 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/commons/AMConstants.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/commons/AMConstants.java @@ -24,6 +24,8 @@ public final class AMConstants { public static final String PREF_WACONFIG_PAGINATOR_ROWS = "waconfig.paginator.rows"; + public static final String PREF_WASESSION_PAGINATOR_ROWS = "wasession.paginator.rows"; + public static final String PREF_AUTHMODULE_PAGINATOR_ROWS = "authmodule.paginator.rows"; public static final String PREF_CLIENTAPP_PAGINATOR_ROWS = "clientapp.paginator.rows"; diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java index 30312b4..cc283b1 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java @@ -38,13 +38,12 @@ import org.apache.syncope.client.console.clientapps.ClientApps; import org.apache.syncope.client.console.panels.OIDC; import org.apache.syncope.client.console.panels.SAML2; import org.apache.syncope.client.console.panels.WAConfigDirectoryPanel; +import org.apache.syncope.client.console.panels.WASessionPanel; import org.apache.syncope.client.console.rest.WAConfigRestClient; import org.apache.syncope.client.ui.commons.Constants; -import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel; import org.apache.syncope.client.ui.commons.pages.BaseWebPage; import org.apache.syncope.common.keymaster.client.api.ServiceOps; import org.apache.syncope.common.keymaster.client.api.model.NetworkService; -import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.common.lib.types.AMEntitlement; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxLink; @@ -75,6 +74,8 @@ public class WA extends BasePage { body.add(BookmarkablePageLinkBuilder.build("dashboard", "dashboardBr", Dashboard.class)); body.setOutputMarkupId(true); + List<NetworkService> waInstances = serviceOps.list(NetworkService.Type.WA); + AjaxLink<?> push = new AjaxLink<>("push") { @Override @@ -90,19 +91,20 @@ public class WA extends BasePage { ((BaseWebPage) getPageReference().getPage()).getNotificationPanel().refresh(target); } }; - push.setEnabled(!serviceOps.list(NetworkService.Type.WA).isEmpty() - && SyncopeConsoleSession.get().owns(AMEntitlement.WA_CONFIG_PUSH, SyncopeConstants.ROOT_REALM)); + push.setEnabled(!waInstances.isEmpty() + && SyncopeConsoleSession.get().owns(AMEntitlement.WA_CONFIG_PUSH)); body.add(push); WebMarkupContainer content = new WebMarkupContainer("content"); content.setOutputMarkupId(true); - AjaxBootstrapTabbedPanel<ITab> tabbedPanel = new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList()); + AjaxBootstrapTabbedPanel<ITab> tabbedPanel = + new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList(waInstances)); content.add(tabbedPanel); body.add(content); - if (!serviceOps.list(NetworkService.Type.WA).isEmpty()) { - String actuatorEndpoint = serviceOps.list(NetworkService.Type.WA).get(0).getAddress() + "/actuator/env"; + if (!waInstances.isEmpty()) { + String actuatorEndpoint = waInstances.get(0).getAddress() + "/actuator/env"; try { Response response = WebClient.create( actuatorEndpoint, @@ -132,10 +134,10 @@ public class WA extends BasePage { } } - private List<ITab> buildTabList() { + private List<ITab> buildTabList(final List<NetworkService> waInstances) { List<ITab> tabs = new ArrayList<>(0); - if (SyncopeConsoleSession.get().owns(AMEntitlement.AUTH_MODULE_LIST, SyncopeConstants.ROOT_REALM)) { + if (SyncopeConsoleSession.get().owns(AMEntitlement.AUTH_MODULE_LIST)) { tabs.add(new AbstractTab(new ResourceModel("authModules")) { private static final long serialVersionUID = 5211692813425391144L; @@ -147,7 +149,7 @@ public class WA extends BasePage { }); } - if (SyncopeConsoleSession.get().owns(AMEntitlement.CLIENTAPP_LIST, SyncopeConstants.ROOT_REALM)) { + if (SyncopeConsoleSession.get().owns(AMEntitlement.CLIENTAPP_LIST)) { tabs.add(new AbstractTab(new ResourceModel("clientApps")) { private static final long serialVersionUID = 5211692813425391144L; @@ -179,7 +181,7 @@ public class WA extends BasePage { } }); - if (SyncopeConsoleSession.get().owns(AMEntitlement.WA_CONFIG_LIST, SyncopeConstants.ROOT_REALM)) { + if (SyncopeConsoleSession.get().owns(AMEntitlement.WA_CONFIG_LIST)) { tabs.add(new AbstractTab(new ResourceModel("config")) { private static final long serialVersionUID = 5211692813425391144L; @@ -191,7 +193,7 @@ public class WA extends BasePage { }); } - if (SyncopeConsoleSession.get().owns(AMEntitlement.AUTH_PROFILE_LIST, SyncopeConstants.ROOT_REALM)) { + if (SyncopeConsoleSession.get().owns(AMEntitlement.AUTH_PROFILE_LIST)) { tabs.add(new AbstractTab(new ResourceModel("authProfiles")) { private static final long serialVersionUID = 5211692813425391144L; @@ -203,15 +205,14 @@ public class WA extends BasePage { }); } - List<NetworkService> instances = serviceOps.list(NetworkService.Type.WA); - if (!instances.isEmpty()) { + if (!waInstances.isEmpty() && SyncopeConsoleSession.get().owns(AMEntitlement.WA_SESSION_LIST)) { tabs.add(new AbstractTab(new ResourceModel("sessions")) { private static final long serialVersionUID = 5211692813425391144L; @Override public Panel getPanel(final String panelId) { - return new AjaxTextFieldPanel(panelId, panelId, Model.of(instances.get(0).getAddress())); + return new WASessionPanel(panelId, waInstances, getPageReference()); } }); } diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/SRARouteDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/SRARouteDirectoryPanel.java index 7008abe..2357cb1 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/SRARouteDirectoryPanel.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/SRARouteDirectoryPanel.java @@ -67,8 +67,6 @@ public class SRARouteDirectoryPanel modal.show(false); }); - restClient = new SRARouteRestClient(); - addNewItemPanelBuilder(new SRARouteWizardBuilder(new SRARouteTO(), pageRef), true); initResultTable(); } diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/WASessionDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/WASessionDirectoryPanel.java new file mode 100644 index 0000000..db74094 --- /dev/null +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/WASessionDirectoryPanel.java @@ -0,0 +1,209 @@ +/* + * 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 de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Stream; +import org.apache.syncope.client.console.SyncopeConsoleSession; +import org.apache.syncope.client.console.commons.AMConstants; +import org.apache.syncope.client.console.commons.SortableDataProviderComparator; +import org.apache.syncope.client.console.panels.WASessionDirectoryPanel.WASessionProvider; +import org.apache.syncope.client.console.panels.WASessionPanel.WASessionSearchEvent; +import org.apache.syncope.client.console.rest.WASession; +import org.apache.syncope.client.console.rest.WASessionRestClient; +import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn; +import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.KeyPropertyColumn; +import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal; +import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink; +import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel; +import org.apache.syncope.client.console.wicket.markup.html.form.JsonEditorPanel; +import org.apache.syncope.client.ui.commons.Constants; +import org.apache.syncope.client.ui.commons.DirectoryDataProvider; +import org.apache.syncope.client.ui.commons.pages.BaseWebPage; +import org.apache.syncope.common.keymaster.client.api.model.NetworkService; +import org.apache.syncope.common.lib.SyncopeClientException; +import org.apache.syncope.common.lib.types.AMEntitlement; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.event.IEvent; +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.model.CompoundPropertyModel; +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 WASessionDirectoryPanel + extends DirectoryPanel<WASession, WASession, WASessionProvider, WASessionRestClient> { + + private static final long serialVersionUID = 24083331272114L; + + private final BaseModal<String> viewModal; + + private final List<NetworkService> waInstances; + + private String keyword; + + public WASessionDirectoryPanel( + final String id, + final List<NetworkService> waInstances, + final PageReference pageRef) { + + super(id, pageRef); + this.waInstances = waInstances; + + disableCheckBoxes(); + + viewModal = new BaseModal<>(Constants.OUTER) { + + private static final long serialVersionUID = 389935548143327858L; + + @Override + protected void onConfigure() { + super.onConfigure(); + setFooterVisible(false); + } + }; + viewModal.size(Modal.Size.Extra_large); + viewModal.setWindowClosedCallback(target -> viewModal.show(false)); + addOuterObject(viewModal); + + initResultTable(); + } + + @Override + protected List<IColumn<WASession, String>> getColumns() { + List<IColumn<WASession, String>> columns = new ArrayList<>(); + + columns.add(new KeyPropertyColumn<>( + new StringResourceModel(Constants.KEY_FIELD_NAME, this), Constants.KEY_FIELD_NAME)); + columns.add(new DatePropertyColumn<>( + new ResourceModel("authenticationDate"), "authenticationDate", "authenticationDate")); + columns.add(new PropertyColumn<>( + new ResourceModel("authenticatedPrincipal"), "authenticatedPrincipal", "authenticatedPrincipal")); + return columns; + } + + @Override + protected ActionsPanel<WASession> getActions(final IModel<WASession> model) { + ActionsPanel<WASession> panel = super.getActions(model); + + panel.add(new ActionLink<WASession>() { + + private static final long serialVersionUID = 22687128346032L; + + @Override + public void onClick(final AjaxRequestTarget target, final WASession ignore) { + viewModal.header(new ResourceModel("details")); + target.add(viewModal.setContent( + new JsonEditorPanel(viewModal, Model.of(model.getObject().getJson()), true, pageRef))); + viewModal.show(true); + } + }, ActionLink.ActionType.VIEW, AMEntitlement.WA_SESSION_LIST); + + panel.add(new ActionLink<WASession>() { + + private static final long serialVersionUID = -4608353559809323466L; + + @Override + public void onClick(final AjaxRequestTarget target, final WASession ignore) { + WASession waSession = model.getObject(); + try { + WASessionRestClient.delete(waInstances, waSession.getKey()); + SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED)); + target.add(container); + } catch (SyncopeClientException e) { + LOG.error("While deleting {}", waSession.getKey(), e); + SyncopeConsoleSession.get().onException(e); + } + ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target); + } + }, ActionLink.ActionType.DELETE, AMEntitlement.WA_SESSION_DELETE, true); + + return panel; + } + + @Override + protected Collection<ActionLink.ActionType> getBatches() { + return List.of(); + } + + @Override + protected WASessionProvider dataProvider() { + return new WASessionProvider(rows); + } + + @Override + protected String paginatorRowsKey() { + return AMConstants.PREF_WASESSION_PAGINATOR_ROWS; + } + + @Override + public void onEvent(final IEvent<?> event) { + if (event.getPayload() instanceof WASessionSearchEvent) { + WASessionSearchEvent payload = WASessionSearchEvent.class.cast(event.getPayload()); + keyword = payload.getKeyword(); + + updateResultTable(payload.getTarget()); + } else { + super.onEvent(event); + } + } + + protected final class WASessionProvider extends DirectoryDataProvider<WASession> { + + private static final long serialVersionUID = 18002870965042L; + + private final SortableDataProviderComparator<WASession> comparator; + + public WASessionProvider(final int paginatorRows) { + super(paginatorRows); + setSort("authenticationDate", SortOrder.ASCENDING); + comparator = new SortableDataProviderComparator<>(this); + } + + private Stream<WASession> filtered() { + Stream<WASession> stream = WASessionRestClient.list(waInstances).stream(); + return keyword == null + ? stream + : stream.filter(s -> s.getJson().contains(keyword)); + } + + @Override + public Iterator<? extends WASession> iterator(final long first, final long count) { + return filtered().skip(first).limit(count).sorted(comparator).iterator(); + } + + @Override + public long size() { + return filtered().count(); + } + + @Override + public IModel<WASession> model(final WASession waSession) { + return new CompoundPropertyModel<>(waSession); + } + } +} diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/WASessionPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/WASessionPanel.java new file mode 100644 index 0000000..24439d9 --- /dev/null +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/WASessionPanel.java @@ -0,0 +1,91 @@ +/* + * 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.io.Serializable; +import java.util.List; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel; +import org.apache.syncope.common.keymaster.client.api.model.NetworkService; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; +import org.apache.wicket.event.Broadcast; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.Model; + +public class WASessionPanel extends Panel { + + private static final long serialVersionUID = 30189416462011L; + + public WASessionPanel(final String id, final List<NetworkService> waInstances, final PageReference pageRef) { + super(id); + + Model<String> keywordModel = new Model<>(StringUtils.EMPTY); + + WebMarkupContainer searchBoxContainer = new WebMarkupContainer("searchBox"); + add(searchBoxContainer); + + WASessionDirectoryPanel directoryPanel = new WASessionDirectoryPanel("directoryPanel", waInstances, pageRef); + add(directoryPanel); + + Form<?> form = new Form<>("form"); + searchBoxContainer.add(form); + + AjaxTextFieldPanel filter = new AjaxTextFieldPanel("filter", "filter", keywordModel, true); + form.add(filter.hideLabel().setOutputMarkupId(true).setRenderBodyOnly(true)); + + AjaxButton search = new AjaxButton("search") { + + private static final long serialVersionUID = 8390605330558248736L; + + @Override + protected void onSubmit(final AjaxRequestTarget target) { + send(directoryPanel, Broadcast.EXACT, new WASessionSearchEvent(target, keywordModel.getObject())); + } + }; + search.setOutputMarkupId(true); + form.add(search); + form.setDefaultButton(search); + } + + public static class WASessionSearchEvent implements Serializable { + + private static final long serialVersionUID = 5063826346823013424L; + + private final transient AjaxRequestTarget target; + + private final String keyword; + + WASessionSearchEvent(final AjaxRequestTarget target, final String keyword) { + this.target = target; + this.keyword = keyword; + } + + public AjaxRequestTarget getTarget() { + return target; + } + + public String getKeyword() { + return keyword; + } + } +} diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WASession.java b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WASession.java new file mode 100644 index 0000000..2ecdda2 --- /dev/null +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WASession.java @@ -0,0 +1,71 @@ +/* + * 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.rest; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import java.util.Date; +import org.apache.syncope.common.lib.to.EntityTO; + +@JsonDeserialize(using = WASessionDeserializer.class) +public class WASession implements EntityTO { + + private static final long serialVersionUID = 18201657700802L; + + private String key; + + private Date authenticationDate; + + private String authenticatedPrincipal; + + private String json; + + @Override + public String getKey() { + return key; + } + + @Override + public void setKey(final String key) { + this.key = key; + } + + public Date getAuthenticationDate() { + return authenticationDate; + } + + public void setAuthenticationDate(final Date authenticationDate) { + this.authenticationDate = authenticationDate; + } + + public String getAuthenticatedPrincipal() { + return authenticatedPrincipal; + } + + public void setAuthenticatedPrincipal(final String authenticatedPrincipal) { + this.authenticatedPrincipal = authenticatedPrincipal; + } + + public String getJson() { + return json; + } + + public void setJson(final String json) { + this.json = json; + } +} diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WASessionDeserializer.java b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WASessionDeserializer.java new file mode 100644 index 0000000..12d39d9 --- /dev/null +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WASessionDeserializer.java @@ -0,0 +1,83 @@ +/* + * 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.rest; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import java.io.IOException; +import java.io.StringWriter; +import java.text.ParseException; +import org.apache.commons.lang3.time.DateFormatUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WASessionDeserializer extends StdDeserializer<WASession> { + + private static final long serialVersionUID = 24527200564172L; + + private static final Logger LOG = LoggerFactory.getLogger(WASessionDeserializer.class); + + public WASessionDeserializer() { + this(null); + } + + public WASessionDeserializer(final Class<?> vc) { + super(vc); + } + + @Override + public WASession deserialize(final JsonParser jp, final DeserializationContext ctxt) + throws IOException, JsonProcessingException { + + JsonNode node = jp.getCodec().readTree(jp); + + WASession waSession = new WASession(); + + if (node.has("authentication_date_formatted")) { + String authenticationDate = node.get("authentication_date_formatted").textValue(); + try { + waSession.setAuthenticationDate( + DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.parse(authenticationDate)); + } catch (ParseException e) { + LOG.error("Unparsable date: {}", authenticationDate, e); + } + } + + if (node.has("authenticated_principal")) { + waSession.setAuthenticatedPrincipal(node.get("authenticated_principal").textValue()); + } + + if (node.has("ticket_granting_ticket")) { + waSession.setKey(node.get("ticket_granting_ticket").textValue()); + } + + StringWriter writer = new StringWriter(); + JsonGenerator jgen = jp.getCodec().getFactory().createGenerator(writer); + jgen.setPrettyPrinter(new DefaultPrettyPrinter()); + jp.getCodec().writeTree(jgen, node); + waSession.setJson(writer.toString()); + + return waSession; + } +} diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WASessionRestClient.java b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WASessionRestClient.java new file mode 100644 index 0000000..94aaf65 --- /dev/null +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WASessionRestClient.java @@ -0,0 +1,106 @@ +/* + * 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.rest; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.InputStream; +import java.util.List; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.apache.cxf.jaxrs.client.WebClient; +import org.apache.syncope.client.console.SyncopeWebApplication; +import org.apache.syncope.client.ui.commons.rest.RestClient; +import org.apache.syncope.common.keymaster.client.api.model.NetworkService; +import org.apache.syncope.common.lib.SyncopeClientException; +import org.apache.syncope.common.lib.types.ClientExceptionType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class WASessionRestClient implements RestClient { + + private static final long serialVersionUID = 22118820292494L; + + private static final Logger LOG = LoggerFactory.getLogger(WASessionRestClient.class); + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + private static String getActuatorEndpoint(final List<NetworkService> waInstances) { + return waInstances.get(0).getAddress() + "/actuator/ssoSessions"; + } + + public static List<WASession> list(final List<NetworkService> waInstances) { + try { + Response response = WebClient.create( + getActuatorEndpoint(waInstances), + SyncopeWebApplication.get().getAnonymousUser(), + SyncopeWebApplication.get().getAnonymousKey(), + null). + accept(MediaType.APPLICATION_JSON_TYPE).get(); + if (response.getStatus() == Response.Status.OK.getStatusCode()) { + JsonNode node = MAPPER.readTree((InputStream) response.getEntity()); + if (node.has("activeSsoSessions")) { + return MAPPER.readValue( + MAPPER.treeAsTokens(node.get("activeSsoSessions")), + new TypeReference<List<WASession>>() { + }); + } + } else { + LOG.error("Unexpected response for SSO Sessions from {}: {}", + getActuatorEndpoint(waInstances), response.getStatus()); + } + } catch (Exception e) { + LOG.error("Could not fetch SSO Sessions from {}", getActuatorEndpoint(waInstances), e); + } + + return List.of(); + } + + public static void delete(final List<NetworkService> waInstances, final String ticketGrantingTicket) { + SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown); + + try { + Response response = WebClient.create( + getActuatorEndpoint(waInstances), + SyncopeWebApplication.get().getAnonymousUser(), + SyncopeWebApplication.get().getAnonymousKey(), + null). + path(ticketGrantingTicket). + accept(MediaType.APPLICATION_JSON_TYPE).type(MediaType.APPLICATION_JSON_TYPE).delete(); + if (response.getStatus() != Response.Status.OK.getStatusCode()) { + LOG.error("Unexpected response when deleting SSO Session {} from {}: {}", + ticketGrantingTicket, getActuatorEndpoint(waInstances), response.getStatus()); + sce.getElements().add("Unexpected response code: " + response.getStatus()); + } + } catch (Exception e) { + LOG.error("Could not delete SSO Session {} from {}", + ticketGrantingTicket, getActuatorEndpoint(waInstances), e); + sce.getElements().add("Unexpected error: " + e.getMessage()); + } + + if (!sce.getElements().isEmpty()) { + throw sce; + } + } + + private WASessionRestClient() { + // private constructor for static utility class + } +} diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel.properties new file mode 100644 index 0000000..7883872 --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel.properties @@ -0,0 +1,22 @@ +# 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. +any.edit=Edit ${key} +any.finish=Submit ${key} +any.cancel=Cancel ${key} +authenticationDate=Creation Date +authenticatedPrincipal=Principal +details=Details diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_fr_CA.properties new file mode 100644 index 0000000..0baec19 --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_fr_CA.properties @@ -0,0 +1,22 @@ +# 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. +any.edit=Modifier ${key} +any.finish=Soumettre ${key} +any.cancel=Annuler ${key} +authenticationDate=Creation Date +authenticatedPrincipal=Principal +details=Details diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_it.properties new file mode 100644 index 0000000..6df8cdc --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_it.properties @@ -0,0 +1,22 @@ +# 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. +any.edit=Modifica ${key} +any.finish=Invia ${key} +any.cancel=Annulla ${key} +authenticationDate=Data di Creazione +authenticatedPrincipal=Soggetto +details=Dettagli diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_ja.properties new file mode 100644 index 0000000..c5c1d0d --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_ja.properties @@ -0,0 +1,22 @@ +# 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. +any.edit=${key} \u3092\u7de8\u96c6 +any.finish=${key} \u3092\u5b9f\u884c +any.cancel=${key} \u3092\u30ad\u30e3\u30f3\u30bb\u30eb +authenticationDate=Creation Date +authenticatedPrincipal=Principal +details=Details diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_pt_BR.properties new file mode 100644 index 0000000..7883872 --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_pt_BR.properties @@ -0,0 +1,22 @@ +# 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. +any.edit=Edit ${key} +any.finish=Submit ${key} +any.cancel=Cancel ${key} +authenticationDate=Creation Date +authenticatedPrincipal=Principal +details=Details diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_ru.properties new file mode 100644 index 0000000..63e4a85 --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionDirectoryPanel_ru.properties @@ -0,0 +1,22 @@ +# 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. +any.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c ${key} +any.finish=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c ${key} +any.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c ${key} +authenticationDate=Creation Date +authenticatedPrincipal=Principal +details=Details diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionPanel.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionPanel.html new file mode 100644 index 0000000..362e7ed --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WASessionPanel.html @@ -0,0 +1,36 @@ +<!-- +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. +--> +<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org"> + <wicket:panel> + <div wicket:id="searchBox"> + <form wicket:id="form"> + <div class="input-group mb-3"> + <span wicket:id="filter">[FILTER]</span> + <span class="input-group-btn"> + <button type="button" class="btn btn-default btn-flat" wicket:id="search"> + <span class="fas fa-search" aria-hidden="true"></span> + </button> + </span> + </div> + </form> + </div> + + <div wicket:id="directoryPanel"></div> + </wicket:panel> +</html> diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java index 8127725..979d173 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java @@ -38,10 +38,10 @@ import org.slf4j.LoggerFactory; public abstract class BaseRestClient implements RestClient { - protected static final Logger LOG = LoggerFactory.getLogger(BaseRestClient.class); - private static final long serialVersionUID = 1523999867826481989L; + protected static final Logger LOG = LoggerFactory.getLogger(BaseRestClient.class); + public static SyncopeService getSyncopeService() { return getService(SyncopeService.class); } diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java index 7de374e..1869e18 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java @@ -96,6 +96,10 @@ public final class AMEntitlement { public static final String WA_CONFIG_PUSH = "WA_CONFIG_PUSH"; + public static final String WA_SESSION_LIST = "WA_SESSION_LIST"; + + public static final String WA_SESSION_DELETE = "WA_SESSION_DELETE"; + private static final Set<String> VALUES; static {
