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.enduser.pages;
20  
21  import java.util.List;
22  import java.util.stream.Collectors;
23  import org.apache.commons.lang3.StringUtils;
24  import org.apache.syncope.client.enduser.SyncopeEnduserSession;
25  import org.apache.syncope.client.enduser.SyncopeWebApplication;
26  import org.apache.syncope.client.enduser.commons.EnduserConstants;
27  import org.apache.syncope.client.enduser.commons.ProvisioningUtils;
28  import org.apache.syncope.client.enduser.panels.captcha.CaptchaPanel;
29  import org.apache.syncope.client.enduser.rest.SecurityQuestionRestClient;
30  import org.apache.syncope.client.enduser.rest.UserSelfRestClient;
31  import org.apache.syncope.client.ui.commons.Constants;
32  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
33  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
34  import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
35  import org.apache.syncope.client.ui.commons.panels.CardPanel;
36  import org.apache.syncope.common.lib.request.StringReplacePatchItem;
37  import org.apache.syncope.common.lib.request.UserUR;
38  import org.apache.syncope.common.lib.to.ProvisioningResult;
39  import org.apache.syncope.common.lib.to.SecurityQuestionTO;
40  import org.apache.syncope.common.lib.to.UserTO;
41  import org.apache.syncope.common.lib.types.ExecStatus;
42  import org.apache.wicket.ajax.AjaxEventBehavior;
43  import org.apache.wicket.ajax.AjaxRequestTarget;
44  import org.apache.wicket.ajax.markup.html.form.AjaxButton;
45  import org.apache.wicket.markup.html.WebMarkupContainer;
46  import org.apache.wicket.markup.html.form.Button;
47  import org.apache.wicket.markup.html.form.IChoiceRenderer;
48  import org.apache.wicket.markup.html.form.StatelessForm;
49  import org.apache.wicket.model.IModel;
50  import org.apache.wicket.model.Model;
51  import org.apache.wicket.model.PropertyModel;
52  import org.apache.wicket.request.mapper.parameter.PageParameters;
53  import org.apache.wicket.spring.injection.annot.SpringBean;
54  
55  public class EditSecurityQuestion extends BasePage {
56  
57      private static final long serialVersionUID = -537205681762708502L;
58  
59      protected static final String EDIT_SECURITY_QUESTION = "page.editSecurityQuestion";
60  
61      @SpringBean
62      protected SecurityQuestionRestClient securityQuestionRestClient;
63  
64      @SpringBean
65      protected UserSelfRestClient userSelfRestClient;
66  
67      protected final AjaxDropDownChoicePanel<String> securityQuestion;
68  
69      protected final FieldPanel<String> securityAnswer;
70  
71      protected final UserTO userTO;
72  
73      public EditSecurityQuestion(final PageParameters parameters) {
74          super(parameters, EDIT_SECURITY_QUESTION);
75  
76          userTO = SyncopeEnduserSession.get().getSelfTO(true);
77  
78          WebMarkupContainer content = new WebMarkupContainer("content");
79          content.setOutputMarkupId(true);
80          contentWrapper.add(content);
81  
82          StatelessForm<Void> form = new StatelessForm<>("securityQuestionForm");
83          form.setOutputMarkupId(true);
84          content.add(form);
85  
86          securityQuestion = new AjaxDropDownChoicePanel<>("securityQuestion",
87                  "securityQuestion", new PropertyModel<>(userTO, "securityQuestion"));
88          securityQuestion.setNullValid(true);
89          securityQuestion.setRequired(true);
90  
91          List<SecurityQuestionTO> securityQuestions = securityQuestionRestClient.list();
92          securityQuestion.setChoices(securityQuestions.stream().
93                  map(SecurityQuestionTO::getKey).collect(Collectors.toList()));
94          securityQuestion.setChoiceRenderer(new IChoiceRenderer<>() {
95  
96              private static final long serialVersionUID = -4421146737845000747L;
97  
98              @Override
99              public Object getDisplayValue(final String value) {
100                 return securityQuestions.stream().filter(sq -> value.equals(sq.getKey())).
101                         map(SecurityQuestionTO::getContent).findFirst().orElse(null);
102             }
103 
104             @Override
105             public String getIdValue(final String value, final int index) {
106                 return value;
107             }
108 
109             @Override
110             public String getObject(final String id, final IModel<? extends List<? extends String>> choices) {
111                 return id;
112             }
113         });
114 
115         securityQuestion.add(new AjaxEventBehavior(Constants.ON_CHANGE) {
116 
117             private static final long serialVersionUID = 192359260308762078L;
118 
119             @Override
120             protected void onEvent(final AjaxRequestTarget target) {
121                 securityAnswer.setEnabled(StringUtils.isNotBlank(securityQuestion.getModelObject()));
122                 target.add(securityAnswer);
123             }
124         });
125 
126         form.add(securityQuestion);
127 
128         securityAnswer = new AjaxTextFieldPanel("securityAnswer", "securityAnswer",
129                 new PropertyModel<>(userTO, "securityAnswer"), false);
130         form.add(securityAnswer.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true).
131                 setEnabled(StringUtils.isNotBlank(securityQuestion.getModelObject())));
132         securityAnswer.setRequired(true);
133 
134         CaptchaPanel<Void> captcha = new CaptchaPanel<>(EnduserConstants.CONTENT_PANEL);
135         captcha.setOutputMarkupPlaceholderTag(true);
136 
137         form.add(new CardPanel.Builder<CaptchaPanel<Void>>()
138                 .setName("captcha")
139                 .setComponent(captcha)
140                 .isVisible(SyncopeWebApplication.get().isCaptchaEnabled()).build("captchaPanelCard"));
141 
142         AjaxButton submitButton = new AjaxButton("submit", new Model<>(getString("submit"))) {
143 
144             private static final long serialVersionUID = 429178684321093953L;
145 
146             @Override
147             protected void onSubmit(final AjaxRequestTarget target) {
148                 if (SyncopeWebApplication.get().isCaptchaEnabled() && !captcha.check()) {
149                     SyncopeEnduserSession.get().error(getString(Constants.CAPTCHA_ERROR));
150                     ((BasePage) getPageReference().getPage()).getNotificationPanel().refresh(target);
151                 } else {
152                     try {
153                         ProvisioningResult<UserTO> provisioningResult =
154                                 userSelfRestClient.update(
155                                         userTO.getETagValue(),
156                                         new UserUR.Builder(userTO.getKey())
157                                                 .securityQuestion(new StringReplacePatchItem.Builder().
158                                                         value(securityQuestion.getModelObject()).build())
159                                                 .securityAnswer(new StringReplacePatchItem.Builder().
160                                                         value(securityAnswer.getModelObject()).build()).build());
161                         setResponsePage(new SelfResult(provisioningResult,
162                                 ProvisioningUtils.managePageParams(EditSecurityQuestion.this,
163                                         "securityquestion.change",
164                                         !SyncopeWebApplication.get().isReportPropagationErrors()
165                                         || provisioningResult.getPropagationStatuses().stream()
166                                                 .allMatch(ps -> ExecStatus.SUCCESS == ps.getStatus()))));
167                     } catch (Exception e) {
168                         LOG.error("While updating security question for {}",
169                                 SyncopeEnduserSession.get().getSelfTO().getUsername(), e);
170                         SyncopeEnduserSession.get().onException(e);
171                         ((BasePage) getPageReference().getPage()).getNotificationPanel().refresh(target);
172                     }
173                 }
174             }
175 
176             @Override
177             protected void onError(final AjaxRequestTarget target) {
178                 notificationPanel.refresh(target);
179             }
180         };
181         form.add(submitButton);
182 
183         form.setDefaultButton(submitButton);
184 
185         Button cancel = new Button("cancel") {
186 
187             private static final long serialVersionUID = 3669569969172391336L;
188 
189             @Override
190             public void onSubmit() {
191                 setResponsePage(getApplication().getHomePage());
192             }
193         };
194 
195         cancel.setOutputMarkupId(true);
196         cancel.setDefaultFormProcessing(false);
197         form.add(cancel);
198     }
199 }