View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.client.console.pages;
20  
21  import com.fasterxml.jackson.databind.JsonNode;
22  import com.fasterxml.jackson.databind.json.JsonMapper;
23  import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
24  import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
25  import java.io.InputStream;
26  import java.io.Serializable;
27  import java.util.ArrayList;
28  import java.util.List;
29  import javax.ws.rs.core.MediaType;
30  import javax.ws.rs.core.Response;
31  import org.apache.commons.lang3.StringUtils;
32  import org.apache.cxf.jaxrs.client.WebClient;
33  import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
34  import org.apache.syncope.client.console.SyncopeConsoleSession;
35  import org.apache.syncope.client.console.SyncopeWebApplication;
36  import org.apache.syncope.client.console.annotations.AMPage;
37  import org.apache.syncope.client.console.authprofiles.AuthProfileDirectoryPanel;
38  import org.apache.syncope.client.console.clientapps.ClientApps;
39  import org.apache.syncope.client.console.panels.AMSessionPanel;
40  import org.apache.syncope.client.console.panels.AttrRepoDirectoryPanel;
41  import org.apache.syncope.client.console.panels.AuthModuleDirectoryPanel;
42  import org.apache.syncope.client.console.panels.OIDC;
43  import org.apache.syncope.client.console.panels.SAML2;
44  import org.apache.syncope.client.console.panels.WAConfigDirectoryPanel;
45  import org.apache.syncope.client.console.panels.WAPushModalPanel;
46  import org.apache.syncope.client.console.rest.AttrRepoRestClient;
47  import org.apache.syncope.client.console.rest.AuthModuleRestClient;
48  import org.apache.syncope.client.console.rest.AuthProfileRestClient;
49  import org.apache.syncope.client.console.rest.WAConfigRestClient;
50  import org.apache.syncope.client.console.rest.WASessionRestClient;
51  import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
52  import org.apache.syncope.common.keymaster.client.api.ServiceOps;
53  import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
54  import org.apache.syncope.common.lib.types.AMEntitlement;
55  import org.apache.wicket.ajax.AjaxRequestTarget;
56  import org.apache.wicket.ajax.markup.html.AjaxLink;
57  import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
58  import org.apache.wicket.extensions.markup.html.tabs.ITab;
59  import org.apache.wicket.markup.html.WebMarkupContainer;
60  import org.apache.wicket.markup.html.panel.Panel;
61  import org.apache.wicket.model.Model;
62  import org.apache.wicket.model.ResourceModel;
63  import org.apache.wicket.request.mapper.parameter.PageParameters;
64  import org.apache.wicket.spring.injection.annot.SpringBean;
65  
66  @AMPage(label = "WA", icon = "fas fa-id-card", listEntitlement = "", priority = 200)
67  public class WA extends BasePage {
68  
69      private static final long serialVersionUID = 9200112197134882164L;
70  
71      protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
72  
73      @SpringBean
74      protected WAConfigRestClient waConfigRestClient;
75  
76      @SpringBean
77      protected AuthProfileRestClient authProfileRestClient;
78  
79      @SpringBean
80      protected AuthModuleRestClient authModuleRestClient;
81  
82      @SpringBean
83      protected AttrRepoRestClient attrRepoRestClient;
84  
85      @SpringBean
86      protected ServiceOps serviceOps;
87  
88      protected final BaseModal<Serializable> modal;
89  
90      protected String waPrefix = "";
91  
92      public WA(final PageParameters parameters) {
93          super(parameters);
94  
95          body.add(BookmarkablePageLinkBuilder.build("dashboard", "dashboardBr", Dashboard.class));
96          body.setOutputMarkupId(true);
97  
98          List<NetworkService> instances = serviceOps.list(NetworkService.Type.WA);
99  
100         modal = new BaseModal<>("push-modal");
101         modal.setWindowClosedCallback(target -> modal.show(false));
102         modal.addSubmitButton();
103         body.add(modal.size(Modal.Size.Large));
104 
105         AjaxLink<?> push = new AjaxLink<>("push") {
106 
107             private static final long serialVersionUID = -817438685948164787L;
108 
109             @Override
110             public void onClick(final AjaxRequestTarget target) {
111                 modal.header(new ResourceModel("push.options"));
112                 modal.setContent(new WAPushModalPanel(modal, instances, getPageReference()));
113                 modal.show(true);
114                 target.add(modal);
115             }
116         };
117         push.setEnabled(!instances.isEmpty() && SyncopeConsoleSession.get().owns(AMEntitlement.WA_CONFIG_PUSH));
118         body.add(push);
119 
120         WebMarkupContainer content = new WebMarkupContainer("content");
121         content.setOutputMarkupId(true);
122         AjaxBootstrapTabbedPanel<ITab> tabbedPanel =
123                 new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList(instances));
124         content.add(tabbedPanel);
125 
126         body.add(content);
127 
128         if (!instances.isEmpty()) {
129             String actuatorEndpoint = StringUtils.appendIfMissing(instances.get(0).getAddress(), "/") + "actuator/env";
130             try {
131                 Response response = WebClient.create(
132                         actuatorEndpoint,
133                         SyncopeWebApplication.get().getAnonymousUser(),
134                         SyncopeWebApplication.get().getAnonymousKey(),
135                         null).
136                         accept(MediaType.APPLICATION_JSON_TYPE).get();
137                 if (response.getStatus() == Response.Status.OK.getStatusCode()) {
138                     JsonNode env = MAPPER.readTree((InputStream) response.getEntity());
139                     if (env.has("propertySources")) {
140                         for (JsonNode propertySource : env.get("propertySources")) {
141                             if (propertySource.has("properties")) {
142                                 JsonNode properties = propertySource.get("properties");
143                                 if (properties.has("cas.server.prefix")) {
144                                     JsonNode prefix = properties.get("cas.server.prefix");
145                                     if (prefix.has("value")) {
146                                         waPrefix = StringUtils.removeEnd(prefix.get("value").asText(), "/");
147                                     }
148                                 }
149                             }
150                         }
151                     }
152                 }
153             } catch (Exception e) {
154                 LOG.error("While contacting {}", actuatorEndpoint, e);
155             }
156 
157             if (StringUtils.isBlank(waPrefix)) {
158                 waPrefix = StringUtils.removeEnd(instances.get(0).getAddress(), "/");
159             }
160         }
161     }
162 
163     protected List<ITab> buildTabList(final List<NetworkService> instances) {
164         List<ITab> tabs = new ArrayList<>();
165 
166         if (SyncopeConsoleSession.get().owns(AMEntitlement.AUTH_MODULE_LIST)) {
167             tabs.add(new AbstractTab(new ResourceModel("authModules")) {
168 
169                 private static final long serialVersionUID = 5211692813425391144L;
170 
171                 @Override
172                 public Panel getPanel(final String panelId) {
173                     return new AuthModuleDirectoryPanel(panelId, authModuleRestClient, getPageReference());
174                 }
175             });
176         }
177 
178         if (SyncopeConsoleSession.get().owns(AMEntitlement.ATTR_REPO_LIST)) {
179             tabs.add(new AbstractTab(new ResourceModel("attrRepos")) {
180 
181                 private static final long serialVersionUID = 5211692813425391144L;
182 
183                 @Override
184                 public Panel getPanel(final String panelId) {
185                     return new AttrRepoDirectoryPanel(panelId, attrRepoRestClient, getPageReference());
186                 }
187             });
188         }
189 
190         if (SyncopeConsoleSession.get().owns(AMEntitlement.CLIENTAPP_LIST)) {
191             tabs.add(new AbstractTab(new ResourceModel("clientApps")) {
192 
193                 private static final long serialVersionUID = 5211692813425391144L;
194 
195                 @Override
196                 public Panel getPanel(final String panelId) {
197                     return new ClientApps(panelId, getPageReference());
198                 }
199             });
200         }
201 
202         tabs.add(new AbstractTab(Model.of("SAML 2.0")) {
203 
204             private static final long serialVersionUID = 5211692813425391144L;
205 
206             @Override
207             public Panel getPanel(final String panelId) {
208                 return new SAML2(panelId, waPrefix, getPageReference());
209             }
210         });
211 
212         tabs.add(new AbstractTab(Model.of("OIDC 1.0")) {
213 
214             private static final long serialVersionUID = 5211692813425391144L;
215 
216             @Override
217             public Panel getPanel(final String panelId) {
218                 return new OIDC(panelId, waPrefix, getPageReference());
219             }
220         });
221 
222         if (SyncopeConsoleSession.get().owns(AMEntitlement.WA_CONFIG_LIST)) {
223             tabs.add(new AbstractTab(new ResourceModel("config")) {
224 
225                 private static final long serialVersionUID = 5211692813425391144L;
226 
227                 @Override
228                 public Panel getPanel(final String panelId) {
229                     return new WAConfigDirectoryPanel(panelId, waConfigRestClient, getPageReference());
230                 }
231             });
232         }
233 
234         if (SyncopeConsoleSession.get().owns(AMEntitlement.AUTH_PROFILE_LIST)) {
235             tabs.add(new AbstractTab(new ResourceModel("authProfiles")) {
236 
237                 private static final long serialVersionUID = 5211692813425391144L;
238 
239                 @Override
240                 public Panel getPanel(final String panelId) {
241                     return new AuthProfileDirectoryPanel(panelId, authProfileRestClient, getPageReference());
242                 }
243             });
244         }
245 
246         if (!instances.isEmpty() && SyncopeConsoleSession.get().owns(AMEntitlement.WA_SESSION_LIST)) {
247             tabs.add(new AbstractTab(new ResourceModel("sessions")) {
248 
249                 private static final long serialVersionUID = 5211692813425391144L;
250 
251                 @Override
252                 public Panel getPanel(final String panelId) {
253                     return new AMSessionPanel(panelId, new WASessionRestClient(instances),
254                             AMEntitlement.WA_SESSION_LIST, AMEntitlement.WA_SESSION_DELETE, getPageReference());
255                 }
256             });
257         }
258 
259         return tabs;
260     }
261 }