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.policies;
20  
21  import com.fasterxml.jackson.databind.json.JsonMapper;
22  import java.io.Serializable;
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.stream.Collectors;
26  import org.apache.syncope.client.console.panels.BeanPanel;
27  import org.apache.syncope.client.console.rest.ImplementationRestClient;
28  import org.apache.syncope.client.console.rest.PolicyRestClient;
29  import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
30  import org.apache.syncope.client.ui.commons.Constants;
31  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
32  import org.apache.syncope.common.lib.policy.ComposablePolicy;
33  import org.apache.syncope.common.lib.policy.PolicyTO;
34  import org.apache.syncope.common.lib.policy.RuleConf;
35  import org.apache.syncope.common.lib.to.ImplementationTO;
36  import org.apache.syncope.common.lib.types.IdRepoImplementationType;
37  import org.apache.syncope.common.lib.types.ImplementationEngine;
38  import org.apache.syncope.common.lib.types.PolicyType;
39  import org.apache.wicket.PageReference;
40  import org.apache.wicket.WicketRuntimeException;
41  import org.apache.wicket.ajax.AjaxEventBehavior;
42  import org.apache.wicket.ajax.AjaxRequestTarget;
43  import org.apache.wicket.extensions.wizard.WizardModel;
44  import org.apache.wicket.extensions.wizard.WizardStep;
45  import org.apache.wicket.model.LoadableDetachableModel;
46  import org.apache.wicket.model.PropertyModel;
47  
48  public class PolicyRuleWizardBuilder extends BaseAjaxWizardBuilder<PolicyRuleWrapper> {
49  
50      private static final long serialVersionUID = 5945391813567245081L;
51  
52      protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
53  
54      protected final String policy;
55  
56      protected final PolicyType type;
57  
58      protected final String implementationType;
59  
60      protected final PolicyRestClient policyRestClient;
61  
62      protected final ImplementationRestClient implementationRestClient;
63  
64      public PolicyRuleWizardBuilder(
65              final String policy,
66              final PolicyType type,
67              final PolicyRuleWrapper policyWrapper,
68              final PolicyRestClient policyRestClient,
69              final ImplementationRestClient implementationRestClient,
70              final PageReference pageRef) {
71  
72          super(policyWrapper, pageRef);
73  
74          this.policy = policy;
75          this.type = type;
76          this.implementationType = type == PolicyType.ACCOUNT
77                  ? IdRepoImplementationType.ACCOUNT_RULE
78                  : IdRepoImplementationType.PASSWORD_RULE;
79          this.policyRestClient = policyRestClient;
80          this.implementationRestClient = implementationRestClient;
81      }
82  
83      @Override
84      protected Serializable onApplyInternal(final PolicyRuleWrapper modelObject) {
85          PolicyTO policyTO = policyRestClient.read(type, policy);
86  
87          ComposablePolicy composable;
88          if (policyTO instanceof ComposablePolicy) {
89              composable = (ComposablePolicy) policyTO;
90          } else {
91              throw new IllegalStateException("Non composable policy");
92          }
93  
94          if (modelObject.getImplementationEngine() == ImplementationEngine.JAVA) {
95              ImplementationTO rule = implementationRestClient.
96                      read(implementationType, modelObject.getImplementationKey());
97              try {
98                  rule.setBody(MAPPER.writeValueAsString(modelObject.getConf()));
99                  implementationRestClient.update(rule);
100             } catch (Exception e) {
101                 throw new WicketRuntimeException(e);
102             }
103         }
104 
105         if (modelObject.isNew()) {
106             composable.getRules().add(modelObject.getImplementationKey());
107         }
108 
109         policyRestClient.update(type, policyTO);
110         return modelObject;
111     }
112 
113     @Override
114     protected WizardModel buildModelSteps(final PolicyRuleWrapper modelObject, final WizardModel wizardModel) {
115         wizardModel.add(new Profile(modelObject));
116         wizardModel.add(new Configuration(modelObject));
117         return wizardModel;
118     }
119 
120     public class Profile extends WizardStep {
121 
122         private static final long serialVersionUID = -3043839139187792810L;
123 
124         private final PolicyRuleWrapper rule;
125 
126         public Profile(final PolicyRuleWrapper rule) {
127             this.rule = rule;
128 
129             AjaxDropDownChoicePanel<String> conf = new AjaxDropDownChoicePanel<>(
130                     "rule", "rule", new PropertyModel<>(rule, "implementationKey"));
131 
132             List<String> choices;
133             switch (type) {
134                 case ACCOUNT:
135                     choices = implementationRestClient.list(IdRepoImplementationType.ACCOUNT_RULE).stream().
136                             map(ImplementationTO::getKey).sorted().collect(Collectors.toList());
137                     break;
138 
139                 case PASSWORD:
140                     choices = implementationRestClient.list(IdRepoImplementationType.PASSWORD_RULE).stream().
141                             map(ImplementationTO::getKey).sorted().collect(Collectors.toList());
142                     break;
143 
144                 default:
145                     choices = new ArrayList<>();
146             }
147 
148             conf.setChoices(choices);
149             conf.addRequiredLabel();
150             conf.setNullValid(false);
151             conf.setEnabled(rule.isNew());
152             conf.add(new AjaxEventBehavior(Constants.ON_CHANGE) {
153 
154                 private static final long serialVersionUID = -7133385027739964990L;
155 
156                 @Override
157                 protected void onEvent(final AjaxRequestTarget target) {
158                     ImplementationTO impl = implementationRestClient.read(implementationType, conf.getModelObject());
159                     rule.setImplementationEngine(impl.getEngine());
160                     if (impl.getEngine() == ImplementationEngine.JAVA) {
161                         try {
162                             rule.setConf(MAPPER.readValue(impl.getBody(), RuleConf.class));
163                         } catch (Exception e) {
164                             LOG.error("During deserialization", e);
165                         }
166                     }
167                 }
168             });
169             add(conf);
170         }
171 
172         @Override
173         public void applyState() {
174             if (rule.getImplementationEngine() == ImplementationEngine.GROOVY) {
175                 getWizardModel().finish();
176             }
177         }
178     }
179 
180     public class Configuration extends WizardStep {
181 
182         private static final long serialVersionUID = -785981096328637758L;
183 
184         public Configuration(final PolicyRuleWrapper rule) {
185             LoadableDetachableModel<Serializable> bean = new LoadableDetachableModel<>() {
186 
187                 private static final long serialVersionUID = 2092144708018739371L;
188 
189                 @Override
190                 protected Serializable load() {
191                     return rule.getConf();
192                 }
193             };
194             add(new BeanPanel<>("bean", bean, pageRef).setRenderBodyOnly(true));
195         }
196     }
197 }