001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ui.login; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsUser; 032import org.opencms.main.CmsException; 033import org.opencms.main.CmsLog; 034import org.opencms.main.CmsRuntimeException; 035import org.opencms.main.OpenCms; 036import org.opencms.security.CmsSecurityException; 037import org.opencms.security.I_CmsPasswordHandler; 038import org.opencms.security.I_CmsPasswordSecurityEvaluator; 039import org.opencms.security.I_CmsPasswordSecurityEvaluator.SecurityLevel; 040import org.opencms.ui.A_CmsUI; 041import org.opencms.ui.CmsVaadinUtils; 042import org.opencms.ui.I_CmsDialogContext; 043import org.opencms.ui.Messages; 044import org.opencms.ui.components.CmsBasicDialog; 045import org.opencms.ui.components.CmsOkCancelActionHandler; 046import org.opencms.ui.components.OpenCmsTheme; 047import org.opencms.util.CmsStringUtil; 048import org.opencms.util.CmsUUID; 049import org.opencms.workplace.CmsWorkplaceLoginHandler; 050 051import java.util.Collections; 052import java.util.Locale; 053 054import org.apache.commons.logging.Log; 055 056import com.vaadin.server.UserError; 057import com.vaadin.ui.Button; 058import com.vaadin.ui.Button.ClickEvent; 059import com.vaadin.ui.Button.ClickListener; 060import com.vaadin.ui.UI; 061import com.vaadin.v7.data.Property.ValueChangeEvent; 062import com.vaadin.v7.data.Property.ValueChangeListener; 063import com.vaadin.v7.event.FieldEvents.TextChangeEvent; 064import com.vaadin.v7.event.FieldEvents.TextChangeListener; 065 066/** 067 * Dialog used to change the password.<p> 068 */ 069public class CmsChangePasswordDialog extends CmsBasicDialog { 070 071 /** Logger instance for this class. */ 072 private static final Log LOG = CmsLog.getLog(CmsChangePasswordDialog.class); 073 074 /** Serial version id. */ 075 private static final long serialVersionUID = 1L; 076 077 /** The password form. */ 078 protected CmsPasswordForm m_form; 079 080 /** The CMS context. */ 081 CmsObject m_cms; 082 083 /** The locale. */ 084 Locale m_locale; 085 086 /** The user. */ 087 CmsUser m_user; 088 089 /** The cancel button. */ 090 private Button m_cancelButton; 091 092 /** The dialog context. */ 093 private I_CmsDialogContext m_context; 094 095 /** The button to change the password. */ 096 private Button m_passwordChangeButton; 097 098 /** 099 * Creates a new instance.<p> 100 * 101 * @param cms the CMS context 102 * @param user the user 103 * @param locale the locale 104 */ 105 public CmsChangePasswordDialog(CmsObject cms, CmsUser user, Locale locale) { 106 107 super(); 108 m_locale = locale; 109 m_cms = cms; 110 m_user = user; 111 if (m_user.isManaged()) { 112 throw new CmsRuntimeException( 113 Messages.get().container(Messages.ERR_USER_NOT_SELF_MANAGED_1, m_user.getName())); 114 } 115 116 m_form = new CmsPasswordForm(m_locale); 117 setContent(m_form); 118 if (OpenCms.getPasswordHandler() instanceof I_CmsPasswordSecurityEvaluator) { 119 m_form.setSecurityHint( 120 ((I_CmsPasswordSecurityEvaluator)OpenCms.getPasswordHandler()).getPasswordSecurityHint(m_locale)); 121 } 122 m_passwordChangeButton = new Button(CmsVaadinUtils.getMessageText(Messages.GUI_CHANGE_PASSWORD_BUTTON_0)); 123 addButton(m_passwordChangeButton); 124 m_passwordChangeButton.addClickListener(new ClickListener() { 125 126 /** Serial versino id. */ 127 private static final long serialVersionUID = 1L; 128 129 public void buttonClick(ClickEvent event) { 130 131 submit(); 132 } 133 }); 134 135 m_cancelButton = new Button(CmsVaadinUtils.messageCancel()); 136 addButton(m_cancelButton); 137 m_cancelButton.addClickListener(new ClickListener() { 138 139 /** Serial versino id. */ 140 private static final long serialVersionUID = 1L; 141 142 public void buttonClick(ClickEvent event) { 143 144 close(); 145 } 146 }); 147 m_cancelButton.setVisible(false); 148 m_form.getOldPasswordField().setImmediate(true); 149 m_form.getPassword1Field().setImmediate(true); 150 m_form.getPassword2Field().setImmediate(true); 151 152 m_form.getOldPasswordField().addValueChangeListener(new ValueChangeListener() { 153 154 private static final long serialVersionUID = 1L; 155 156 public void valueChange(ValueChangeEvent event) { 157 158 clearOldPasswordError(); 159 } 160 }); 161 162 m_form.getPassword1Field().addTextChangeListener(new TextChangeListener() { 163 164 private static final long serialVersionUID = 1L; 165 166 public void textChange(TextChangeEvent event) { 167 168 checkSecurity(event.getText()); 169 } 170 }); 171 m_form.getPassword2Field().addTextChangeListener(new TextChangeListener() { 172 173 private static final long serialVersionUID = 1L; 174 175 public void textChange(TextChangeEvent event) { 176 177 checkPasswordMatch(event.getText()); 178 } 179 }); 180 } 181 182 /** 183 * Creates a new instance.<p> 184 * 185 * @param context the dialog context 186 */ 187 public CmsChangePasswordDialog(I_CmsDialogContext context) { 188 189 this(context.getCms(), context.getCms().getRequestContext().getCurrentUser(), UI.getCurrent().getLocale()); 190 m_context = context; 191 m_cancelButton.setVisible(true); 192 setActionHandler(new CmsOkCancelActionHandler() { 193 194 private static final long serialVersionUID = 1L; 195 196 @Override 197 protected void cancel() { 198 199 close(); 200 } 201 202 @Override 203 protected void ok() { 204 205 submit(); 206 } 207 }); 208 } 209 210 /** 211 * Displays some additional text.<p> 212 * 213 * @param text the text to display 214 */ 215 public void setAdditionalMessage(String text) { 216 217 m_form.setAdditionalText(text); 218 } 219 220 /** 221 * Checks whether the passwords match.<p> 222 * 223 * @param password2 the password 2 value 224 */ 225 void checkPasswordMatch(String password2) { 226 227 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(password2)) { 228 showPasswordMatchError(!password2.equals(m_form.getPassword1())); 229 } 230 } 231 232 /** 233 * Checks the security level of the given password.<p> 234 * 235 * @param password the password 236 */ 237 void checkSecurity(String password) { 238 239 I_CmsPasswordHandler handler = OpenCms.getPasswordHandler(); 240 try { 241 handler.validatePassword(password); 242 if (handler instanceof I_CmsPasswordSecurityEvaluator) { 243 SecurityLevel level = ((I_CmsPasswordSecurityEvaluator)handler).evaluatePasswordSecurity(password); 244 m_form.setErrorPassword1(null, OpenCmsTheme.SECURITY + "-" + level.name()); 245 } else { 246 m_form.setErrorPassword1(null, OpenCmsTheme.SECURITY_STRONG); 247 } 248 } catch (CmsSecurityException e) { 249 m_form.setErrorPassword1(new UserError(e.getLocalizedMessage(m_locale)), OpenCmsTheme.SECURITY_INVALID); 250 } 251 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_form.getPassword2())) { 252 showPasswordMatchError(!password.equals(m_form.getPassword2())); 253 } 254 } 255 256 /** 257 * Clears the wrong old password error.<p> 258 */ 259 void clearOldPasswordError() { 260 261 m_form.setErrorOldPassword(null, null); 262 } 263 264 /** 265 * Closes the dialog.<p> 266 */ 267 void close() { 268 269 if (m_context != null) { 270 m_context.finish(Collections.<CmsUUID> emptyList()); 271 } 272 } 273 274 /** 275 * Shows or hides the not matching passwords error.<p> 276 * 277 * @param show <code>true</code> to show the error 278 */ 279 void showPasswordMatchError(boolean show) { 280 281 if (show) { 282 m_form.setErrorPassword2( 283 new UserError(Messages.get().getBundle(m_locale).key(Messages.GUI_PWCHANGE_PASSWORD_MISMATCH_0)), 284 OpenCmsTheme.SECURITY_INVALID); 285 } else { 286 m_form.setErrorPassword2(null, OpenCmsTheme.SECURITY_STRONG); 287 } 288 } 289 290 /** 291 * Submits the password change.<p> 292 */ 293 void submit() { 294 295 String password1 = m_form.getPassword1(); 296 String password2 = m_form.getPassword2(); 297 298 if (validatePasswords(password1, password2)) { 299 String oldPassword = m_form.getOldPassword(); 300 boolean error = false; 301 302 if (oldPassword.equals(password1)) { 303 m_form.setErrorPassword1( 304 new UserError( 305 Messages.get().getBundle(m_locale).key(Messages.GUI_PWCHANGE_DIFFERENT_PASSWORD_REQUIRED_0)), 306 OpenCmsTheme.SECURITY_INVALID); 307 error = true; 308 } else { 309 try { 310 m_cms.setPassword(m_user.getName(), oldPassword, password1); 311 } catch (CmsException e) { 312 m_form.setErrorOldPassword( 313 new UserError(e.getLocalizedMessage(m_locale)), 314 OpenCmsTheme.SECURITY_INVALID); 315 error = true; 316 LOG.debug(e.getLocalizedMessage(), e); 317 } 318 } 319 320 if (!error) { 321 if (m_context != null) { 322 close(); 323 } else { 324 // this will be the case for forced password changes after login 325 CmsVaadinUtils.showAlert( 326 Messages.get().getBundle(m_locale).key(Messages.GUI_PWCHANGE_SUCCESS_HEADER_0), 327 Messages.get().getBundle(m_locale).key(Messages.GUI_PWCHANGE_GUI_PWCHANGE_SUCCESS_CONTENT_0), 328 new Runnable() { 329 330 public void run() { 331 332 A_CmsUI.get().getPage().setLocation( 333 OpenCms.getLinkManager().substituteLinkForUnknownTarget( 334 CmsLoginUI.m_adminCms, 335 CmsWorkplaceLoginHandler.LOGIN_HANDLER 336 + "?ocUname=" 337 + m_user.getSimpleName() 338 + "&ocOuFqn=" 339 + m_user.getOuFqn(), 340 false)); 341 } 342 343 }); 344 } 345 } 346 } 347 } 348 349 /** 350 * Validates the passwords, checking if they match and fulfill the requirements of the password handler.<p> 351 * Will show the appropriate errors if necessary.<p> 352 * 353 * @param password1 password 1 354 * @param password2 password 2 355 * 356 * @return <code>true</code> if valid 357 */ 358 boolean validatePasswords(String password1, String password2) { 359 360 if (!password1.equals(password2)) { 361 showPasswordMatchError(true); 362 return false; 363 } 364 showPasswordMatchError(false); 365 try { 366 OpenCms.getPasswordHandler().validatePassword(password1); 367 m_form.getPassword1Field().setComponentError(null); 368 return true; 369 } catch (CmsException e) { 370 m_form.setErrorPassword1(new UserError(e.getLocalizedMessage(m_locale)), OpenCmsTheme.SECURITY_INVALID); 371 return false; 372 } 373 } 374}