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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+