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.clientapps;
20  
21  import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
22  import java.io.Serializable;
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.Iterator;
26  import java.util.List;
27  import org.apache.commons.lang3.SerializationUtils;
28  import org.apache.syncope.client.console.SyncopeConsoleSession;
29  import org.apache.syncope.client.console.audit.AuditHistoryModal;
30  import org.apache.syncope.client.console.commons.AMConstants;
31  import org.apache.syncope.client.console.commons.DirectoryDataProvider;
32  import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
33  import org.apache.syncope.client.console.pages.BasePage;
34  import org.apache.syncope.client.console.panels.DirectoryPanel;
35  import org.apache.syncope.client.console.panels.ModalDirectoryPanel;
36  import org.apache.syncope.client.console.rest.AuditRestClient;
37  import org.apache.syncope.client.console.rest.ClientAppRestClient;
38  import org.apache.syncope.client.console.rest.PolicyRestClient;
39  import org.apache.syncope.client.console.rest.RealmRestClient;
40  import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.KeyPropertyColumn;
41  import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
42  import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
43  import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
44  import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
45  import org.apache.syncope.client.ui.commons.Constants;
46  import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
47  import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
48  import org.apache.syncope.common.lib.SyncopeClientException;
49  import org.apache.syncope.common.lib.to.ClientAppTO;
50  import org.apache.syncope.common.lib.types.AMEntitlement;
51  import org.apache.syncope.common.lib.types.AuditElements;
52  import org.apache.syncope.common.lib.types.ClientAppType;
53  import org.apache.syncope.common.lib.types.IdRepoEntitlement;
54  import org.apache.wicket.PageReference;
55  import org.apache.wicket.ajax.AjaxRequestTarget;
56  import org.apache.wicket.event.Broadcast;
57  import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
58  import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
59  import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
60  import org.apache.wicket.model.CompoundPropertyModel;
61  import org.apache.wicket.model.IModel;
62  import org.apache.wicket.model.Model;
63  import org.apache.wicket.model.StringResourceModel;
64  import org.apache.wicket.spring.injection.annot.SpringBean;
65  
66  public abstract class ClientAppDirectoryPanel<T extends ClientAppTO>
67          extends DirectoryPanel<T, T, DirectoryDataProvider<T>, ClientAppRestClient> {
68  
69      private static final long serialVersionUID = 4100100988730985059L;
70  
71      @SpringBean
72      protected PolicyRestClient policyRestClient;
73  
74      @SpringBean
75      protected ClientAppRestClient clientAppRestClient;
76  
77      @SpringBean
78      protected RealmRestClient realmRestClient;
79  
80      @SpringBean
81      protected AuditRestClient auditRestClient;
82  
83      protected final ClientAppType type;
84  
85      protected final BaseModal<T> propertiesModal;
86  
87      protected final BaseModal<Serializable> historyModal;
88  
89      public ClientAppDirectoryPanel(
90              final String id,
91              final ClientAppRestClient restClient,
92              final ClientAppType type,
93              final PageReference pageRef) {
94  
95          super(id, restClient, pageRef, true);
96          this.type = type;
97  
98          modal.addSubmitButton();
99          modal.size(Modal.Size.Large);
100         modal.setWindowClosedCallback(target -> {
101             updateResultTable(target);
102             modal.show(false);
103         });
104         setFooterVisibility(true);
105 
106         propertiesModal = new BaseModal<>(Constants.OUTER) {
107 
108             private static final long serialVersionUID = 389935548143327858L;
109 
110             @Override
111             protected void onConfigure() {
112                 super.onConfigure();
113                 setFooterVisible(false);
114             }
115         };
116         propertiesModal.size(Modal.Size.Large);
117         propertiesModal.setWindowClosedCallback(target -> propertiesModal.show(false));
118         addOuterObject(propertiesModal);
119 
120         disableCheckBoxes();
121 
122         historyModal = new BaseModal<>(Constants.OUTER);
123         historyModal.size(Modal.Size.Large);
124         addOuterObject(historyModal);
125     }
126 
127     @Override
128     protected List<IColumn<T, String>> getColumns() {
129         List<IColumn<T, String>> columns = new ArrayList<>();
130 
131         columns.add(new KeyPropertyColumn<>(
132                 new StringResourceModel(Constants.KEY_FIELD_NAME, this), Constants.KEY_FIELD_NAME));
133         columns.add(new PropertyColumn<>(
134                 new StringResourceModel(Constants.NAME_FIELD_NAME, this),
135                 Constants.NAME_FIELD_NAME, Constants.NAME_FIELD_NAME));
136         columns.add(new PropertyColumn<>(
137                 new StringResourceModel("clientAppId", this), "clientAppId", "clientAppId"));
138 
139         addCustomColumnFields(columns);
140 
141         return columns;
142     }
143 
144     protected void addCustomColumnFields(final List<IColumn<T, String>> columns) {
145     }
146 
147     @Override
148     public ActionsPanel<T> getActions(final IModel<T> model) {
149         ActionsPanel<T> panel = super.getActions(model);
150 
151         panel.add(new ActionLink<>() {
152 
153             private static final long serialVersionUID = -3722207913631435501L;
154 
155             @Override
156             public void onClick(final AjaxRequestTarget target, final ClientAppTO ignore) {
157                 send(ClientAppDirectoryPanel.this, Broadcast.EXACT,
158                         new AjaxWizard.EditItemActionEvent<>(
159                                 restClient.read(type, model.getObject().getKey()), target));
160             }
161         }, ActionLink.ActionType.EDIT, AMEntitlement.CLIENTAPP_UPDATE);
162 
163         panel.add(new ActionLink<>() {
164 
165             private static final long serialVersionUID = -3722207913631435501L;
166 
167             @Override
168             public void onClick(final AjaxRequestTarget target, final ClientAppTO ignore) {
169                 model.setObject(restClient.read(type, model.getObject().getKey()));
170                 modal.setContent(new UsernameAttributeProviderModalPanelBuilder<>(
171                         type, model.getObject(), modal, clientAppRestClient, pageRef).
172                         build(actualId, 1, AjaxWizard.Mode.EDIT));
173                 modal.header(new Model<>(getString("usernameAttributeProviderConf.title", model)));
174                 modal.show(true);
175                 target.add(modal);
176             }
177         }, ActionLink.ActionType.COMPOSE, AMEntitlement.CLIENTAPP_UPDATE);
178 
179         panel.add(new ActionLink<>() {
180 
181             private static final long serialVersionUID = -3722207913631435501L;
182 
183             @Override
184             public void onClick(final AjaxRequestTarget target, final ClientAppTO ignore) {
185                 model.setObject(restClient.read(type, model.getObject().getKey()));
186                 target.add(propertiesModal.setContent(new ModalDirectoryPanel<>(
187                         propertiesModal,
188                         new ClientAppPropertiesDirectoryPanel<>(
189                                 "panel", restClient, propertiesModal, type, model, pageRef),
190                         pageRef)));
191                 propertiesModal.header(new Model<>(getString("properties.title", model)));
192                 propertiesModal.show(true);
193             }
194         }, ActionLink.ActionType.TYPE_EXTENSIONS, AMEntitlement.CLIENTAPP_UPDATE);
195 
196         panel.add(new ActionLink<>() {
197 
198             private static final long serialVersionUID = -5432034353017728756L;
199 
200             @Override
201             public void onClick(final AjaxRequestTarget target, final ClientAppTO ignore) {
202                 model.setObject(restClient.read(type, model.getObject().getKey()));
203 
204                 target.add(historyModal.setContent(new AuditHistoryModal<>(
205                         AuditElements.EventCategoryType.LOGIC,
206                         "ClientAppLogic",
207                         model.getObject(),
208                         AMEntitlement.CLIENTAPP_UPDATE,
209                         auditRestClient) {
210 
211                     private static final long serialVersionUID = -3712506022627033811L;
212 
213                     @Override
214                     protected void restore(final String json, final AjaxRequestTarget target) {
215                         try {
216                             ClientAppTO updated = MAPPER.readValue(json, ClientAppTO.class);
217                             restClient.update(type, updated);
218 
219                             SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
220                         } catch (Exception e) {
221                             LOG.error("While restoring ClientApp {}", ((ClientAppTO) model.getObject()).getKey(), e);
222                             SyncopeConsoleSession.get().onException(e);
223                         }
224                         ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
225                     }
226                 }));
227 
228                 historyModal.header(new Model<>(getString("auditHistory.title", new Model<>(model.getObject()))));
229 
230                 historyModal.show(true);
231             }
232         }, ActionLink.ActionType.VIEW_AUDIT_HISTORY, String.format("%s,%s", AMEntitlement.CLIENTAPP_READ,
233                 IdRepoEntitlement.AUDIT_LIST));
234 
235         panel.add(new ActionLink<>() {
236 
237             private static final long serialVersionUID = -3722207913631435501L;
238 
239             @Override
240             public void onClick(final AjaxRequestTarget target, final ClientAppTO ignore) {
241                 ClientAppTO clone = SerializationUtils.clone(model.getObject());
242                 clone.setKey(null);
243                 clone.setClientAppId(null);
244                 send(ClientAppDirectoryPanel.this, Broadcast.EXACT,
245                         new AjaxWizard.EditItemActionEvent<>(clone, target));
246             }
247         }, ActionLink.ActionType.CLONE, AMEntitlement.CLIENTAPP_CREATE);
248 
249         panel.add(new ActionLink<>() {
250 
251             private static final long serialVersionUID = -3722207913631435501L;
252 
253             @Override
254             public void onClick(final AjaxRequestTarget target, final ClientAppTO ignore) {
255                 T clientAppTO = model.getObject();
256                 try {
257                     restClient.delete(type, clientAppTO.getKey());
258 
259                     SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
260                     target.add(container);
261                 } catch (SyncopeClientException e) {
262                     LOG.error("While deleting {}", clientAppTO.getKey(), e);
263                     SyncopeConsoleSession.get().onException(e);
264                 }
265                 ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
266             }
267         }, ActionLink.ActionType.DELETE, AMEntitlement.CLIENTAPP_DELETE, true);
268 
269         return panel;
270     }
271 
272     @Override
273     protected Collection<ActionType> getBatches() {
274         return List.of();
275     }
276 
277     @Override
278     protected ClientAppDataProvider dataProvider() {
279         return new ClientAppDataProvider(rows);
280     }
281 
282     @Override
283     protected String paginatorRowsKey() {
284         return AMConstants.PREF_CLIENTAPP_PAGINATOR_ROWS;
285     }
286 
287     protected class ClientAppDataProvider extends DirectoryDataProvider<T> {
288 
289         private static final long serialVersionUID = 4725679400450513556L;
290 
291         private final SortableDataProviderComparator<T> comparator;
292 
293         ClientAppDataProvider(final int paginatorRows) {
294             super(paginatorRows);
295 
296             setSort(Constants.NAME_FIELD_NAME, SortOrder.ASCENDING);
297             comparator = new SortableDataProviderComparator<>(this);
298         }
299 
300         @Override
301         public Iterator<T> iterator(final long first, final long count) {
302             List<T> list = restClient.list(type);
303             list.sort(comparator);
304             return list.subList((int) first, (int) first + (int) count).iterator();
305         }
306 
307         @Override
308         public long size() {
309             return restClient.list(type).size();
310         }
311 
312         @Override
313         public IModel<T> model(final T object) {
314             return new CompoundPropertyModel<>(object);
315         }
316     }
317 }