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 java.nio.charset.StandardCharsets;
22  import java.util.ArrayList;
23  import java.util.Base64;
24  import java.util.Comparator;
25  import java.util.Iterator;
26  import java.util.LinkedHashMap;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.stream.Collectors;
30  import java.util.stream.Stream;
31  import javax.ws.rs.core.MediaType;
32  import org.apache.commons.lang3.RandomStringUtils;
33  import org.apache.commons.lang3.StringUtils;
34  import org.apache.syncope.client.console.SyncopeConsoleSession;
35  import org.apache.syncope.client.console.SyncopeWebApplication;
36  import org.apache.syncope.client.console.commons.RealmsUtils;
37  import org.apache.syncope.client.console.panels.AbstractModalPanel;
38  import org.apache.syncope.client.console.rest.ClientAppRestClient;
39  import org.apache.syncope.client.console.rest.PolicyRestClient;
40  import org.apache.syncope.client.console.rest.RealmRestClient;
41  import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
42  import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSearchFieldPanel;
43  import org.apache.syncope.client.console.wicket.markup.html.form.BinaryFieldPanel;
44  import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
45  import org.apache.syncope.client.console.wicket.markup.html.form.PolicyRenderer;
46  import org.apache.syncope.client.ui.commons.Constants;
47  import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
48  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
49  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
50  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
51  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
52  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
53  import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
54  import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
55  import org.apache.syncope.client.ui.commons.wizards.AbstractModalPanelBuilder;
56  import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
57  import org.apache.syncope.common.lib.OIDCScopeConstants;
58  import org.apache.syncope.common.lib.policy.PolicyTO;
59  import org.apache.syncope.common.lib.to.ClientAppTO;
60  import org.apache.syncope.common.lib.to.OIDCRPClientAppTO;
61  import org.apache.syncope.common.lib.to.RealmTO;
62  import org.apache.syncope.common.lib.types.ClientAppType;
63  import org.apache.syncope.common.lib.types.LogoutType;
64  import org.apache.syncope.common.lib.types.OIDCClientAuthenticationMethod;
65  import org.apache.syncope.common.lib.types.OIDCGrantType;
66  import org.apache.syncope.common.lib.types.OIDCResponseType;
67  import org.apache.syncope.common.lib.types.OIDCSubjectType;
68  import org.apache.syncope.common.lib.types.PolicyType;
69  import org.apache.syncope.common.lib.types.SAML2SPNameId;
70  import org.apache.syncope.common.lib.types.XmlSecAlgorithm;
71  import org.apache.wicket.Component;
72  import org.apache.wicket.PageReference;
73  import org.apache.wicket.ajax.AjaxRequestTarget;
74  import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteSettings;
75  import org.apache.wicket.markup.html.form.AbstractSingleSelectChoice;
76  import org.apache.wicket.markup.html.list.ListItem;
77  import org.apache.wicket.markup.html.list.ListView;
78  import org.apache.wicket.model.IModel;
79  import org.apache.wicket.model.LoadableDetachableModel;
80  import org.apache.wicket.model.Model;
81  import org.apache.wicket.model.PropertyModel;
82  import org.apache.wicket.model.util.ListModel;
83  import org.apache.wicket.validation.validator.UrlValidator;
84  
85  public class ClientAppModalPanelBuilder<T extends ClientAppTO> extends AbstractModalPanelBuilder<T> {
86  
87      private static final long serialVersionUID = 5945391813567245081L;
88  
89      protected final IModel<Map<String, String>> accessPolicies = new LoadableDetachableModel<>() {
90  
91          private static final long serialVersionUID = -2012833443695917883L;
92  
93          @Override
94          protected Map<String, String> load() {
95              return policyRestClient.list(PolicyType.ACCESS).stream().
96                      collect(Collectors.toMap(PolicyTO::getKey, PolicyTO::getName, (v1, v2) -> v1, LinkedHashMap::new));
97          }
98      };
99  
100     protected final IModel<Map<String, String>> attrReleasePolicies = new LoadableDetachableModel<>() {
101 
102         private static final long serialVersionUID = -2012833443695917883L;
103 
104         @Override
105         protected Map<String, String> load() {
106             return policyRestClient.list(PolicyType.ATTR_RELEASE).stream().
107                     collect(Collectors.toMap(PolicyTO::getKey, PolicyTO::getName, (v1, v2) -> v1, LinkedHashMap::new));
108         }
109     };
110 
111     protected final IModel<Map<String, String>> authPolicies = new LoadableDetachableModel<>() {
112 
113         private static final long serialVersionUID = -2012833443695917883L;
114 
115         @Override
116         protected Map<String, String> load() {
117             return policyRestClient.list(PolicyType.AUTH).stream().
118                     collect(Collectors.toMap(PolicyTO::getKey, PolicyTO::getName, (v1, v2) -> v1, LinkedHashMap::new));
119         }
120     };
121 
122     protected final IModel<Map<String, String>> ticketExpirationPolicies = new LoadableDetachableModel<>() {
123 
124         private static final long serialVersionUID = -2012833443695917883L;
125 
126         @Override
127         protected Map<String, String> load() {
128             return policyRestClient.list(PolicyType.TICKET_EXPIRATION).stream().
129                     collect(Collectors.toMap(PolicyTO::getKey, PolicyTO::getName, (v1, v2) -> v1, LinkedHashMap::new));
130         }
131     };
132 
133     protected final BaseModal<T> modal;
134 
135     protected final ClientAppType type;
136 
137     protected final PolicyRestClient policyRestClient;
138 
139     protected final ClientAppRestClient clientAppRestClient;
140 
141     protected final RealmRestClient realmRestClient;
142 
143     public ClientAppModalPanelBuilder(
144             final ClientAppType type,
145             final T defaultItem,
146             final BaseModal<T> modal,
147             final PolicyRestClient policyRestClient,
148             final ClientAppRestClient clientAppRestClient,
149             final RealmRestClient realmRestClient,
150             final PageReference pageRef) {
151 
152         super(defaultItem, pageRef);
153         this.type = type;
154         this.modal = modal;
155         this.policyRestClient = policyRestClient;
156         this.clientAppRestClient = clientAppRestClient;
157         this.realmRestClient = realmRestClient;
158     }
159 
160     @Override
161     public WizardModalPanel<T> build(final String id, final int index, final AjaxWizard.Mode mode) {
162         return new Profile(newModelObject(), modal, pageRef);
163     }
164 
165     private class Profile extends AbstractModalPanel<T> {
166 
167         private static final long serialVersionUID = 7647959917047450318L;
168 
169         private final T clientAppTO;
170 
171         Profile(final T clientAppTO, final BaseModal<T> modal, final PageReference pageRef) {
172             super(modal, pageRef);
173             modal.setFormModel(clientAppTO);
174 
175             this.clientAppTO = clientAppTO;
176 
177             List<Component> fields = new ArrayList<>();
178 
179             boolean fullRealmsTree = SyncopeWebApplication.get().fullRealmsTree(realmRestClient);
180             AutoCompleteSettings settings = new AutoCompleteSettings();
181             settings.setShowCompleteListOnFocusGain(fullRealmsTree);
182             settings.setShowListOnEmptyInput(fullRealmsTree);
183             AjaxSearchFieldPanel realm = new AjaxSearchFieldPanel(
184                     "field", "realm", new PropertyModel<>(clientAppTO, "realm"), settings) {
185 
186                 private static final long serialVersionUID = -6390474600233486704L;
187 
188                 @Override
189                 protected Iterator<String> getChoices(final String input) {
190                     return realmRestClient.search(fullRealmsTree
191                             ? RealmsUtils.buildRootQuery()
192                             : RealmsUtils.buildKeywordQuery(input)).getResult().stream().
193                             map(RealmTO::getFullPath).collect(Collectors.toList()).iterator();
194                 }
195             };
196             fields.add(realm.setOutputMarkupId(true));
197 
198             AjaxTextFieldPanel name = new AjaxTextFieldPanel(
199                     "field", Constants.NAME_FIELD_NAME,
200                     new PropertyModel<>(clientAppTO, Constants.NAME_FIELD_NAME), false);
201             fields.add(name.setRequired(true));
202 
203             if (clientAppTO.getClientAppId() == null) {
204                 Stream.of(ClientAppType.values()).map(clientAppRestClient::list).flatMap(List::stream).
205                         max(Comparator.comparing(ClientAppTO::getClientAppId)).
206                         ifPresent(app -> clientAppTO.setClientAppId(app.getClientAppId() + 1));
207             }
208             fields.add(new AjaxSpinnerFieldPanel.Builder<Long>().build(
209                     "field", "clientAppId", Long.class,
210                     new PropertyModel<>(clientAppTO, "clientAppId")).setRequired(true));
211 
212             fields.add(new AjaxTextFieldPanel(
213                     "field", Constants.DESCRIPTION_FIELD_NAME,
214                     new PropertyModel<>(clientAppTO, Constants.DESCRIPTION_FIELD_NAME), false));
215 
216             fields.add(new AjaxTextFieldPanel(
217                     "field", "logo",
218                     new PropertyModel<>(clientAppTO, "logo"), false));
219 
220             fields.add(new AjaxTextFieldPanel(
221                     "field", "theme",
222                     new PropertyModel<>(clientAppTO, "theme"), false));
223 
224             AjaxTextFieldPanel informationUrl = new AjaxTextFieldPanel(
225                     "field", "informationUrl",
226                     new PropertyModel<>(clientAppTO, "informationUrl"), false);
227             informationUrl.addValidator(new UrlValidator());
228             fields.add(informationUrl);
229 
230             AjaxTextFieldPanel privacyUrl = new AjaxTextFieldPanel(
231                     "field", "privacyUrl",
232                     new PropertyModel<>(clientAppTO, "privacyUrl"), false);
233             privacyUrl.addValidator(new UrlValidator());
234             fields.add(privacyUrl);
235 
236             AjaxDropDownChoicePanel<String> accessPolicy = new AjaxDropDownChoicePanel<>(
237                     "field", "accessPolicy", new PropertyModel<>(clientAppTO, "accessPolicy"), false);
238             accessPolicy.setChoiceRenderer(new PolicyRenderer(accessPolicies.getObject()));
239             accessPolicy.setChoices(new ArrayList<>(accessPolicies.getObject().keySet()));
240             ((AbstractSingleSelectChoice<?>) accessPolicy.getField()).setNullValid(true);
241             fields.add(accessPolicy);
242 
243             AjaxDropDownChoicePanel<String> attrReleasePolicy = new AjaxDropDownChoicePanel<>(
244                     "field", "attrReleasePolicy", new PropertyModel<>(clientAppTO, "attrReleasePolicy"), false);
245             attrReleasePolicy.setChoiceRenderer(new PolicyRenderer(attrReleasePolicies.getObject()));
246             attrReleasePolicy.setChoices(new ArrayList<>(attrReleasePolicies.getObject().keySet()));
247             ((AbstractSingleSelectChoice<?>) attrReleasePolicy.getField()).setNullValid(true);
248             fields.add(attrReleasePolicy);
249 
250             AjaxDropDownChoicePanel<String> authPolicy = new AjaxDropDownChoicePanel<>(
251                     "field", "authPolicy", new PropertyModel<>(clientAppTO, "authPolicy"), false);
252             authPolicy.setChoiceRenderer(new PolicyRenderer(authPolicies.getObject()));
253             authPolicy.setChoices(new ArrayList<>(authPolicies.getObject().keySet()));
254             fields.add(authPolicy);
255 
256             AjaxDropDownChoicePanel<String> ticketExpirationPolicy = new AjaxDropDownChoicePanel<>(
257                     "field", "ticketExpirationPolicy",
258                     new PropertyModel<>(clientAppTO, "ticketExpirationPolicy"), false);
259             ticketExpirationPolicy.setChoiceRenderer(new PolicyRenderer(ticketExpirationPolicies.getObject()));
260             ticketExpirationPolicy.setChoices(new ArrayList<>(ticketExpirationPolicies.getObject().keySet()));
261             ((AbstractSingleSelectChoice<?>) ticketExpirationPolicy.getField()).setNullValid(true);
262             fields.add(ticketExpirationPolicy);
263 
264             AjaxDropDownChoicePanel<LogoutType> logoutType = new AjaxDropDownChoicePanel<>(
265                     "field", "logoutType", new PropertyModel<>(clientAppTO, "logoutType"), false);
266             logoutType.setChoices(List.of(LogoutType.values()));
267             fields.add(logoutType.setRequired(true));
268 
269             switch (type) {
270                 case CASSP:
271                     fields.add(new AjaxTextFieldPanel(
272                             "field", "serviceId", new PropertyModel<>(clientAppTO, "serviceId"), false).
273                             setRequired(true));
274                     break;
275 
276                 case OIDCRP:
277                     AjaxTextFieldPanel clientId = new AjaxTextFieldPanel(
278                             "field", "clientId", new PropertyModel<>(clientAppTO, "clientId"), false);
279                     fields.add(clientId.setRequired(true));
280                     name.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
281 
282                         private static final long serialVersionUID = -6139318907146065915L;
283 
284                         @Override
285                         protected void onUpdate(final AjaxRequestTarget target) {
286                             if (StringUtils.isBlank(clientId.getModelObject())) {
287                                 clientId.setModelObject(name.getModelObject());
288                                 target.add(clientId);
289                             }
290                         }
291                     });
292 
293                     AjaxTextFieldPanel clientSecret = new AjaxTextFieldPanel(
294                             "field", "clientSecret", new PropertyModel<>(clientAppTO, "clientSecret"), false);
295                     clientSecret.setChoices(List.of(RandomStringUtils.randomAlphanumeric(15)));
296                     fields.add(clientSecret.setRequired(true));
297 
298                     fields.add(new AjaxCheckBoxPanel(
299                             "field", "signIdToken", new PropertyModel<>(clientAppTO, "signIdToken")));
300                     fields.add(new AjaxCheckBoxPanel(
301                             "field", "jwtAccessToken", new PropertyModel<>(clientAppTO, "jwtAccessToken")));
302                     fields.add(new AjaxCheckBoxPanel(
303                             "field", "bypassApprovalPrompt", new PropertyModel<>(clientAppTO, "bypassApprovalPrompt")));
304                     fields.add(new AjaxCheckBoxPanel(
305                             "field", "generateRefreshToken", new PropertyModel<>(clientAppTO, "generateRefreshToken")));
306 
307                     AjaxDropDownChoicePanel<OIDCSubjectType> subjectType = new AjaxDropDownChoicePanel<>(
308                             "field", "subjectType", new PropertyModel<>(clientAppTO, "subjectType"), false);
309                     subjectType.setChoices(List.of(OIDCSubjectType.values()));
310                     subjectType.addRequiredLabel().setEnabled(true);
311                     fields.add(subjectType);
312 
313                     AjaxTextFieldPanel redirectUri = new AjaxTextFieldPanel("panel", "redirectUris", new Model<>());
314                     fields.add(new MultiFieldPanel.Builder<String>(
315                             new PropertyModel<>(clientAppTO, "redirectUris")).build(
316                             "field",
317                             "redirectUris",
318                             redirectUri));
319 
320                     fields.add(new AjaxPalettePanel.Builder<OIDCGrantType>().setName("supportedGrantTypes").build(
321                             "field",
322                             new PropertyModel<>(clientAppTO, "supportedGrantTypes"),
323                             new ListModel<>(List.of(OIDCGrantType.values()))));
324 
325                     fields.add(new AjaxPalettePanel.Builder<OIDCResponseType>().setName("supportedResponseTypes").build(
326                             "field",
327                             new PropertyModel<>(clientAppTO, "supportedResponseTypes"),
328                             new ListModel<>(List.of(OIDCResponseType.values()))));
329 
330                     AutoCompleteSettings scopesSettings = new AutoCompleteSettings();
331                     scopesSettings.setShowCompleteListOnFocusGain(true);
332                     scopesSettings.setShowListOnEmptyInput(true);
333                     AjaxSearchFieldPanel scopes = new AjaxSearchFieldPanel(
334                             "panel", "scopes", new PropertyModel<>(clientAppTO, "scopes"), scopesSettings) {
335 
336                         private static final long serialVersionUID = 7160878678968866138L;
337 
338                         @Override
339                         protected Iterator<String> getChoices(final String input) {
340                             List<String> choices = new ArrayList<>(OIDCScopeConstants.ALL_STANDARD_SCOPES);
341                             choices.add(OIDCScopeConstants.SYNCOPE);
342                             return choices.iterator();
343                         }
344                     };
345                     fields.add(new MultiFieldPanel.Builder<String>(
346                             new PropertyModel<>(clientAppTO, "scopes")).build(
347                             "field",
348                             "scopes",
349                             scopes));
350 
351                     AjaxTextFieldPanel logoutUri = new AjaxTextFieldPanel(
352                             "field", "logoutUri", new PropertyModel<>(clientAppTO, "logoutUri"), false);
353                     logoutUri.addValidator(new UrlValidator());
354                     fields.add(logoutUri);
355 
356                     BinaryFieldPanel jwks = new BinaryFieldPanel(
357                             "field",
358                             "jwks",
359                             new Model<>() {
360 
361                         private static final long serialVersionUID = 7666049400663637482L;
362 
363                         @Override
364                         public String getObject() {
365                             OIDCRPClientAppTO oidcRPCA = (OIDCRPClientAppTO) clientAppTO;
366                             return StringUtils.isBlank(oidcRPCA.getJwks())
367                                     ? null
368                                     : Base64.getEncoder().encodeToString(
369                                             oidcRPCA.getJwks().getBytes(StandardCharsets.UTF_8));
370                         }
371 
372                         @Override
373                         public void setObject(final String object) {
374                             OIDCRPClientAppTO oidcRPCA = (OIDCRPClientAppTO) clientAppTO;
375                             if (StringUtils.isBlank(object)) {
376                                 oidcRPCA.setJwks(null);
377                             } else {
378                                 oidcRPCA.setJwks(
379                                         new String(Base64.getDecoder().decode(object), StandardCharsets.UTF_8));
380                             }
381                         }
382                     },
383                             MediaType.APPLICATION_JSON,
384                             "client-jwks");
385                     fields.add(jwks);
386 
387                     AjaxTextFieldPanel jwksUri = new AjaxTextFieldPanel(
388                             "field", "jwksUri", new PropertyModel<>(clientAppTO, "jwksUri"), false);
389                     jwksUri.addValidator(new UrlValidator());
390                     fields.add(jwksUri);
391 
392                     AjaxDropDownChoicePanel<OIDCClientAuthenticationMethod> tokenEndpointAuthenticationMethod =
393                             new AjaxDropDownChoicePanel<>(
394                                     "field",
395                                     "tokenEndpointAuthenticationMethod",
396                                     new PropertyModel<>(clientAppTO, "tokenEndpointAuthenticationMethod"),
397                                     false);
398                     tokenEndpointAuthenticationMethod.setChoices(List.of(OIDCClientAuthenticationMethod.values()));
399                     fields.add(tokenEndpointAuthenticationMethod);
400                     break;
401 
402                 case SAML2SP:
403                     AjaxTextFieldPanel entityId = new AjaxTextFieldPanel(
404                             "field", "entityId", new PropertyModel<>(clientAppTO, "entityId"), false);
405                     fields.add(entityId.setRequired(true));
406 
407                     fields.add(new AjaxTextFieldPanel("field", "metadataLocation",
408                             new PropertyModel<>(clientAppTO, "metadataLocation"), false).setRequired(true));
409 
410                     fields.add(new AjaxTextFieldPanel(
411                             "field", "metadataSignatureLocation",
412                             new PropertyModel<>(clientAppTO, "metadataSignatureLocation"), false));
413 
414                     fields.add(new AjaxCheckBoxPanel(
415                             "field", "signAssertions", new PropertyModel<>(clientAppTO, "signAssertions")));
416 
417                     fields.add(new AjaxCheckBoxPanel(
418                             "field", "signResponses", new PropertyModel<>(clientAppTO, "signResponses")));
419 
420                     fields.add(new AjaxCheckBoxPanel(
421                             "field", "encryptionOptional", new PropertyModel<>(clientAppTO, "encryptionOptional")));
422 
423                     fields.add(new AjaxCheckBoxPanel(
424                             "field", "encryptAssertions", new PropertyModel<>(clientAppTO, "encryptAssertions")));
425 
426                     fields.add(new AjaxTextFieldPanel(
427                             "field", "requiredAuthenticationContextClass",
428                             new PropertyModel<>(clientAppTO, "requiredAuthenticationContextClass"), false));
429 
430                     AjaxDropDownChoicePanel<SAML2SPNameId> requiredNameIdFormat = new AjaxDropDownChoicePanel<>(
431                             "field", "requiredNameIdFormat", new PropertyModel<>(clientAppTO, "requiredNameIdFormat"),
432                             false);
433                     requiredNameIdFormat.setChoices(List.of(SAML2SPNameId.values()));
434                     requiredNameIdFormat.addRequiredLabel().setEnabled(true);
435                     fields.add(requiredNameIdFormat);
436 
437                     fields.add(new AjaxSpinnerFieldPanel.Builder<Integer>().min(0).build(
438                             "field", "skewAllowance", Integer.class,
439                             new PropertyModel<>(clientAppTO, "skewAllowance")));
440 
441                     fields.add(new AjaxTextFieldPanel(
442                             "field", "nameIdQualifier", new PropertyModel<>(clientAppTO, "nameIdQualifier"), false));
443 
444                     AjaxTextFieldPanel assertionAudience = new AjaxTextFieldPanel(
445                             "panel", "assertionAudience", new Model<>());
446                     assertionAudience.addValidator(new UrlValidator());
447                     fields.add(new MultiFieldPanel.Builder<String>(
448                             new PropertyModel<>(clientAppTO, "assertionAudiences")).build(
449                             "field",
450                             "assertionAudiences",
451                             assertionAudience));
452 
453                     fields.add(new AjaxTextFieldPanel(
454                             "field", "serviceProviderNameIdQualifier",
455                             new PropertyModel<>(clientAppTO, "serviceProviderNameIdQualifier"), false));
456 
457                     fields.add(new AjaxPalettePanel.Builder<XmlSecAlgorithm>().
458                             setName("signingSignatureAlgorithms").build(
459                             "field",
460                             new PropertyModel<>(clientAppTO, "signingSignatureAlgorithms"),
461                             new ListModel<>(List.of(XmlSecAlgorithm.values()))));
462 
463                     fields.add(new AjaxPalettePanel.Builder<XmlSecAlgorithm>().
464                             setName("signingSignatureReferenceDigestMethods").build(
465                             "field",
466                             new PropertyModel<>(clientAppTO, "signingSignatureReferenceDigestMethods"),
467                             new ListModel<>(List.of(XmlSecAlgorithm.values()))));
468 
469                     fields.add(new AjaxPalettePanel.Builder<XmlSecAlgorithm>().
470                             setName("encryptionDataAlgorithms").build(
471                             "field",
472                             new PropertyModel<>(clientAppTO, "encryptionDataAlgorithms"),
473                             new ListModel<>(List.of(XmlSecAlgorithm.values()))));
474 
475                     fields.add(new AjaxPalettePanel.Builder<XmlSecAlgorithm>().
476                             setName("encryptionKeyAlgorithms").build(
477                             "field",
478                             new PropertyModel<>(clientAppTO, "encryptionKeyAlgorithms"),
479                             new ListModel<>(List.of(XmlSecAlgorithm.values()))));
480 
481                     fields.add(new AjaxPalettePanel.Builder<XmlSecAlgorithm>().
482                             setName("signingSignatureBlackListedAlgorithms").build(
483                             "field",
484                             new PropertyModel<>(clientAppTO, "signingSignatureBlackListedAlgorithms"),
485                             new ListModel<>(List.of(XmlSecAlgorithm.values()))));
486 
487                     fields.add(new AjaxPalettePanel.Builder<XmlSecAlgorithm>().
488                             setName("encryptionBlackListedAlgorithms").build(
489                             "field",
490                             new PropertyModel<>(clientAppTO, "encryptionBlackListedAlgorithms"),
491                             new ListModel<>(List.of(XmlSecAlgorithm.values()))));
492                     break;
493 
494                 default:
495             }
496 
497             add(new ListView<>("fields", fields) {
498 
499                 private static final long serialVersionUID = -9180479401817023838L;
500 
501                 @Override
502                 protected void populateItem(final ListItem<Component> item) {
503                     item.add(item.getModelObject());
504                 }
505             });
506         }
507 
508         @Override
509         public void onSubmit(final AjaxRequestTarget target) {
510             try {
511                 if (clientAppTO.getKey() == null) {
512                     clientAppRestClient.create(type, clientAppTO);
513                 } else {
514                     clientAppRestClient.update(type, clientAppTO);
515                 }
516                 SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
517                 Profile.this.modal.close(target);
518             } catch (Exception e) {
519                 LOG.error("While creating/updating clientApp", e);
520                 SyncopeConsoleSession.get().onException(e);
521             }
522             ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
523         }
524     }
525 }