From 42eccc8baf41238a720665d6c4fe78d8fde7443d Mon Sep 17 00:00:00 2001 From: Cristina Alvarino Date: Thu, 7 Jul 2011 09:32:07 +0200 Subject: [PATCH] New option "Change password" in tab "Settings" FEA: ItEr75S07UserSettings --- .../web/common/CustomMenuController.java | 3 +- .../web/users/settings/IPasswordModel.java | 45 ++++++ .../web/users/settings/ISettingsModel.java | 8 - .../users/settings/PasswordController.java | 111 ++++++++++++++ .../web/users/settings/PasswordModel.java | 143 ++++++++++++++++++ .../users/settings/SettingsController.java | 22 --- .../web/users/settings/SettingsModel.java | 46 +----- .../main/webapp/settings/changePassword.zul | 81 ++++++++++ .../src/main/webapp/settings/settings.zul | 11 -- 9 files changed, 383 insertions(+), 87 deletions(-) create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/IPasswordModel.java create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/PasswordController.java create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/PasswordModel.java create mode 100644 navalplanner-webapp/src/main/webapp/settings/changePassword.zul diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/CustomMenuController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/CustomMenuController.java index 716d9ec62..13e5864e6 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/CustomMenuController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/CustomMenuController.java @@ -340,7 +340,8 @@ public class CustomMenuController extends Div implements IMenuItemsRegister { subItem(_("Materials Needs At Date"),"/reports/timeLineMaterialReport.zul","15-informes.html")); topItem(_("My account"), "", "", - subItem(_("Settings"), "/settings/settings.zul", "")); + subItem(_("Settings"), "/settings/settings.zul", ""), + subItem(_("Change Password"), "/settings/changePassword.zul", "")); } private Vbox getRegisteredItemsInsertionPoint() { diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/IPasswordModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/IPasswordModel.java new file mode 100644 index 000000000..241b4cf16 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/IPasswordModel.java @@ -0,0 +1,45 @@ +/* + * This file is part of NavalPlan + * + * Copyright (C) 2011 ComtecSF, S.L. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.navalplanner.web.users.settings; + +import org.navalplanner.business.common.exceptions.ValidationException; + +/** + * Model for UI operations related to user password + * + * @author Cristina Alvarino Perez + * @author Ignacio Diaz Teijido + */ +public interface IPasswordModel { + + void initEditLoggedUser(); + + void confirmSave() throws ValidationException; + + /** + * Sets the password attribute to the inner {@ link User} object. + * + * @param password String with the unencrypted password. + */ + void setPassword(String password); + + boolean validateCurrentPassword(String value); + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/ISettingsModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/ISettingsModel.java index c8ff07e4c..4093a18af 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/ISettingsModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/ISettingsModel.java @@ -67,12 +67,4 @@ public interface ISettingsModel { String getLoginName(); - /** - * Sets the password attribute to the inner {@ link User} object. - * - * @param password String with the unencrypted password. - */ - void setPassword(String password); - - String getClearNewPassword(); } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/PasswordController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/PasswordController.java new file mode 100644 index 000000000..de9dad0a9 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/PasswordController.java @@ -0,0 +1,111 @@ +/* + * This file is part of NavalPlan + * + * Copyright (C) 2011 ComtecSF, S.L. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.navalplanner.web.users.settings; + +import static org.navalplanner.web.I18nHelper._; + +import org.apache.commons.lang.StringUtils; +import org.navalplanner.business.common.exceptions.ValidationException; +import org.navalplanner.web.common.ConstraintChecker; +import org.navalplanner.web.common.IMessagesForUser; +import org.navalplanner.web.common.Level; +import org.navalplanner.web.common.MessagesForUser; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.WrongValueException; +import org.zkoss.zk.ui.util.GenericForwardComposer; +import org.zkoss.zul.Constraint; +import org.zkoss.zul.Textbox; +import org.zkoss.zul.api.Window; + +/** + * Controller for password changes + * + * @author Cristina Alvarino Perez + * @author Ignacio Diaz Teijido + */ +public class PasswordController extends GenericForwardComposer { + + private Window passwordWindow; + + private IMessagesForUser messages; + + private Component messagesContainer; + + private IPasswordModel passwordModel; + + private Textbox password; + + public void doAfterCompose(Component comp) throws Exception { + super.doAfterCompose(comp); + comp.setVariable("passwordController", this, true); + messages = new MessagesForUser(messagesContainer); + passwordModel.initEditLoggedUser(); + } + + public void save() { + if(ConstraintChecker.isValid(passwordWindow)) { + try { + passwordModel.confirmSave(); + messages.showMessage(Level.INFO, _("Password saved")); + + } catch (ValidationException e) { + messages.showInvalidValues(e); + } + } + } + + /** + * Tells the SettingsModel to set the password attribute of the inner + * {@ link User} object. + * + * @param password String with the unencrypted password. + */ + public void setPassword(String password) { + passwordModel.setPassword(password); + } + + public Constraint validatePasswordConfirmation() { + return new Constraint() { + @Override + public void validate(Component comp, Object value) + throws WrongValueException { + if(StringUtils.isEmpty((String)value) || StringUtils.isEmpty(password.getValue())) { + throw new WrongValueException(comp, _("passwords can not be empty")); + } + if(!((String)value).equals(password.getValue())) { + throw new WrongValueException(comp, _("passwords don't match")); + } + } + }; + } + + public Constraint validateCurrentPassword() { + return new Constraint() { + @Override + public void validate(Component comp, Object value) + throws WrongValueException { + if(!passwordModel.validateCurrentPassword((String)value)) { + throw new WrongValueException(comp, _("Current password is incorrect")); + } + } + }; + } + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/PasswordModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/PasswordModel.java new file mode 100644 index 000000000..f156efd39 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/PasswordModel.java @@ -0,0 +1,143 @@ +/* + * This file is part of NavalPlan + * + * Copyright (C) 2011 ComtecSF, S.L. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.navalplanner.web.users.settings; + +import org.navalplanner.business.common.Configuration; +import org.navalplanner.business.common.exceptions.InstanceNotFoundException; +import org.navalplanner.business.common.exceptions.ValidationException; +import org.navalplanner.business.users.daos.IUserDAO; +import org.navalplanner.business.users.entities.Profile; +import org.navalplanner.business.users.entities.User; +import org.navalplanner.business.users.entities.UserRole; +import org.navalplanner.web.common.concurrentdetection.OnConcurrentModification; +import org.navalplanner.web.security.SecurityUtils; +import org.navalplanner.web.users.PasswordUtil; +import org.navalplanner.web.users.services.IDBPasswordEncoderService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * Model for UI operations related to user password + * + * @author Cristina Alvarino Perez + * @author Ignacio Diaz Teijido + */ +@Service +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +@OnConcurrentModification(goToPage = "/settings/changePassword.zul") +public class PasswordModel extends PasswordUtil implements IPasswordModel{ + + @Autowired + private IUserDAO userDAO; + + private User user; + + @Autowired + private IDBPasswordEncoderService dbPasswordEncoderService; + + @Override + @Transactional + public void confirmSave() throws ValidationException { + try { + if (getClearNewPassword() != null) { + + /* + * it ckecks if the user password who have admin role has + * changed and if so sets true in the field + * changedDefaultAdminPassword. + */ + if (Configuration.isDefaultPasswordsControl()) { + checkIfChangeDefaultPasswd(user); + } + + user.setPassword(dbPasswordEncoderService.encodePassword( + getClearNewPassword(), user.getLoginName())); + } + } catch (IllegalArgumentException e) { + } + user.validate(); + userDAO.save(user); + } + + @Override + public void setPassword(String password) { + // password is not encrypted right away, because + // user.getLoginName must exist to do that, and we're + // not sure at this point + if (password != "") { + setClearNewPassword(password); + } else { + setClearNewPassword(null); + } + } + + private User findByLoginUser(String login) { + try { + return user = userDAO.findByLoginName(login); + } catch (InstanceNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + @Transactional(readOnly = true) + public void initEditLoggedUser() { + User user = findByLoginUser(SecurityUtils.getSessionUserLoginName()); + this.user = getFromDB(user); + } + + @Transactional(readOnly = true) + private User getFromDB(User user) { + return getFromDB(user.getId()); + } + + private User getFromDB(Long id) { + try { + User result = userDAO.find(id); + forceLoadEntities(result); + return result; + } catch (InstanceNotFoundException e) { + throw new RuntimeException(e); + } + } + + private void forceLoadEntities(User user) { + user.getLoginName(); + for (UserRole each : user.getRoles()) { + each.name(); + } + for (Profile each : user.getProfiles()) { + each.getProfileName(); + } + } + + @Override + public boolean validateCurrentPassword(String value) + { + String currentPasswordEncoded = dbPasswordEncoderService.encodePassword((String)value, user.getLoginName()); + if(!(currentPasswordEncoded).equals(user.getPassword())) { + return false; + } + return true; + } +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/SettingsController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/SettingsController.java index af81f41ac..4d713740c 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/SettingsController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/SettingsController.java @@ -140,28 +140,6 @@ public class SettingsController extends GenericForwardComposer { settingsModel.setLastName(lastName); } - /** - * Tells the SettingsModel to set the password attribute of the inner - * {@ link User} object. - * - * @param password String with the unencrypted password. - */ - public void setPassword(String password) { - settingsModel.setPassword(password); - } - - public Constraint validatePasswordConfirmation() { - return new Constraint() { - @Override - public void validate(Component comp, Object value) - throws WrongValueException { - if(!((String)value).equals(password.getValue())) { - throw new WrongValueException(comp, _("passwords don't match")); - } - } - }; - } - public String getLoginName() { return settingsModel.getLoginName(); } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/SettingsModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/SettingsModel.java index 0686a5260..9d27a8e6d 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/SettingsModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/settings/SettingsModel.java @@ -20,7 +20,6 @@ package org.navalplanner.web.users.settings; import org.apache.commons.lang.Validate; -import org.navalplanner.business.common.Configuration; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.common.exceptions.ValidationException; import org.navalplanner.business.settings.entities.Language; @@ -30,8 +29,6 @@ import org.navalplanner.business.users.entities.User; import org.navalplanner.business.users.entities.UserRole; import org.navalplanner.web.common.concurrentdetection.OnConcurrentModification; import org.navalplanner.web.security.SecurityUtils; -import org.navalplanner.web.users.PasswordUtil; -import org.navalplanner.web.users.services.IDBPasswordEncoderService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; @@ -47,18 +44,13 @@ import org.springframework.transaction.annotation.Transactional; @Service @Scope(BeanDefinition.SCOPE_PROTOTYPE) @OnConcurrentModification(goToPage = "/settings/settings.zul") -public class SettingsModel extends PasswordUtil implements ISettingsModel { +public class SettingsModel implements ISettingsModel { @Autowired private IUserDAO userDAO; private User user; - private String clearNewPassword; - - @Autowired - private IDBPasswordEncoderService dbPasswordEncoderService; - @Override public Language getApplicationLanguage() { return user.getApplicationLanguage(); @@ -117,47 +109,11 @@ public class SettingsModel extends PasswordUtil implements ISettingsModel { // because it must exist to perform the encoding Validate.notEmpty(user.getLoginName()); - if (getClearNewPassword() != null) { - - /* - * it ckecks if the user password who have admin role has - * changed and if so sets true in the field - * changedDefaultAdminPassword. - */ - if (Configuration.isDefaultPasswordsControl()) { - checkIfChangeDefaultPasswd(user); - } - - user.setPassword(dbPasswordEncoderService.encodePassword( - getClearNewPassword(), user.getLoginName())); - } } catch (IllegalArgumentException e) { } user.validate(); userDAO.save(user); } - - @Override - public void setPassword(String password) { - // password is not encrypted right away, because - // user.getLoginName must exist to do that, and we're - // not sure at this point - if (password != "") { - setClearNewPassword(password); - } else { - setClearNewPassword(null); - } - } - - public void setClearNewPassword(String clearNewPassword) { - this.clearNewPassword = clearNewPassword; - } - - @Override - public String getClearNewPassword() { - return clearNewPassword; - } - @Override public boolean isExpandCompanyPlanningViewCharts() { return user.isExpandCompanyPlanningViewCharts(); diff --git a/navalplanner-webapp/src/main/webapp/settings/changePassword.zul b/navalplanner-webapp/src/main/webapp/settings/changePassword.zul new file mode 100644 index 000000000..bca9ae5fc --- /dev/null +++ b/navalplanner-webapp/src/main/webapp/settings/changePassword.zul @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +