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.List;
23  import java.util.stream.Collectors;
24  import org.apache.commons.lang3.StringUtils;
25  import org.apache.syncope.client.console.SyncopeWebApplication;
26  import org.apache.syncope.client.console.panels.BeanPanel;
27  import org.apache.syncope.client.console.rest.AuthModuleRestClient;
28  import org.apache.syncope.client.console.wizards.mapping.AuthModuleMappingPanel;
29  import org.apache.syncope.client.ui.commons.Constants;
30  import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
31  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
32  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
33  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
34  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
35  import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
36  import org.apache.syncope.common.lib.AbstractLDAPConf;
37  import org.apache.syncope.common.lib.auth.AuthModuleConf;
38  import org.apache.syncope.common.lib.auth.LDAPDependantAuthModuleConf;
39  import org.apache.syncope.common.lib.to.AuthModuleTO;
40  import org.apache.syncope.common.lib.types.AuthModuleState;
41  import org.apache.wicket.PageReference;
42  import org.apache.wicket.ajax.AjaxEventBehavior;
43  import org.apache.wicket.ajax.AjaxRequestTarget;
44  import org.apache.wicket.extensions.wizard.WizardModel;
45  import org.apache.wicket.extensions.wizard.WizardStep;
46  import org.apache.wicket.model.IModel;
47  import org.apache.wicket.model.LoadableDetachableModel;
48  import org.apache.wicket.model.Model;
49  import org.apache.wicket.model.PropertyModel;
50  import org.springframework.util.ClassUtils;
51  
52  public class AuthModuleWizardBuilder extends BaseAjaxWizardBuilder<AuthModuleTO> {
53  
54      private static final long serialVersionUID = -6163230263062920394L;
55  
56      protected final LoadableDetachableModel<List<String>> authModuleConfs = new LoadableDetachableModel<>() {
57  
58          private static final long serialVersionUID = 5275935387613157437L;
59  
60          @Override
61          protected List<String> load() {
62              return SyncopeWebApplication.get().getLookup().getClasses(AuthModuleConf.class).stream().
63                      map(Class::getName).sorted().collect(Collectors.toList());
64          }
65      };
66  
67      protected final AuthModuleRestClient authModuleRestClient;
68  
69      protected final Model<Class<? extends AuthModuleConf>> authModuleConfClass = Model.of();
70  
71      public AuthModuleWizardBuilder(
72              final AuthModuleTO defaultItem,
73              final AuthModuleRestClient authModuleRestClient,
74              final PageReference pageRef) {
75  
76          super(defaultItem, pageRef);
77          this.authModuleRestClient = authModuleRestClient;
78      }
79  
80      @Override
81      protected Serializable onApplyInternal(final AuthModuleTO modelObject) {
82          if (mode == AjaxWizard.Mode.CREATE) {
83              authModuleRestClient.create(modelObject);
84          } else {
85              authModuleRestClient.update(modelObject);
86          }
87          return modelObject;
88      }
89  
90      @Override
91      protected WizardModel buildModelSteps(final AuthModuleTO modelObject, final WizardModel wizardModel) {
92          wizardModel.add(new Profile(modelObject, authModuleConfs, authModuleConfClass));
93          wizardModel.add(new Configuration(modelObject));
94          wizardModel.add(new AuthModuleConfLDAP(modelObject, authModuleConfClass));
95          wizardModel.add(new Mapping(modelObject));
96          return wizardModel;
97      }
98  
99      protected static class Profile extends WizardStep {
100 
101         private static final long serialVersionUID = -3043839139187792810L;
102 
103         Profile(
104                 final AuthModuleTO authModule,
105                 final LoadableDetachableModel<List<String>> authModuleConfs,
106                 final Model<Class<? extends AuthModuleConf>> authModuleConfClass) {
107 
108             boolean isNew = authModule.getConf() == null;
109             if (!isNew) {
110                 authModuleConfClass.setObject(authModule.getConf().getClass());
111             }
112 
113             AjaxTextFieldPanel key = new AjaxTextFieldPanel(
114                     Constants.KEY_FIELD_NAME, Constants.KEY_FIELD_NAME,
115                     new PropertyModel<>(authModule, Constants.KEY_FIELD_NAME));
116             key.addRequiredLabel();
117             key.setEnabled(isNew);
118             add(key);
119 
120             AjaxTextFieldPanel description = new AjaxTextFieldPanel(
121                     Constants.DESCRIPTION_FIELD_NAME, getString(Constants.DESCRIPTION_FIELD_NAME),
122                     new PropertyModel<>(authModule, Constants.DESCRIPTION_FIELD_NAME));
123             add(description);
124 
125             AjaxDropDownChoicePanel<AuthModuleState> state = new AjaxDropDownChoicePanel<>(
126                     "state", getString("state"), new PropertyModel<>(authModule, "state"));
127             state.setChoices(List.of(AuthModuleState.values()));
128             state.addRequiredLabel();
129             state.setNullValid(false);
130             add(state);
131 
132             add(new AjaxSpinnerFieldPanel.Builder<Integer>().build(
133                     "order",
134                     "order",
135                     Integer.class,
136                     new PropertyModel<>(authModule, "order")).addRequiredLabel());
137 
138             AjaxDropDownChoicePanel<String> conf = new AjaxDropDownChoicePanel<>("conf", getString("type"), isNew
139                     ? Model.of()
140                     : Model.of(authModule.getConf().getClass().getName()));
141             conf.setChoices(authModuleConfs.getObject());
142             conf.addRequiredLabel();
143             conf.setNullValid(false);
144             conf.setEnabled(isNew);
145             conf.add(new AjaxEventBehavior(Constants.ON_CHANGE) {
146 
147                 private static final long serialVersionUID = -7133385027739964990L;
148 
149                 @SuppressWarnings("unchecked")
150                 @Override
151                 protected void onEvent(final AjaxRequestTarget target) {
152                     try {
153                         Class<? extends AuthModuleConf> clazz =
154                                 (Class<? extends AuthModuleConf>) ClassUtils.resolveClassName(
155                                         conf.getModelObject(), ClassUtils.getDefaultClassLoader());
156 
157                         authModule.setConf(clazz.getConstructor().newInstance());
158                         authModuleConfClass.setObject(clazz);
159                     } catch (Exception e) {
160                         LOG.error("Cannot instantiate {}", conf.getModelObject(), e);
161                     }
162                 }
163             });
164             add(conf);
165         }
166     }
167 
168     protected class Configuration extends WizardStep {
169 
170         private static final long serialVersionUID = -785981096328637758L;
171 
172         Configuration(final AuthModuleTO authModule) {
173             add(new BeanPanel<>("bean", new PropertyModel<>(authModule, "conf"), pageRef, "ldap").
174                     setRenderBodyOnly(true));
175         }
176     }
177 
178     protected class AuthModuleConfLDAP extends WizardStep implements WizardModel.ICondition {
179 
180         private static final long serialVersionUID = 5328049907748683944L;
181 
182         private final Model<Class<? extends AuthModuleConf>> authModuleConfClass;
183 
184         AuthModuleConfLDAP(
185                 final AuthModuleTO authModule,
186                 final Model<Class<? extends AuthModuleConf>> authModuleConfClass) {
187 
188             this.authModuleConfClass = authModuleConfClass;
189 
190             PropertyModel<AbstractLDAPConf> beanPanelModel = new PropertyModel<>(authModule, "conf.ldap");
191 
192             AjaxCheckBoxPanel enable = new AjaxCheckBoxPanel("enable", "enableLDAP", new IModel<Boolean>() {
193 
194                 private static final long serialVersionUID = -7126718045816207110L;
195 
196                 @Override
197                 public Boolean getObject() {
198                     return beanPanelModel.getObject() != null;
199                 }
200 
201                 @Override
202                 public void setObject(final Boolean object) {
203                     // nothing to do
204                 }
205             });
206             enable.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
207 
208                 private static final long serialVersionUID = -1107858522700306810L;
209 
210                 @Override
211                 protected void onUpdate(final AjaxRequestTarget target) {
212                     if (beanPanelModel.getObject() == null) {
213                         try {
214                             beanPanelModel.setObject((AbstractLDAPConf) authModuleConfClass.getObject().
215                                     getMethod("ldapInstance", new Class<?>[] {}).invoke(authModule.getConf()));
216                         } catch (Exception e) {
217                             LOG.warn("Error instantiating beanPanel model object", e);
218                         }
219                     } else {
220                         beanPanelModel.setObject(null);
221                     }
222                     target.add(AuthModuleConfLDAP.this);
223                 }
224             });
225             add(enable);
226 
227             add(new BeanPanel<>("bean", beanPanelModel, pageRef).setRenderBodyOnly(true));
228             setOutputMarkupId(true);
229         }
230 
231         @Override
232         public boolean evaluate() {
233             return LDAPDependantAuthModuleConf.class.isAssignableFrom(authModuleConfClass.getObject());
234         }
235     }
236 
237     protected static final class Mapping extends WizardStep {
238 
239         private static final long serialVersionUID = 3454904947720856253L;
240 
241         Mapping(final AuthModuleTO authModule) {
242             setTitleModel(Model.of("Mapping"));
243             setSummaryModel(Model.of(StringUtils.EMPTY));
244             add(new AuthModuleMappingPanel("mapping", authModule));
245         }
246     }
247 }