diff --git a/application/loginwebpage.class.inc.php b/application/loginwebpage.class.inc.php index 939ae65eb..b64ad5fe9 100644 --- a/application/loginwebpage.class.inc.php +++ b/application/loginwebpage.class.inc.php @@ -31,72 +31,62 @@ require_once(APPROOT."/application/nicewebpage.class.inc.php"); class LoginWebPage extends NiceWebPage { + protected static $sHandlerClass = __class__; + public static function RegisterHandler($sClass) + { + self::$sHandlerClass = $sClass; + } + + public static function NewLoginWebPage() + { + return new self::$sHandlerClass; + } + protected static $m_sLoginFailedMessage = ''; - public function __construct() - { - parent::__construct("iTop Login"); - $this->add_style(<<SetStyleSheet(); } + public function SetStyleSheet() + { + $this->add_linked_stylesheet("../css/login.css"); + } + public static function SetLoginFailedMessage($sMessage) { self::$m_sLoginFailedMessage = $sMessage; } - + + public function EnableResetPassword() + { + return MetaModel::GetConfig()->Get('forgot_password'); + } + + public function DisplayLoginHeader($bMainAppLogo = false) + { + if ($bMainAppLogo) + { + $sLogo = 'itop-logo.png'; + $sBrandingLogo = 'main-logo.png'; + } + else + { + $sLogo = 'itop-logo-external.png'; + $sBrandingLogo = 'login-logo.png'; + } + $sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_VERSION); + $sIconUrl = Utils::GetConfig()->Get('app_icon_url'); + $sDisplayIcon = utils::GetAbsoluteUrlAppRoot().'images/'.$sLogo; + if (file_exists(MODULESROOT.'branding/'.$sBrandingLogo)) + { + $sDisplayIcon = utils::GetAbsoluteUrlModulesRoot().'branding/'.$sBrandingLogo; + } + $this->add("
\n"); + } + public function DisplayLoginForm($sLoginType, $bFailedLogin = false) { switch($sLoginType) @@ -121,14 +111,7 @@ EOF $sAuthUser = utils::ReadParam('auth_user', '', true, 'raw_data'); $sAuthPwd = utils::ReadParam('suggest_pwd', '', true, 'raw_data'); - $sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_VERSION); - $sIconUrl = Utils::GetConfig()->Get('app_icon_url'); - $sDisplayIcon = utils::GetAbsoluteUrlAppRoot().'images/itop-logo-external.png'; - if (file_exists(MODULESROOT.'branding/login-logo.png')) - { - $sDisplayIcon = utils::GetAbsoluteUrlModulesRoot().'branding/login-logo.png'; - } - $this->add("
\n"); + $this->DisplayLoginHeader(); $this->add("
\n"); $this->add("

".Dict::S('UI:Login:Welcome')."

\n"); if ($bFailedLogin) @@ -148,9 +131,14 @@ EOF } $this->add("
\n"); $this->add("\n"); + $sForgotPwd = $this->EnableResetPassword() ? $this->ForgotPwdLink() : ''; $this->add("\n"); $this->add("\n"); $this->add("\n"); + if (strlen($sForgotPwd) > 0) + { + $this->add("\n"); + } $this->add("
$sForgotPwd
\n"); $this->add("\n"); @@ -180,11 +168,194 @@ EOF } } + /** + * Return '' to disable this feature + */ + public function ForgotPwdLink() + { + $sUrl = '?loginop=forgot_pwd'; + $sHtml = "".Dict::S('UI:Login:ForgotPwd').""; + return $sHtml; + } + + public function DisplayForgotPwdForm($bFailedToReset = false, $sFailureReason = null) + { + $this->DisplayLoginHeader(); + $this->add("
\n"); + $this->add("

".Dict::S('UI:Login:ForgotPwdForm')."

\n"); + $this->add("

".Dict::S('UI:Login:ForgotPwdForm+')."

\n"); + if ($bFailedToReset) + { + $this->add("

".Dict::Format('UI:Login:ResetPwdFailed', $sFailureReason)."

\n"); + } + $sAuthUser = utils::ReadParam('auth_user', '', true, 'raw_data'); + $this->add("\n"); + $this->add("\n"); + $this->add("\n"); + $this->add("\n"); + $this->add("
  
\n"); + $this->add("\n"); + $this->add("\n"); + $this->add("
\n"); + } + + protected function ForgotPwdGo() + { + $sAuthUser = utils::ReadParam('auth_user', '', true, 'raw_data'); + + try + { + UserRights::Login($sAuthUser); // Set the user's language (if possible!) + $oUser = UserRights::GetUserObject(); + if ($oUser == null) + { + throw new Exception(Dict::Format('UI:ResetPwd-Error-WrongLogin', $sAuthUser)); + } + if (!MetaModel::IsValidAttCode(get_class($oUser), 'reset_pwd_token')) + { + throw new Exception(Dict::S('UI:ResetPwd-Error-NotPossible')); + } + if (!$oUser->CanChangePassword()) + { + throw new Exception(Dict::S('UI:ResetPwd-Error-FixedPwd')); + } + + $sTo = $oUser->GetResetPasswordEmail(); // throws Exceptions if not allowed + if ($sTo == '') + { + throw new Exception(Dict::S('UI:ResetPwd-Error-NoEmail')); + } + + // This token allows the user to change the password without knowing the previous one + $sToken = substr(md5(APPROOT.uniqid()), 0, 16); + $oUser->Set('reset_pwd_token', $sToken); + CMDBObject::SetTrackInfo('Reset password'); + $oUser->DBUpdate(); + + $oEmail = new Email(); + $oEmail->SetRecipientTO($sTo); + $oEmail->SetRecipientFrom($sTo); + $oEmail->SetSubject(Dict::S('UI:ResetPwd-EmailSubject')); + $sResetUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?loginop=reset_pwd&auth_user='.urlencode($oUser->Get('login')).'&token='.urlencode($sToken); + $oEmail->SetBody(Dict::Format('UI:ResetPwd-EmailBody', $sResetUrl)); + $iRes = $oEmail->Send($aIssues, true /* force synchronous exec */); + switch ($iRes) + { + //case EMAIL_SEND_PENDING: + case EMAIL_SEND_OK: + break; + + case EMAIL_SEND_ERROR: + default: + IssueLog::Error('Failed to send the email with the NEW password for '.$oUser->Get('friendlyname').': '.implode(', ', $aIssues)); + throw new Exception(Dict::S('UI:ResetPwd-Error-Send')); + } + + $this->DisplayLoginHeader(); + $this->add("
\n"); + $this->add("

".Dict::S('UI:Login:ForgotPwdForm')."

\n"); + $this->add("

".Dict::S('UI:ResetPwd-EmailSent')."

"); + $this->add("
\n"); + $this->add("\n"); + $this->add("\n"); + $this->add("
\n"); + $this->add("
\n"); + $this->add("DisplayForgotPwdForm(true, $e->getMessage()); + } + } + + public function DisplayResetPwdForm() + { + $sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data'); + $sToken = utils::ReadParam('token', '', false, 'raw_data'); + + UserRights::Login($sAuthUser); // Set the user's language + $oUser = UserRights::GetUserObject(); + + $this->DisplayLoginHeader(); + $this->add("
\n"); + $this->add("

".Dict::S('UI:ResetPwd-Title')."

\n"); + if ($oUser == null) + { + $this->add("

".Dict::Format('UI:ResetPwd-Error-WrongLogin', $sAuthUser)."

\n"); + } + elseif ($oUser->Get('reset_pwd_token') != $sToken) + { + $this->add("

".Dict::S('UI:ResetPwd-Error-InvalidToken')."

\n"); + } + else + { + $this->add("

".Dict::Format('UI:ResetPwd-Error-EnterPassword', $oUser->GetFriendlyName())."

\n"); + + $sInconsistenPwdMsg = Dict::S('UI:Login:RetypePwdDoesNotMatch'); + $this->add_script( +<<add("
\n"); + $this->add("\n"); + $this->add("\n"); + $this->add("\n"); + $this->add("\n"); + $this->add("
\n"); + $this->add("\n"); + $this->add("\n"); + $this->add("\n"); + $this->add("
\n"); + $this->add("DisplayLoginHeader(); + $this->add("
\n"); + $this->add("

".Dict::S('UI:ResetPwd-Title')."

\n"); + if ($oUser == null) + { + $this->add("

".Dict::Format('UI:ResetPwd-Error-WrongLogin', $sAuthUser)."

\n"); + } + elseif ($oUser->Get('reset_pwd_token') != $sToken) + { + $this->add("

".Dict::S('UI:ResetPwd-Error-InvalidToken')."

\n"); + } + else + { + // Trash the token and change the password + $oUser->Set('reset_pwd_token', ''); + $oUser->SetPassword($sNewPwd); // Does record the change into the DB + + $this->add("

".Dict::S('UI:ResetPwd-Ready')."

"); + $sUrl = utils::GetAbsoluteUrlAppRoot(); + $this->add("

".Dict::S('UI:ResetPwd-Login')."

"); + } + $this->add("add_script(<<Get('app_icon_url'); - $sDisplayIcon = utils::GetAbsoluteUrlAppRoot().'images/itop-logo.png'; - if (file_exists(MODULESROOT.'branding/main-logo.png')) - { - $sDisplayIcon = utils::GetAbsoluteUrlModulesRoot().'branding/main-logo.png'; - } - $this->add("
\n"); + $this->DisplayLoginHeader(); $this->add("
\n"); $this->add("

".Dict::S('UI:Login:ChangeYourPassword')."

\n"); if ($bFailedLogin) @@ -353,7 +518,7 @@ EOF { $sLoginMode = $aAllowedLoginTypes[0]; // First in the list... } - $oPage = new LoginWebPage(); + $oPage = self::NewLoginWebPage(); $oPage->DisplayLoginForm( $sLoginMode, false /* no previous failed attempt */); $oPage->output(); exit; @@ -364,7 +529,7 @@ EOF { //echo "Check Credentials returned false for user $sAuthUser!"; self::ResetSession(); - $oPage = new LoginWebPage(); + $oPage = self::NewLoginWebPage(); $oPage->DisplayLoginForm( $sLoginMode, true /* failed attempt */); $oPage->output(); exit; @@ -390,6 +555,19 @@ EOF } } + /** + * Overridable: depending on the user, head toward a dedicated portal + * @param bool $bIsAllowedToPortalUsers Whether or not the current page is considered as part of the portal + */ + protected static function ChangeLocation($bIsAllowedToPortalUsers) + { + if ( (!$bIsAllowedToPortalUsers) && (UserRights::IsPortalUser())) + { + // No rights to be here, redirect to the portal + header('Location: '.utils::GetAbsoluteUrlAppRoot().'portal/index.php'); + } + } + /** * Check if the user is already authentified, if yes, then performs some additional validations: * - if $bMustBeAdmin is true, then the user must be an administrator, otherwise an error is displayed @@ -421,16 +599,44 @@ EOF } } self::ResetSession(); - $oPage = new LoginWebPage(); + $oPage = self::NewLoginWebPage(); $oPage->DisplayLoginForm( $sLoginMode, false /* not a failed attempt */); $oPage->output(); exit; } + else if ($operation == 'forgot_pwd') + { + $oPage = self::NewLoginWebPage(); + $oPage->DisplayForgotPwdForm(); + $oPage->output(); + exit; + } + else if ($operation == 'forgot_pwd_go') + { + $oPage = self::NewLoginWebPage(); + $oPage->ForgotPwdGo(); + $oPage->output(); + exit; + } + else if ($operation == 'reset_pwd') + { + $oPage = self::NewLoginWebPage(); + $oPage->DisplayResetPwdForm(); + $oPage->output(); + exit; + } + else if ($operation == 'do_reset_pwd') + { + $oPage = self::NewLoginWebPage(); + $oPage->DoResetPassword(); + $oPage->output(); + exit; + } else if ($operation == 'change_pwd') { $sAuthUser = $_SESSION['auth_user']; UserRights::Login($sAuthUser); // Set the user's language - $oPage = new LoginWebPage(); + $oPage = self::NewLoginWebPage(); $oPage->DisplayChangePwdForm(); $oPage->output(); exit; @@ -443,7 +649,7 @@ EOF $sNewPwd = utils::ReadPostedParam('new_pwd', '', false, 'raw_data'); if (UserRights::CanChangePassword() && ((!UserRights::CheckCredentials($sAuthUser, $sOldPwd)) || (!UserRights::ChangePassword($sOldPwd, $sNewPwd)))) { - $oPage = new LoginWebPage(); + $oPage = self::NewLoginWebPage(); $oPage->DisplayChangePwdForm(true); // old pwd was wrong $oPage->output(); exit; @@ -462,12 +668,7 @@ EOF $oP->output(); exit; } - elseif ( (!$bIsAllowedToPortalUsers) && (UserRights::IsPortalUser())) - { - // No rights to be here, redirect to the portal - header('Location: '.utils::GetAbsoluteUrlAppRoot().'portal/index.php'); - } + call_user_func(array(self::$sHandlerClass, 'ChangeLocation'), $bIsAllowedToPortalUsers); return $sMessage; } } // End of class -?> diff --git a/core/config.class.inc.php b/core/config.class.inc.php index 8b2ba970d..d0164d8b0 100644 --- a/core/config.class.inc.php +++ b/core/config.class.inc.php @@ -525,6 +525,15 @@ class Config 'source_of_value' => '', 'show_in_conf_sample' => false, ), + 'forgot_password' => array( + 'type' => 'bool', + 'description' => 'Enable the "Forgot password" feature', + // examples... not used (nor 'description') + 'default' => true, + 'value' => true, + 'source_of_value' => '', + 'show_in_conf_sample' => false, + ), 'deadline_format' => array( 'type' => 'string', 'description' => 'The format used for displaying "deadline" attributes: any string with the following placeholders: $date$, $difference$', diff --git a/core/userrights.class.inc.php b/core/userrights.class.inc.php index 3dad02dda..93e0677b7 100644 --- a/core/userrights.class.inc.php +++ b/core/userrights.class.inc.php @@ -140,6 +140,7 @@ abstract class User extends cmdbAbstractObject return $sLastName; } } + return $this->Get('login'); } /* @@ -289,6 +290,9 @@ abstract class UserInternal extends User MetaModel::Init_Params($aParams); MetaModel::Init_InheritAttributes(); + // When set, this token allows for password reset + MetaModel::Init_AddAttribute(new AttributeString("reset_pwd_token", array("allowed_values"=>null, "sql"=>"reset_pwd_token", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); + // Display lists MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'language', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('list', array('finalclass', 'first_name', 'last_name', 'login')); // Attributes to be displayed for a list @@ -296,6 +300,47 @@ abstract class UserInternal extends User MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid')); // Criteria of the std search form MetaModel::Init_SetZListItems('advanced_search', array('login', 'contactid')); // Criteria of the advanced search form } + + /** + * Use with care! + */ + public function SetPassword($sNewPassword) + { + } + + /** + * The email recipient is the person who is allowed to regain control when the password gets lost + * Throws an exception if the feature cannot be available + */ + public function GetResetPasswordEmail() + { + if (!MetaModel::IsValidAttCode(get_class($this), 'contactid')) + { + throw new Exception(Dict::S('UI:ResetPwd-Error-NoContact')); + } + $iContactId = $this->Get('contactid'); + if ($iContactId == 0) + { + throw new Exception(Dict::S('UI:ResetPwd-Error-NoContact')); + } + $oContact = MetaModel::GetObject('Contact', $iContactId); + // Determine the email attribute (the first one will be our choice) + foreach (MetaModel::ListAttributeDefs(get_class($oContact)) as $sAttCode => $oAttDef) + { + if ($oAttDef instanceof AttributeEmailAddress) + { + $sEmailAttCode = $sAttCode; + // we've got one, exit the loop + break; + } + } + if (!isset($sEmailAttCode)) + { + throw new Exception(Dict::S('UI:ResetPwd-Error-NoEmailAtt')); + } + $sRes = trim($oContact->Get($sEmailAttCode)); + return $sRes; + } } /** diff --git a/css/login.css b/css/login.css new file mode 100644 index 000000000..ed6ef46d6 --- /dev/null +++ b/css/login.css @@ -0,0 +1,52 @@ +@CHARSET "UTF-8"; +body { + background: #eee; + margin: 0; + padding: 0; +} +#login-logo { + margin-top: 150px; + width: 300px; + padding-left: 20px; + padding-right: 20px; + padding-top: 10px; + padding-bottom: 10px; + margin-left: auto; + margin-right: auto; + background: #f6f6f1; + height: 54px; + border-top: 1px solid #000; + border-left: 1px solid #000; + border-right: 1px solid #000; + border-bottom: 0; + text-align: center; +} +#login-logo img { + border: 0; +} +#login { + width: 300px; + margin-left: auto; + margin-right: auto; + padding: 20px; + background-color: #fff; + border-bottom: 1px solid #000; + border-left: 1px solid #000; + border-right: 1px solid #000; + border-top: 0; + text-align: center; +} +#pwd, #user,#old_pwd, #new_pwd, #retype_new_pwd { + width: 10em; +} +.center { + text-align: center; +} + +h1 { + color: #1C94C4; + font-size: 16pt; +} +.v-spacer { + padding-top: 1em; +} diff --git a/dictionaries/dictionary.itop.ui.php b/dictionaries/dictionary.itop.ui.php index 73197baf9..55af72996 100644 --- a/dictionaries/dictionary.itop.ui.php +++ b/dictionaries/dictionary.itop.ui.php @@ -475,6 +475,29 @@ 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:ForgotPwd' => 'Forgot your password?', + 'UI:Login:ForgotPwdForm' => 'Forgot your password', + 'UI:Login:ForgotPwdForm+' => 'iTop can send you an email in which you will find instructions to follow to reset your account.', + 'UI:Button:ResetPassword' => 'Send now!', + 'UI:Login:ResetPwdFailed' => 'Failed to send an email: %1$s', + + 'UI:ResetPwd-Error-WrongLogin' => '\'%1$s\' is not a valid login', + 'UI:ResetPwd-Error-NotPossible' => 'external accounts do not allow password reset.', + 'UI:ResetPwd-Error-FixedPwd' => 'the account does not allow password reset.', + 'UI:ResetPwd-Error-NoContact' => 'the account is not associated to a person.', + 'UI:ResetPwd-Error-NoEmailAtt' => 'the account is not associated to a person having an email attribute. Please Contact your administrator.', + 'UI:ResetPwd-Error-NoEmail' => 'missing an email address. Please Contact your administrator.', + 'UI:ResetPwd-Error-Send' => 'email transport technical issue. Please Contact your administrator.', + 'UI:ResetPwd-EmailSent' => 'Please check your email box and follow the instructions...', + 'UI:ResetPwd-EmailSubject' => 'Reset your iTop password', + 'UI:ResetPwd-EmailBody' => '

You have requested to reset your iTop password.

Please follow this link (single usage) to enter a new password

.', + + 'UI:ResetPwd-Title' => 'Reset password', + 'UI:ResetPwd-Error-InvalidToken' => 'Sorry, either the password has already been reset, or you have received several emails. Please make sure that you use the link provided in the very last email received.', + 'UI:ResetPwd-Error-EnterPassword' => 'Enter a new password for the account \'%1$s\'.', + 'UI:ResetPwd-Ready' => 'The password has been changed.', + 'UI:ResetPwd-Login' => 'Click here to login...', + 'UI:Login:About' => '', 'UI:Login:ChangeYourPassword' => 'Change Your Password', 'UI:Login:OldPasswordPrompt' => 'Old password', @@ -485,11 +508,11 @@ Dict::Add('EN US', 'English', 'English', array( 'UI:LogOff:ThankYou' => 'Thank you for using iTop', 'UI:LogOff:ClickHereToLoginAgain' => 'Click here to login again...', 'UI:ChangePwdMenu' => 'Change Password...', - 'UI:Login:PasswordChanged' => 'Password successfully set !', + 'UI:Login:PasswordChanged' => 'Password successfully set!', 'UI:AccessRO-All' => 'iTop is read-only', 'UI:AccessRO-Users' => 'iTop is read-only for end-users', 'UI:ApplicationEnvironment' => 'Application environment: %1$s', - 'UI:Login:RetypePwdDoesNotMatch' => 'New password and retyped new password do not match !', + 'UI:Login:RetypePwdDoesNotMatch' => 'New password and retyped new password do not match!', 'UI:Button:Login' => 'Enter iTop', 'UI:Login:Error:AccessRestricted' => 'iTop access is restricted. Please, contact an iTop administrator.', 'UI:Login:Error:AccessAdmin' => 'Access restricted to people having administrator privileges. Please, contact an iTop administrator.', diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php index c7d7cc906..34404fdae 100644 --- a/dictionaries/fr.dictionary.itop.ui.php +++ b/dictionaries/fr.dictionary.itop.ui.php @@ -351,6 +351,29 @@ 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:ForgotPwd' => 'Mot de passe oublié ?', + 'UI:Login:ForgotPwdForm' => 'Mot de passe oublié', + 'UI:Login:ForgotPwdForm+' => 'Vous pouvez demander à saisir d\'un nouveau mot de passe. Vous allez recevoir un email et vous pourrez suivre les instructions.', + 'UI:Button:ResetPassword' => 'Envoyer le message', + 'UI:Login:ResetPwdFailed' => 'Impossible de vous faire parvenir le message: %1$s', + + 'UI:ResetPwd-Error-WrongLogin' => 'le compte \'%1$s\' est inconnu.', + 'UI:ResetPwd-Error-NotPossible' => 'les comptes "externes" ne permettent pas la saisie d\'un mot de passe dans iTop.', + 'UI:ResetPwd-Error-FixedPwd' => 'ce mode de saisie du mot de passe n\'est pas autorisé pour ce compte.', + 'UI:ResetPwd-Error-NoContact' => 'le comte n\'est pas associé à une Personne.', + 'UI:ResetPwd-Error-NoEmailAtt' => 'il manque un attribut de type "email" sur la Personne associée à ce compte. Veuillez contacter l\'administrateur de l\'application.', + 'UI:ResetPwd-Error-NoEmail' => 'il manque une adresse email sur la Personne associée à ce compte. Veuillez contacter l\'administrateur de l\'application.', + 'UI:ResetPwd-Error-Send' => 'erreur technique lors de l\'envoi de l\'email. Veuillez contacter l\'administrateur de l\'application.', + 'UI:ResetPwd-EmailSent' => 'Veuillez vérifier votre boîte de réception. Ensuite, suivez les instructions données dans l\'email...', + 'UI:ResetPwd-EmailSubject' => 'Changer votre mot de passe iTop', + 'UI:ResetPwd-EmailBody' => '

Vous avez demandé à changer votre de passe iTop sans connaitre le mot de passe précédent.

Veuillez suivre le lien suivant (usage unique) afin de pouvoir saisir un nouveau mot de passe

.', + + 'UI:ResetPwd-Title' => 'Nouveau mot de passe', + 'UI:ResetPwd-Error-InvalidToken' => 'Désolé, le mot de passe a déjà été modifié avec le lien que vous avez suivi, ou bien vous avez reçu plusieurs emails. Dans ce cas, veillez à utiliser le tout dernier lien reçu.', + 'UI:ResetPwd-Error-EnterPassword' => 'Veuillez saisir le nouveau mot de passe pour \'%1$s\'.', + 'UI:ResetPwd-Ready' => 'Le mot de passe a bien été changé.', + 'UI:ResetPwd-Login' => 'Cliquez ici pour vous connecter...', + 'UI:Login:ChangeYourPassword' => 'Changer de mot de passe', 'UI:Login:OldPasswordPrompt' => 'Ancien mot de passe', 'UI:Login:NewPasswordPrompt' => 'Nouveau mot de passe', diff --git a/pages/logoff.php b/pages/logoff.php index 97b4bc1ea..5303fa800 100644 --- a/pages/logoff.php +++ b/pages/logoff.php @@ -51,16 +51,9 @@ switch($sLoginMode) phpCAS::logoutWithRedirectService($sCASLogoutUrl); // Redirects to the CAS logout page break; } -$oPage = new LoginWebPage(); +$oPage = LoginWebPage::NewLoginWebPage(); $oPage->no_cache(); -$sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_VERSION); -$sIconUrl = Utils::GetConfig()->Get('app_icon_url'); -$sDisplayIcon = utils::GetAbsoluteUrlAppRoot().'images/itop-logo-external.png'; -if (file_exists(MODULESROOT.'branding/login-logo.png')) -{ - $sDisplayIcon = utils::GetAbsoluteUrlModulesRoot().'branding/login-logo.png'; -} -$oPage->add("
\n"); +$oPage->DisplayLoginHeader(); $oPage->add("
\n"); $oPage->add("

".Dict::S('UI:LogOff:ThankYou')."

\n");