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.panels;
20  
21  import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.password.strength.PasswordStrengthBehavior;
22  import org.apache.syncope.client.enduser.SyncopeWebApplication;
23  import org.apache.syncope.client.enduser.commons.EnduserConstants;
24  import org.apache.syncope.client.enduser.panels.captcha.CaptchaPanel;
25  import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
26  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel;
27  import org.apache.syncope.client.ui.commons.markup.html.form.SyncopePasswordStrengthConfig;
28  import org.apache.syncope.client.ui.commons.panels.CardPanel;
29  import org.apache.syncope.client.ui.commons.panels.NotificationPanel;
30  import org.apache.syncope.common.lib.to.UserTO;
31  import org.apache.wicket.AttributeModifier;
32  import org.apache.wicket.Component;
33  import org.apache.wicket.ajax.AjaxRequestTarget;
34  import org.apache.wicket.ajax.markup.html.form.AjaxButton;
35  import org.apache.wicket.core.util.string.CssUtils;
36  import org.apache.wicket.markup.html.basic.Label;
37  import org.apache.wicket.markup.html.form.Button;
38  import org.apache.wicket.markup.html.form.Form;
39  import org.apache.wicket.markup.html.form.PasswordTextField;
40  import org.apache.wicket.markup.html.form.StatelessForm;
41  import org.apache.wicket.markup.html.form.validation.EqualPasswordInputValidator;
42  import org.apache.wicket.markup.html.panel.Panel;
43  import org.apache.wicket.model.Model;
44  import org.apache.wicket.util.string.AppendingStringBuffer;
45  import org.slf4j.Logger;
46  import org.slf4j.LoggerFactory;
47  
48  public abstract class ChangePasswordPanel extends Panel {
49  
50      protected static final Logger LOG = LoggerFactory.getLogger(ChangePasswordPanel.class);
51  
52      private static final long serialVersionUID = -8937593602426944714L;
53  
54      protected static final String FORM_SUFFIX = "form_";
55  
56      protected StatelessForm<Void> form;
57  
58      protected AjaxPasswordFieldPanel passwordField;
59  
60      protected AjaxPasswordFieldPanel confirmPasswordField;
61  
62      protected CaptchaPanel<Void> captcha;
63  
64      public ChangePasswordPanel(final String id, final NotificationPanel notificationPanel) {
65          super(id);
66          form = new StatelessForm<>("changePassword") {
67  
68              private static final long serialVersionUID = 418292023846536149L;
69  
70              @Override
71              protected void appendDefaultButtonField() {
72                  AppendingStringBuffer buffer = new AppendingStringBuffer();
73  
74                  String cssClass = getString(CssUtils.key(Form.class, "hidden-fields"));
75  
76                  // div that is not visible (but not display:none either)
77                  buffer.append(String.format(
78                          "<div style=\"width:0px;height:0px;position:absolute;"
79                          + "left:-100px;top:-100px;overflow:hidden\" class=\"%s\">",
80                          cssClass));
81  
82                  // add an empty textfield (otherwise IE doesn't work)
83                  buffer.append("<input title=\"text_hidden\" "
84                          + "aria-label=\"text_hidden\" type=\"text\" "
85                          + "tabindex=\"-1\" autocomplete=\"off\"/>");
86  
87                  // add the submitting component
88                  final Component submittingComponent = (Component) getDefaultButton();
89                  buffer.append("<input title=\"submit_hidden\" aria-label=\"submit_hidden\" "
90                          + "type=\"submit\" tabindex=\"-1\" name=\"");
91                  buffer.append(getDefaultButton().getInputName());
92                  buffer.append("\" onclick=\" var b=document.getElementById('");
93                  buffer.append(submittingComponent.getMarkupId());
94                  buffer.append(
95                          "'); if (b!=null&amp;&amp;b.onclick!=null&amp;&amp;typeof(b.onclick) != 'undefined') "
96                          + "{  var r = Wicket.bind(b.onclick, b)(); if (r != false) b.click(); } "
97                          + "else { b.click(); };  return false;\" ");
98                  buffer.append(" />");
99  
100                 // close div
101                 buffer.append("</div>");
102 
103                 getResponse().write(buffer);
104             }
105         };
106         form.setOutputMarkupId(true);
107         add(form);
108 
109         passwordField = new AjaxPasswordFieldPanel(
110                 "password",
111                 getString("password"),
112                 Model.of(),
113                 false,
114                 new PasswordStrengthBehavior(new SyncopePasswordStrengthConfig()));
115         passwordField.setRequired(true);
116         passwordField.setMarkupId("password");
117         passwordField.setPlaceholder("password");
118 
119         Label passwordLabel = (Label) passwordField.get(AbstractFieldPanel.LABEL);
120         passwordLabel.add(new AttributeModifier("for", FORM_SUFFIX + "password"));
121 
122         ((PasswordTextField) passwordField.getField()).setResetPassword(true);
123         form.add(passwordField);
124 
125         confirmPasswordField = new AjaxPasswordFieldPanel(
126                 "confirmPassword", getString("confirmPassword"), Model.of(), true);
127         confirmPasswordField.setRequired(true);
128         confirmPasswordField.setMarkupId("confirmPassword");
129         confirmPasswordField.setPlaceholder("confirmPassword");
130 
131         Label confirmPasswordLabel = (Label) confirmPasswordField.get(AbstractFieldPanel.LABEL);
132         confirmPasswordLabel.add(new AttributeModifier("for", FORM_SUFFIX + "confirmPassword"));
133 
134         ((PasswordTextField) confirmPasswordField.getField()).setResetPassword(true);
135         form.add(confirmPasswordField);
136 
137         form.add(new EqualPasswordInputValidator(passwordField.getField(), confirmPasswordField.getField()));
138 
139         captcha = new CaptchaPanel<>(EnduserConstants.CONTENT_PANEL);
140         captcha.setOutputMarkupPlaceholderTag(true);
141 
142         form.add(new CardPanel.Builder<CaptchaPanel<Void>>()
143                 .setName("captcha")
144                 .setComponent(captcha)
145                 .isVisible(SyncopeWebApplication.get().isCaptchaEnabled()).build("captchaPanelCard"));
146 
147         AjaxButton submitButton = new AjaxButton("submit", new Model<>(getString("submit"))) {
148 
149             private static final long serialVersionUID = 429178684321093953L;
150 
151             @Override
152             protected void onSubmit(final AjaxRequestTarget target) {
153                 doSubmit(target, passwordField);
154             }
155 
156             @Override
157             protected void onError(final AjaxRequestTarget target) {
158                 notificationPanel.refresh(target);
159             }
160         };
161         form.add(submitButton);
162         form.setDefaultButton(submitButton);
163 
164         Button cancel = new Button("cancel") {
165 
166             private static final long serialVersionUID = 3669569969172391336L;
167 
168             @Override
169             public void onSubmit() {
170                 doCancel();
171             }
172         };
173         cancel.setOutputMarkupId(true);
174         cancel.setDefaultFormProcessing(false);
175         form.add(cancel);
176     }
177 
178     public StatelessForm<Void> getForm() {
179         return form;
180     }
181 
182     public AjaxPasswordFieldPanel getPasswordField() {
183         return passwordField;
184     }
185 
186     public AjaxPasswordFieldPanel getConfirmPasswordField() {
187         return confirmPasswordField;
188     }
189 
190     protected abstract void doSubmit(AjaxRequestTarget target, AjaxPasswordFieldPanel passwordField);
191 
192     protected abstract void doCancel();
193 
194     protected abstract UserTO getLoggedUser();
195 }