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.syncope.client.console.BookmarkablePageLinkBuilder;
33  import org.apache.syncope.client.console.SyncopeConsoleSession;
34  import org.apache.syncope.client.console.SyncopeWebApplication;
35  import org.apache.syncope.client.console.annotations.AMPage;
36  import org.apache.syncope.client.console.authprofiles.AuthProfileDirectoryPanel;
37  import org.apache.syncope.client.console.clientapps.ClientApps;
38  import org.apache.syncope.client.console.panels.AMSessionPanel;
39  import org.apache.syncope.client.console.panels.AttrRepoDirectoryPanel;
40  import org.apache.syncope.client.console.panels.AuthModuleDirectoryPanel;
41  import org.apache.syncope.client.console.panels.OIDC;
42  import org.apache.syncope.client.console.panels.SAML2;
43  import org.apache.syncope.client.console.panels.WAConfigDirectoryPanel;
44  import org.apache.syncope.client.console.panels.WAPushModalPanel;
45  import org.apache.syncope.client.console.rest.AttrRepoRestClient;
46  import org.apache.syncope.client.console.rest.AuthModuleRestClient;
47  import org.apache.syncope.client.console.rest.AuthProfileRestClient;
48  import org.apache.syncope.client.console.rest.WAConfigRestClient;
49  import org.apache.syncope.client.console.rest.WASessionRestClient;
50  import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
51  import org.apache.syncope.client.lib.WebClientBuilder;
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 = WebClientBuilder.build(actuatorEndpoint,
132                         SyncopeWebApplication.get().getAnonymousUser(),
133                         SyncopeWebApplication.get().getAnonymousKey(),
134                         List.of()).accept(MediaType.APPLICATION_JSON_TYPE).get();
135                 if (response.getStatus() == Response.Status.OK.getStatusCode()) {
136                     JsonNode env = MAPPER.readTree((InputStream) response.getEntity());
137                     if (env.has("propertySources")) {
138                         for (JsonNode propertySource : env.get("propertySources")) {
139                             if (propertySource.has("properties")) {
140                                 JsonNode properties = propertySource.get("properties");
141                                 if (properties.has("cas.server.prefix")) {
142                                     JsonNode prefix = properties.get("cas.server.prefix");
143                                     if (prefix.has("value")) {
144                                         waPrefix = StringUtils.removeEnd(prefix.get("value").asText(), "/");
145                                     }
146                                 }
147                             }
148                         }
149                     }
150                 }
151             } catch (Exception e) {
152                 LOG.error("While contacting {}", actuatorEndpoint, e);
153             }
154 
155             if (StringUtils.isBlank(waPrefix)) {
156                 waPrefix = StringUtils.removeEnd(instances.get(0).getAddress(), "/");
157             }
158         }
159     }
160 
161     protected List<ITab> buildTabList(final List<NetworkService> instances) {
162         List<ITab> tabs = new ArrayList<>();
163 
164         if (SyncopeConsoleSession.get().owns(AMEntitlement.AUTH_MODULE_LIST)) {
165             tabs.add(new AbstractTab(new ResourceModel("authModules")) {
166 
167                 private static final long serialVersionUID = 5211692813425391144L;
168 
169                 @Override
170                 public Panel getPanel(final String panelId) {
171                     return new AuthModuleDirectoryPanel(panelId, authModuleRestClient, getPageReference());
172                 }
173             });
174         }
175 
176         if (SyncopeConsoleSession.get().owns(AMEntitlement.ATTR_REPO_LIST)) {
177             tabs.add(new AbstractTab(new ResourceModel("attrRepos")) {
178 
179                 private static final long serialVersionUID = 5211692813425391144L;
180 
181                 @Override
182                 public Panel getPanel(final String panelId) {
183                     return new AttrRepoDirectoryPanel(panelId, attrRepoRestClient, getPageReference());
184                 }
185             });
186         }
187 
188         if (SyncopeConsoleSession.get().owns(AMEntitlement.CLIENTAPP_LIST)) {
189             tabs.add(new AbstractTab(new ResourceModel("clientApps")) {
190 
191                 private static final long serialVersionUID = 5211692813425391144L;
192 
193                 @Override
194                 public Panel getPanel(final String panelId) {
195                     return new ClientApps(panelId, getPageReference());
196                 }
197             });
198         }
199 
200         tabs.add(new AbstractTab(Model.of("SAML 2.0")) {
201 
202             private static final long serialVersionUID = 5211692813425391144L;
203 
204             @Override
205             public Panel getPanel(final String panelId) {
206                 return new SAML2(panelId, waPrefix, getPageReference());
207             }
208         });
209 
210         tabs.add(new AbstractTab(Model.of("OIDC 1.0")) {
211 
212             private static final long serialVersionUID = 5211692813425391144L;
213 
214             @Override
215             public Panel getPanel(final String panelId) {
216                 return new OIDC(panelId, waPrefix, getPageReference());
217             }
218         });
219 
220         if (SyncopeConsoleSession.get().owns(AMEntitlement.WA_CONFIG_LIST)) {
221             tabs.add(new AbstractTab(new ResourceModel("config")) {
222 
223                 private static final long serialVersionUID = 5211692813425391144L;
224 
225                 @Override
226                 public Panel getPanel(final String panelId) {
227                     return new WAConfigDirectoryPanel(panelId, waConfigRestClient, getPageReference());
228                 }
229             });
230         }
231 
232         if (SyncopeConsoleSession.get().owns(AMEntitlement.AUTH_PROFILE_LIST)) {
233             tabs.add(new AbstractTab(new ResourceModel("authProfiles")) {
234 
235                 private static final long serialVersionUID = 5211692813425391144L;
236 
237                 @Override
238                 public Panel getPanel(final String panelId) {
239                     return new AuthProfileDirectoryPanel(panelId, authProfileRestClient, getPageReference());
240                 }
241             });
242         }
243 
244         if (!instances.isEmpty() && SyncopeConsoleSession.get().owns(AMEntitlement.WA_SESSION_LIST)) {
245             tabs.add(new AbstractTab(new ResourceModel("sessions")) {
246 
247                 private static final long serialVersionUID = 5211692813425391144L;
248 
249                 @Override
250                 public Panel getPanel(final String panelId) {
251                     return new AMSessionPanel(panelId, new WASessionRestClient(instances),
252                             AMEntitlement.WA_SESSION_LIST, AMEntitlement.WA_SESSION_DELETE, getPageReference());
253                 }
254             });
255         }
256 
257         return tabs;
258     }
259 }