diff --git a/addons/userrights/userrightsmatrix.class.inc.php b/addons/userrights/userrightsmatrix.class.inc.php
index 632905031..a85d4bf18 100644
--- a/addons/userrights/userrightsmatrix.class.inc.php
+++ b/addons/userrights/userrightsmatrix.class.inc.php
@@ -304,6 +304,30 @@ class UserRightsMatrix extends UserRightsAddOnAPI
// todo: throw an exception?
return false;
}
+
+ public function CanChangePassword()
+ {
+ return true;
+ }
+
+ public function ChangePassword($iUserId, $sOldPassword, $sNewPassword)
+ {
+ $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixUsers WHERE userid = $iUserId"));
+ if ($oSet->Count() < 1)
+ {
+ return false;
+ }
+
+ $oLogin = $oSet->Fetch();
+ if ($oLogin->Get('password') == $sOldPassword)
+ {
+ $oLogin->Set('password', $sNewPassword);
+ $oLogin->DBUpdate();
+ return true;
+ }
+ return false;
+ }
+
public function GetUserId($sUserName)
{
diff --git a/addons/userrights/userrightsnull.class.inc.php b/addons/userrights/userrightsnull.class.inc.php
index 82d6a00d8..e4b034b90 100644
--- a/addons/userrights/userrightsnull.class.inc.php
+++ b/addons/userrights/userrightsnull.class.inc.php
@@ -51,6 +51,16 @@ class UserRightsNull extends UserRightsAddOnAPI
{
return 1;
}
+
+ public function CanChangePassword()
+ {
+ return true;
+ }
+
+ public function ChangePassword($iUserId, $sOldPassword, $sNewPassword)
+ {
+ return true;
+ }
public function GetUserId($sUserName)
{
diff --git a/addons/userrights/userrightsprofile.class.inc.php b/addons/userrights/userrightsprofile.class.inc.php
index ffa532cdb..929c92778 100644
--- a/addons/userrights/userrightsprofile.class.inc.php
+++ b/addons/userrights/userrightsprofile.class.inc.php
@@ -883,6 +883,41 @@ exit;
return false;
}
+ public function CanChangePassword()
+ {
+ // For now everyone can change their password..
+ return true;
+ }
+
+ public function ChangePassword($iUserId, $sOldPassword, $sNewPassword)
+ {
+ $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT URP_Users WHERE id = :user_id"), array(), array('user_id' => $iUserId));
+ if ($oSet->Count() < 1)
+ {
+ return false;
+ }
+
+ $oLogin = $oSet->Fetch();
+ if ($oLogin->Get('password') == $sOldPassword)
+ {
+ $oLogin->Set('password', $sNewPassword);
+ $oChange = MetaModel::NewObject("CMDBChange");
+ $oChange->Set("date", time());
+ if (UserRights::GetUser() != UserRights::GetRealUser())
+ {
+ $sUserString = Dict::Format('UI:Archive_User_OnBehalfOf_User', UserRights::GetRealUser(), UserRights::GetUser());
+ }
+ else
+ {
+ $sUserString = UserRights::GetUser();
+ }
+ $oChange->Set("userinfo", $sUserString);
+ $oLogin->DBUpdateTracked($oChange);
+ return true;
+ }
+ return false;
+ }
+
public function GetUserId($sUserName)
{
if (array_key_exists($sUserName, $this->m_aLogin2UserId))
diff --git a/application/itopwebpage.class.inc.php b/application/itopwebpage.class.inc.php
index dc2e5e623..b05b40bed 100644
--- a/application/itopwebpage.class.inc.php
+++ b/application/itopwebpage.class.inc.php
@@ -455,8 +455,11 @@ EOF
}
$sLogOffMenu = "
\n \n
\n";
//$sLogOffMenu = "
";
diff --git a/application/loginwebpage.class.inc.php b/application/loginwebpage.class.inc.php
index b22190477..f2da48f3e 100644
--- a/application/loginwebpage.class.inc.php
+++ b/application/loginwebpage.class.inc.php
@@ -40,7 +40,7 @@ body {
}
#login-logo {
margin-top: 150px;
- width: 250px;
+ width: 300px;
padding-left: 20px;
padding-right: 20px;
padding-top: 10px;
@@ -59,7 +59,7 @@ body {
border: 0;
}
#login {
- width: 250px;
+ width: 300px;
margin-left: auto;
margin-right: auto;
padding: 20px;
@@ -112,6 +112,31 @@ EOF
$this->add("\n");
}
+ public function DisplayChangePwdForm($bFailedLogin = false)
+ {
+ $sAuthUser = utils::ReadParam('auth_user', '');
+ $sAuthPwd = utils::ReadParam('suggest_pwd', '');
+
+ $sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_VERSION);
+ $this->add("

\n");
+ $this->add("\n");
+ $this->add("
".Dict::S('UI:Login:ChangeYourPassword')."
\n");
+ if ($bFailedLogin)
+ {
+ $this->add("
".Dict::S('UI:Login:IncorrectOldPassword')."
\n");
+ }
+ $this->add("
\n");
+ $this->add("
\n");
+ }
+
static protected function ResetSession()
{
// Unset all of the session variables.
@@ -193,6 +218,33 @@ EOF
self::ResetSession();
}
+ if ($operation == 'change_pwd')
+ {
+ $oPage = new LoginWebPage();
+ $oPage->DisplayChangePwdForm();
+ $oPage->output();
+ exit;
+ }
+ if ($operation == 'do_change_pwd')
+ {
+ $sAuthUser = $_SESSION['auth_user'];
+ $sOldPwd = utils::ReadPostedParam('old_pwd');
+ $sNewPwd = utils::ReadPostedParam('new_pwd');
+ if (UserRights::CanChangePassword() && ((!UserRights::Login($sAuthUser, $sOldPwd)) || (!UserRights::ChangePassword($sOldPwd, $sNewPwd))))
+ {
+ $oPage = new LoginWebPage();
+ $oPage->DisplayChangePwdForm(true); // old pwd was wrong
+ $oPage->output();
+ exit;
+ }
+ else
+ {
+ // Remember the changed password
+ $_SESSION['auth_pwd'] = $sNewPwd;
+ return;
+ }
+ }
+
if (!isset($_SESSION['auth_user']) || !isset($_SESSION['auth_pwd']))
{
if ($operation == 'loginurl')
diff --git a/core/userrights.class.inc.php b/core/userrights.class.inc.php
index d19a338fe..7519e5dcd 100644
--- a/core/userrights.class.inc.php
+++ b/core/userrights.class.inc.php
@@ -55,6 +55,8 @@ abstract class UserRightsAddOnAPI
abstract public function Init(); // loads data (possible optimizations)
abstract public function CheckCredentials($sLogin, $sPassword); // returns the id of the user or false
+ abstract public function CanChangePassword(); // Whether or not a user can change her/his own password
+ abstract public function ChangePassword($iUserId, $sOldPassword, $sNewPassword); // Change the password of the specified user
abstract public function GetUserLanguage($sLogin); // returns the language code (e.g "EN US")
abstract public function GetUserId($sLogin); // returns the id of the user or false
abstract public function GetContactId($sLogin); // returns the id of the "business" user or false
@@ -144,6 +146,30 @@ class UserRights
}
}
+ public static function CanChangePassword()
+ {
+ if (!is_null(self::$m_iUserId))
+ {
+ return self::$m_oAddOn->CanChangePassword(self::$m_iUserId);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public static function ChangePassword($sCurrentPassword, $sNewPassword)
+ {
+ if (!is_null(self::$m_iUserId))
+ {
+ return self::$m_oAddOn->ChangePassword(self::$m_iUserId, $sCurrentPassword, $sNewPassword);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
public static function Impersonate($sName, $sPassword)
{
if (!self::CheckLogin()) return false;
diff --git a/dictionaries/dictionary.itop.ui.php b/dictionaries/dictionary.itop.ui.php
index ddbca82f1..3c66730b8 100644
--- a/dictionaries/dictionary.itop.ui.php
+++ b/dictionaries/dictionary.itop.ui.php
@@ -358,6 +358,7 @@ Dict::Add('EN US', 'English', 'English', array(
'UI:Button:FilterList' => ' Filter... ',
'UI:Button:Create' => ' Create ',
'UI:Button:Delete' => ' Delete ! ',
+ 'UI:Button:ChangePassword' => ' Change Password ',
'UI:SearchToggle' => 'Search',
'UI:ClickToCreateNew' => 'Click here to create a new %1$s',
@@ -437,6 +438,13 @@ Dict::Add('EN US', 'English', 'English', array(
'UI:Login:IdentifyYourself' => 'Identify yourself before continuing',
'UI:Login:UserNamePrompt' => 'User Name',
'UI:Login:PasswordPrompt' => 'Password',
+ 'UI:Login:ChangeYourPassword' => 'Change Your Password',
+ 'UI:Login:OldPasswordPrompt' => 'Old password',
+ 'UI:Login:NewPasswordPrompt' => 'New password',
+ 'UI:Login:RetypeNewPasswordPrompt' => 'Retype new password',
+ 'UI:Login:IncorrectOldPassword' => 'Error: the old password is incorrect',
+ 'UI:LogoffMenu' => 'Log off',
+ 'UI:ChangePwdMenu' => 'Change Password...',
'UI:Button:Login' => 'Enter iTop',
'UI:Login:Error:AccessRestricted' => 'iTop access is restricted. Please, contact an iTop administrator.',
'UI:CSVImport:MappingSelectOne' => '-- select one --',
diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php
index 8dd286db8..1a9ff348d 100644
--- a/dictionaries/fr.dictionary.itop.ui.php
+++ b/dictionaries/fr.dictionary.itop.ui.php
@@ -351,6 +351,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
'UI:Button:FilterList' => ' Filtrer... ',
'UI:Button:Create' => ' Créer ',
'UI:Button:Delete' => ' Supprimer ! ',
+ 'UI:Button:ChangePassword' => ' Changer ! ',
'UI:SearchToggle' => 'Recherche',
@@ -429,6 +430,13 @@ Dict::Add('FR FR', 'French', 'Français', array(
'UI:Login:IdentifyYourself' => 'Merci de vous identifier',
'UI:Login:UserNamePrompt' => 'Identifiant',
'UI:Login:PasswordPrompt' => 'Mot de passe',
+ 'UI:Login:ChangeYourPassword' => 'Changer de mot de passe',
+ 'UI:Login:OldPasswordPrompt' => 'Ancien mot de passe',
+ 'UI:Login:NewPasswordPrompt' => 'Nouveau mot de passe',
+ 'UI:Login:RetypeNewPasswordPrompt' => 'Resaisir le nouveau mot de passe',
+ 'UI:Login:IncorrectOldPassword' => 'Erreur: l\'ancien mot de passe est incorrect',
+ 'UI:LogoffMenu' => 'Déconnexion',
+ 'UI:ChangePwdMenu' => 'Changer de mot de passe...',
'UI:Button:Login' => 'Entrer dans iTop',
'UI:Login:Error:AccessRestricted' => 'L\'accès à iTop est soumis à autorisation. Merci de contacter votre administrateur iTop.',
'UI:CSVImport:MappingSelectOne' => '-- choisir une valeur --',