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.panels;
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.Base64;
25  import java.util.Collection;
26  import java.util.Iterator;
27  import java.util.List;
28  import org.apache.commons.lang3.StringUtils;
29  import org.apache.syncope.client.console.SyncopeConsoleSession;
30  import org.apache.syncope.client.console.commons.DirectoryDataProvider;
31  import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
32  import org.apache.syncope.client.console.layout.UserFormLayoutInfo;
33  import org.apache.syncope.client.console.pages.BasePage;
34  import org.apache.syncope.client.console.panels.SAML2IdPsDirectoryPanel.SAML2IdPsProvider;
35  import org.apache.syncope.client.console.rest.AnyTypeRestClient;
36  import org.apache.syncope.client.console.rest.ImplementationRestClient;
37  import org.apache.syncope.client.console.rest.SAML2IdPsRestClient;
38  import org.apache.syncope.client.console.rest.UserRestClient;
39  import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.BooleanPropertyColumn;
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.ActionLinksTogglePanel;
44  import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
45  import org.apache.syncope.client.console.wicket.markup.html.form.XMLEditorPanel;
46  import org.apache.syncope.client.console.wizards.SAML2IdPWizardBuilder;
47  import org.apache.syncope.client.console.wizards.WizardMgtPanel;
48  import org.apache.syncope.client.console.wizards.any.UserTemplateWizardBuilder;
49  import org.apache.syncope.client.ui.commons.Constants;
50  import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
51  import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
52  import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
53  import org.apache.syncope.common.lib.SyncopeClientException;
54  import org.apache.syncope.common.lib.to.SAML2SP4UIIdPTO;
55  import org.apache.syncope.common.lib.to.UserTO;
56  import org.apache.syncope.common.lib.types.AnyTypeKind;
57  import org.apache.syncope.common.lib.types.SAML2SP4UIEntitlement;
58  import org.apache.wicket.MarkupContainer;
59  import org.apache.wicket.PageReference;
60  import org.apache.wicket.ajax.AjaxRequestTarget;
61  import org.apache.wicket.ajax.markup.html.AjaxLink;
62  import org.apache.wicket.event.Broadcast;
63  import org.apache.wicket.event.IEvent;
64  import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
65  import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
66  import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
67  import org.apache.wicket.model.CompoundPropertyModel;
68  import org.apache.wicket.model.IModel;
69  import org.apache.wicket.model.Model;
70  import org.apache.wicket.model.ResourceModel;
71  import org.apache.wicket.model.StringResourceModel;
72  import org.apache.wicket.spring.injection.annot.SpringBean;
73  
74  public class SAML2IdPsDirectoryPanel extends DirectoryPanel<
75          SAML2SP4UIIdPTO, SAML2SP4UIIdPTO, SAML2IdPsProvider, SAML2IdPsRestClient> {
76  
77      private static final long serialVersionUID = 4792356089584116041L;
78  
79      protected static final String PREF_SAML2_IDPS_PAGINATOR_ROWS = "saml2.idps.paginator.rows";
80  
81      @SpringBean
82      protected AnyTypeRestClient anyTypeRestClient;
83  
84      @SpringBean
85      protected UserRestClient userRestClient;
86  
87      @SpringBean
88      protected ImplementationRestClient implementationRestClient;
89  
90      protected final BaseModal<String> metadataModal = new BaseModal<>("outer");
91  
92      protected final BaseModal<Serializable> templateModal;
93  
94      public SAML2IdPsDirectoryPanel(final String id, final SAML2IdPsRestClient restClient, final PageReference pageRef) {
95          super(id, new Builder<SAML2SP4UIIdPTO, SAML2SP4UIIdPTO, SAML2IdPsRestClient>(restClient, pageRef) {
96  
97              private static final long serialVersionUID = 8517982765290075155L;
98  
99              @Override
100             protected WizardMgtPanel<SAML2SP4UIIdPTO> newInstance(final String id, final boolean wizardInModal) {
101                 throw new UnsupportedOperationException();
102             }
103         }.disableCheckBoxes());
104 
105         addNewItemPanelBuilder(new SAML2IdPWizardBuilder(
106                 this, new SAML2SP4UIIdPTO(), implementationRestClient, restClient, pageRef), false);
107 
108         modal.addSubmitButton();
109         modal.size(Modal.Size.Large);
110         modal.setWindowClosedCallback(target -> {
111             updateResultTable(target);
112             modal.show(false);
113         });
114 
115         addOuterObject(metadataModal);
116         setWindowClosedReloadCallback(metadataModal);
117         metadataModal.size(Modal.Size.Large);
118 
119         templateModal = new BaseModal<>("outer") {
120 
121             private static final long serialVersionUID = 5787433530654262016L;
122 
123             @Override
124             protected void onConfigure() {
125                 super.onConfigure();
126                 setFooterVisible(false);
127             }
128         };
129         templateModal.setWindowClosedCallback(target -> templateModal.show(false));
130         templateModal.size(Modal.Size.Large);
131         addOuterObject(templateModal);
132 
133         initResultTable();
134 
135         final ImportMetadata importMetadata = new ImportMetadata("importMetadata", container, pageRef);
136         addInnerObject(importMetadata);
137         AjaxLink<Void> importMetadataLink = new AjaxLink<>("add") {
138 
139             private static final long serialVersionUID = -7978723352517770644L;
140 
141             @Override
142             public void onClick(final AjaxRequestTarget target) {
143                 importMetadata.toggle(target, true);
144             }
145         };
146         ((MarkupContainer) get("container:content")).addOrReplace(importMetadataLink);
147     }
148 
149     @Override
150     protected SAML2IdPsProvider dataProvider() {
151         return new SAML2IdPsProvider(rows);
152     }
153 
154     @Override
155     protected ActionLinksTogglePanel<SAML2SP4UIIdPTO> actionTogglePanel() {
156         return new ActionLinksTogglePanel<>(Constants.OUTER, pageRef) {
157 
158             private static final long serialVersionUID = -7688359318035249200L;
159 
160             @Override
161             public void updateHeader(final AjaxRequestTarget target, final Serializable modelObject) {
162                 if (modelObject instanceof SAML2SP4UIIdPTO) {
163                     setHeader(target, StringUtils.abbreviate(
164                             ((SAML2SP4UIIdPTO) modelObject).getName(), HEADER_FIRST_ABBREVIATION));
165                 } else {
166                     super.updateHeader(target, modelObject);
167                 }
168             }
169         };
170     }
171 
172     @Override
173     protected String paginatorRowsKey() {
174         return PREF_SAML2_IDPS_PAGINATOR_ROWS;
175     }
176 
177     @Override
178     protected Collection<ActionLink.ActionType> getBatches() {
179         return List.of();
180     }
181 
182     @Override
183     protected List<IColumn<SAML2SP4UIIdPTO, String>> getColumns() {
184         List<IColumn<SAML2SP4UIIdPTO, String>> columns = new ArrayList<>();
185 
186         columns.add(new KeyPropertyColumn<>(new ResourceModel("key"), "key", "key"));
187         columns.add(new PropertyColumn<>(new ResourceModel("name"), "name", "name"));
188         columns.add(new PropertyColumn<>(new ResourceModel("entityID"), "entityID", "entityID"));
189         columns.add(new PropertyColumn<>(
190                 new ResourceModel("bindingType"), "bindingType", "bindingType"));
191         columns.add(new BooleanPropertyColumn<>(
192                 new ResourceModel("logoutSupported"), "logoutSupported", "logoutSupported"));
193 
194         return columns;
195     }
196 
197     @Override
198     public ActionsPanel<SAML2SP4UIIdPTO> getActions(final IModel<SAML2SP4UIIdPTO> model) {
199         final ActionsPanel<SAML2SP4UIIdPTO> panel = super.getActions(model);
200 
201         panel.add(new ActionLink<>() {
202 
203             private static final long serialVersionUID = -7978723352517770645L;
204 
205             @Override
206             public void onClick(final AjaxRequestTarget target, final SAML2SP4UIIdPTO ignore) {
207                 SAML2SP4UIIdPTO object = restClient.read(model.getObject().getKey());
208                 metadataModal.header(Model.of(object.getName() + " - Metadata"));
209                 metadataModal.setContent(new XMLEditorPanel(
210                         metadataModal,
211                         Model.of(new String(Base64.getMimeDecoder().decode(object.getMetadata()))),
212                         true,
213                         pageRef));
214                 metadataModal.show(true);
215                 target.add(metadataModal);
216             }
217         }, ActionLink.ActionType.HTML, SAML2SP4UIEntitlement.IDP_READ);
218         panel.add(new ActionLink<>() {
219 
220             private static final long serialVersionUID = -3722207913631435501L;
221 
222             @Override
223             public void onClick(final AjaxRequestTarget target, final SAML2SP4UIIdPTO ignore) {
224                 SAML2SP4UIIdPTO object = restClient.read(model.getObject().getKey());
225                 send(SAML2IdPsDirectoryPanel.this, Broadcast.EXACT,
226                         new AjaxWizard.EditItemActionEvent<>(object, target));
227             }
228         }, ActionLink.ActionType.EDIT, SAML2SP4UIEntitlement.IDP_UPDATE);
229         panel.add(new ActionLink<>() {
230 
231             private static final long serialVersionUID = -3722207913631435501L;
232 
233             @Override
234             public void onClick(final AjaxRequestTarget target, final SAML2SP4UIIdPTO ignore) {
235                 final SAML2SP4UIIdPTO object = restClient.read(model.getObject().getKey());
236 
237                 UserTemplateWizardBuilder builder = new UserTemplateWizardBuilder(
238                         object.getUserTemplate(),
239                         anyTypeRestClient.read(AnyTypeKind.USER.name()).getClasses(),
240                         new UserFormLayoutInfo(),
241                         userRestClient,
242                         pageRef) {
243 
244                     private static final long serialVersionUID = -7978723352517770634L;
245 
246                     @Override
247                     protected Serializable onApplyInternal(final AnyWrapper<UserTO> modelObject) {
248                         object.setUserTemplate(modelObject.getInnerObject());
249                         restClient.update(object);
250 
251                         return modelObject;
252                     }
253                 };
254                 templateModal.header(Model.of(StringUtils.capitalize(
255                         new StringResourceModel("template.title", SAML2IdPsDirectoryPanel.this).getString())));
256                 templateModal.setContent(builder.build(BaseModal.CONTENT_ID));
257                 templateModal.show(true);
258                 target.add(templateModal);
259 
260             }
261         }, ActionLink.ActionType.TEMPLATE, SAML2SP4UIEntitlement.IDP_UPDATE);
262         panel.add(new ActionLink<>() {
263 
264             private static final long serialVersionUID = -5467832321897812767L;
265 
266             @Override
267             public void onClick(final AjaxRequestTarget target, final SAML2SP4UIIdPTO ignore) {
268                 try {
269                     restClient.delete(model.getObject().getKey());
270                     SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
271                     target.add(container);
272                 } catch (SyncopeClientException e) {
273                     LOG.error("While deleting object {}", model.getObject().getKey(), e);
274                     SyncopeConsoleSession.get().onException(e);
275                 }
276                 ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
277             }
278         }, ActionLink.ActionType.DELETE, SAML2SP4UIEntitlement.IDP_DELETE, true);
279 
280         return panel;
281     }
282 
283     @Override
284     public void onEvent(final IEvent<?> event) {
285         super.onEvent(event);
286 
287         if (event.getPayload() instanceof AjaxWizard.NewItemEvent) {
288             AjaxWizard.NewItemEvent<?> newItemEvent = AjaxWizard.NewItemEvent.class.cast(event.getPayload());
289             WizardModalPanel<?> modalPanel = newItemEvent.getModalPanel();
290 
291             if (newItemEvent instanceof AjaxWizard.NewItemActionEvent && modalPanel != null) {
292                 IModel<Serializable> model = new CompoundPropertyModel<>(modalPanel.getItem());
293                 templateModal.setFormModel(model);
294                 templateModal.header(newItemEvent.getTitleModel());
295                 newItemEvent.getTarget().ifPresent(target -> target.add(templateModal.setContent(modalPanel)));
296                 templateModal.show(true);
297             } else if (newItemEvent instanceof AjaxWizard.NewItemCancelEvent) {
298                 newItemEvent.getTarget().ifPresent(templateModal::close);
299             } else if (newItemEvent instanceof AjaxWizard.NewItemFinishEvent) {
300                 newItemEvent.getTarget().ifPresent(templateModal::close);
301             }
302         }
303     }
304 
305     protected final class SAML2IdPsProvider extends DirectoryDataProvider<SAML2SP4UIIdPTO> {
306 
307         private static final long serialVersionUID = -185944053385660794L;
308 
309         private final SortableDataProviderComparator<SAML2SP4UIIdPTO> comparator;
310 
311         private SAML2IdPsProvider(final int paginatorRows) {
312             super(paginatorRows);
313 
314             setSort("name", SortOrder.ASCENDING);
315             comparator = new SortableDataProviderComparator<>(this);
316         }
317 
318         @Override
319         public Iterator<SAML2SP4UIIdPTO> iterator(final long first, final long count) {
320             List<SAML2SP4UIIdPTO> list = restClient.list();
321             list.sort(comparator);
322             return list.subList((int) first, (int) first + (int) count).iterator();
323         }
324 
325         @Override
326         public long size() {
327             return restClient.list().size();
328         }
329 
330         @Override
331         public IModel<SAML2SP4UIIdPTO> model(final SAML2SP4UIIdPTO object) {
332             return new CompoundPropertyModel<>(object);
333         }
334     }
335 }