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.wizards;
20  
21  import java.io.Serializable;
22  import java.util.ArrayList;
23  import java.util.List;
24  import java.util.concurrent.Callable;
25  import java.util.concurrent.Future;
26  import java.util.stream.Collectors;
27  import org.apache.commons.lang3.StringUtils;
28  import org.apache.commons.lang3.tuple.Pair;
29  import org.apache.syncope.client.console.SyncopeConsoleSession;
30  import org.apache.syncope.client.console.SyncopeWebApplication;
31  import org.apache.syncope.client.console.panels.SAML2IdPsDirectoryPanel;
32  import org.apache.syncope.client.console.rest.ImplementationRestClient;
33  import org.apache.syncope.client.console.rest.SAML2IdPsRestClient;
34  import org.apache.syncope.client.console.wizards.mapping.ItemTransformersTogglePanel;
35  import org.apache.syncope.client.console.wizards.mapping.JEXLTransformersTogglePanel;
36  import org.apache.syncope.client.console.wizards.mapping.SAML2IdPMappingPanel;
37  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
38  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
39  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
40  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
41  import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
42  import org.apache.syncope.client.ui.commons.wizards.AjaxWizardBuilder;
43  import org.apache.syncope.common.lib.to.ImplementationTO;
44  import org.apache.syncope.common.lib.to.Item;
45  import org.apache.syncope.common.lib.to.SAML2SP4UIIdPTO;
46  import org.apache.syncope.common.lib.types.SAML2BindingType;
47  import org.apache.syncope.common.lib.types.SAML2SP4UIImplementationType;
48  import org.apache.wicket.Component;
49  import org.apache.wicket.PageReference;
50  import org.apache.wicket.extensions.wizard.WizardModel;
51  import org.apache.wicket.extensions.wizard.WizardStep;
52  import org.apache.wicket.markup.html.list.ListItem;
53  import org.apache.wicket.markup.html.list.ListView;
54  import org.apache.wicket.model.IModel;
55  import org.apache.wicket.model.LoadableDetachableModel;
56  import org.apache.wicket.model.Model;
57  import org.apache.wicket.model.PropertyModel;
58  import org.apache.wicket.model.StringResourceModel;
59  import org.apache.wicket.model.util.ListModel;
60  
61  public class SAML2IdPWizardBuilder extends AjaxWizardBuilder<SAML2SP4UIIdPTO> {
62  
63      private static final long serialVersionUID = 5952696913893950460L;
64  
65      protected final SAML2IdPsDirectoryPanel directoryPanel;
66  
67      protected final ImplementationRestClient implementationRestClient;
68  
69      protected final SAML2IdPsRestClient saml2IdPsRestClient;
70  
71      protected final IModel<List<String>> idpActions = new LoadableDetachableModel<>() {
72  
73          private static final long serialVersionUID = 5275935387613157437L;
74  
75          @Override
76          protected List<String> load() {
77              return implementationRestClient.list(SAML2SP4UIImplementationType.IDP_ACTIONS).stream().
78                      map(ImplementationTO::getKey).sorted().collect(Collectors.toList());
79          }
80      };
81  
82      protected final IModel<List<String>> requestedAuthnContextProviders = new LoadableDetachableModel<>() {
83  
84          private static final long serialVersionUID = 4659376149825914247L;
85  
86          @Override
87          protected List<String> load() {
88              return implementationRestClient.list(SAML2SP4UIImplementationType.REQUESTED_AUTHN_CONTEXT_PROVIDER).
89                      stream().map(ImplementationTO::getKey).sorted().collect(Collectors.toList());
90          }
91      };
92  
93      public SAML2IdPWizardBuilder(
94              final SAML2IdPsDirectoryPanel directoryPanel,
95              final SAML2SP4UIIdPTO idpTO,
96              final ImplementationRestClient implementationRestClient,
97              final SAML2IdPsRestClient saml2IdPsRestClient,
98              final PageReference pageRef) {
99  
100         super(idpTO, pageRef);
101 
102         this.directoryPanel = directoryPanel;
103         this.implementationRestClient = implementationRestClient;
104         this.saml2IdPsRestClient = saml2IdPsRestClient;
105     }
106 
107     @Override
108     protected WizardModel buildModelSteps(final SAML2SP4UIIdPTO modelObject, final WizardModel wizardModel) {
109         wizardModel.add(new IdP(modelObject));
110 
111         Mapping mapping = new Mapping();
112         mapping.setOutputMarkupId(true);
113 
114         ItemTransformersTogglePanel mapItemTransformers = new ItemTransformersTogglePanel(mapping, pageRef);
115         addOuterObject(mapItemTransformers);
116         JEXLTransformersTogglePanel jexlTransformers = new JEXLTransformersTogglePanel(mapping, pageRef);
117         addOuterObject(jexlTransformers);
118         mapping.add(new SAML2IdPMappingPanel("mapping", modelObject, mapItemTransformers, jexlTransformers));
119 
120         wizardModel.add(mapping);
121 
122         return wizardModel;
123     }
124 
125     @Override
126     protected long getMaxWaitTimeInSeconds() {
127         return SyncopeWebApplication.get().getMaxWaitTimeInSeconds();
128     }
129 
130     @Override
131     protected void sendError(final Exception exception) {
132         SyncopeConsoleSession.get().onException(exception);
133     }
134 
135     @Override
136     protected void sendWarning(final String message) {
137         SyncopeConsoleSession.get().warn(message);
138     }
139 
140     @Override
141     protected Future<Pair<Serializable, Serializable>> execute(
142             final Callable<Pair<Serializable, Serializable>> future) {
143 
144         return SyncopeConsoleSession.get().execute(future);
145     }
146 
147     private final class IdP extends WizardStep {
148 
149         private static final long serialVersionUID = 854012593185195024L;
150 
151         IdP(final SAML2SP4UIIdPTO idpTO) {
152             super(StringUtils.EMPTY, StringUtils.EMPTY);
153 
154             List<Component> fields = new ArrayList<>();
155 
156             FieldPanel<String> name = new AjaxTextFieldPanel(
157                     "field", "name", new PropertyModel<>(idpTO, "name"), false);
158             name.setRequired(true);
159             fields.add(name);
160 
161             AjaxCheckBoxPanel createUnmatching = new AjaxCheckBoxPanel(
162                     "field", "createUnmatching", new PropertyModel<>(idpTO, "createUnmatching"), false);
163             fields.add(createUnmatching);
164 
165             AjaxCheckBoxPanel selfRegUnmatching = new AjaxCheckBoxPanel(
166                     "field", "selfRegUnmatching", new PropertyModel<>(idpTO, "selfRegUnmatching"), false);
167             fields.add(selfRegUnmatching);
168 
169             AjaxCheckBoxPanel updateMatching = new AjaxCheckBoxPanel(
170                     "field", "updateMatching", new PropertyModel<>(idpTO, "updateMatching"), false);
171             fields.add(updateMatching);
172 
173             AjaxDropDownChoicePanel<SAML2BindingType> bindingType =
174                     new AjaxDropDownChoicePanel<>("field", "bindingType",
175                             new PropertyModel<>(idpTO, "bindingType"), false);
176             bindingType.setChoices(List.of(SAML2BindingType.values()));
177             fields.add(bindingType);
178 
179             AjaxTextFieldPanel requestedAuthnContextProvider = new AjaxTextFieldPanel(
180                     "field", "requestedAuthnContextProvider",
181                     new PropertyModel<>(idpTO, "requestedAuthnContextProvider"));
182             requestedAuthnContextProvider.setChoices(
183                     requestedAuthnContextProviders.getObject());
184             fields.add(requestedAuthnContextProvider);
185 
186             AjaxPalettePanel<String> actions = new AjaxPalettePanel.Builder<String>().
187                     setAllowMoveAll(true).setAllowOrder(true).
188                     setName(new StringResourceModel("actions", directoryPanel).getString()).
189                     build("field",
190                             new PropertyModel<>(idpTO, "actions"),
191                             new ListModel<>(idpActions.getObject()));
192             actions.setOutputMarkupId(true);
193             fields.add(actions);
194 
195             add(new ListView<>("fields", fields) {
196 
197                 private static final long serialVersionUID = -9180479401817023838L;
198 
199                 @Override
200                 protected void populateItem(final ListItem<Component> item) {
201                     item.add(item.getModelObject());
202                 }
203             });
204         }
205     }
206 
207     /**
208      * Mapping definition step.
209      */
210     private static final class Mapping extends WizardStep {
211 
212         private static final long serialVersionUID = 3454904947720856253L;
213 
214         Mapping() {
215             setTitleModel(Model.of("Mapping"));
216             setSummaryModel(Model.of(StringUtils.EMPTY));
217         }
218     }
219 
220     @Override
221     protected Serializable onApplyInternal(final SAML2SP4UIIdPTO modelObject) {
222         long connObjectKeyCount = modelObject.getItems().stream().filter(Item::isConnObjectKey).count();
223         if (connObjectKeyCount != 1) {
224             throw new IllegalArgumentException(
225                     new StringResourceModel("connObjectKeyValidation", directoryPanel).getString());
226         }
227 
228         saml2IdPsRestClient.update(modelObject);
229         return modelObject;
230     }
231 }