stable
Clone or download
Read-only
request #11217 Account takeover due to a missing CSRF protection
Change email CSRF challenge was generated but never checked. Added another round of protection by ensuring that users are logged in when they confirm their change. The confirmation hash generation was also replace for a true random source. Change-Id: Ic0ef04f2fac95c5d501dd42b257dbf519c1482ff
Modified Files
--- 'a/site-content/en_US/account/account.tab'
+++ b/site-content/en_US/account/account.tab
@@ -110,29 +110,6 @@ account_preferences html_format HTML
account_preferences text_format Text
#
#-----------------------------------------------
-# Script: SF/www/account/change_email.php
-#
-account_change_email title Change Email Address
-account_change_email message <P>Changing your email address will require confirmation from your new email address, so that we can ensure we have a good email address on file. <P>Submitting the form below will mail a confirmation URL to the new email address. Visiting this link will complete the email change.
-account_change_email label_new New Email Address
-account_change_email send_new Send Confirmation to New Address
-#
-#-----------------------------------------------
-# Script: SF/www/account/change_email-confirm.php
-#
-account_change_email-confirm message You have requested a change of email address on $1.\nPlease visit the following URL to complete the email change:\n\n$2\n\n-- The $1 Team
-account_change_email-confirm title Email Change Confirmation
-account_change_email-confirm mailsent An email has been sent to the new address. Follow the instructions in the email to complete the email change.
-#
-#-----------------------------------------------
-# Script: SF/www/account/change_email-complete.php
-#
-account_change_email-complete invalid_hash Invalid confirmation hash.
-account_change_email-complete duplicate_hash This hash key exists more than once.
-account_change_email-complete title Email Change Complete
-account_change_email-complete message Welcome, $1.<P>Your email change is complete. Your new email address on file is <B>$2</B>. Mail sent to $3 user $1 (login $4) will now be forwarded to this new email address.
-#
-#-----------------------------------------------
# Script: SF/www/account/change_pw.php
#
account_change_pw title_success Successfully Changed Password
--- 'a/site-content/fr_FR/LC_MESSAGES/tuleap-core.po'
+++ b/site-content/fr_FR/LC_MESSAGES/tuleap-core.po
@@ -10,7 +10,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-"X-Generator: Poedit 2.0.3\n"
+"X-Generator: Poedit 1.8.7.1\n"
#, php-format
msgid ""
@@ -86,6 +86,14 @@ msgid "Already used"
msgstr "Déjà utilisé"
msgid ""
+"An email has been sent to the new address. Follow the instructions in the "
+"email to complete the email change."
+msgstr ""
+"Un courrier électronique vient d'être envoyé à votre nouvelle adresse e-"
+"mail. Suivez les instructions fournies dans ce message pour confirmer "
+"définitivement le changement."
+
+msgid ""
"An error occured with your upload. Please try again or choose another image."
msgstr ""
"Une erreur est survenue lors de votre téléversement. Merci d'essayer à "
@@ -172,6 +180,17 @@ msgstr "Impossible de mettre à jour le
msgid "Categories"
msgstr "Catégories"
+msgid "Change email address"
+msgstr "Changer l'adresse e-mail"
+
+msgid ""
+"Changing your email address will require confirmation from your new email "
+"address, so that we can ensure we have a good email address on file."
+msgstr ""
+"Le changement d'adresse e-mail nécessite une confirmation depuis votre "
+"nouvelle adresse e-mail de façon à s'assurer que nous disposons d'une "
+"adresse valide."
+
msgid "Child projects"
msgstr "Projets enfants"
@@ -302,6 +321,15 @@ msgstr "Éditer les paramètres"
msgid "Edit widget"
msgstr "Éditer le widget"
+msgid "Email change complete"
+msgstr "Changement d'e-mail confirmé"
+
+msgid "Email change confirmation"
+msgstr "Confirmation de changement d'adresse e-mail"
+
+msgid "Email format invalid"
+msgstr "Le formal de l'e-mail n'est pas valide"
+
msgid "Emergency"
msgstr "Urgent"
@@ -473,6 +501,9 @@ msgstr "Barre de menu"
msgid "Nb members"
msgstr "Nb membres"
+msgid "New email address:"
+msgstr "Nouvelle adresse e-mail"
+
msgid "News"
msgstr "Annonces"
@@ -682,6 +713,9 @@ msgstr "Rechercher"
msgid "See permissions"
msgstr "Voir les permissions"
+msgid "Send confirmation to new address"
+msgstr "Envoyer la confirmation"
+
msgid "Service news is disabled for this project."
msgstr "Le service annonces est désactivé pour ce projet."
@@ -712,6 +746,14 @@ msgstr "Commencez par choisir un widget"
msgid "Style"
msgstr "Style"
+msgid ""
+"Submitting the form below will mail a confirmation URL to the new email "
+"address. Visiting this link will complete the email change."
+msgstr ""
+"La soumission de ce formulaire déclenchera l'envoi d'un e-mail à votre "
+"nouvelle adresse incluant un lien à visiter pour confirmer définitivement le "
+"changement."
+
msgid "System"
msgstr "Système"
@@ -752,6 +794,14 @@ msgid "The last project administrator ca
msgstr ""
"Il n'est pas possible de supprimer le dernier administrateur du projet."
+#, php-format
+msgid ""
+"The mail was not accepted for the delivery. Please contact the administrator "
+"at %s."
+msgstr ""
+"L'e-mail n'a pas pu être envoyé. Veuillez contacter les administrateurs à "
+"l'adresse %s."
+
msgid "The name is missing for creating a dashboard."
msgstr "Il manque le nom pour créer un tableau de bord."
@@ -822,6 +872,9 @@ msgstr ""
msgid "This group does not have any members yet."
msgstr "Ce groupe n'a pas encore de membres."
+msgid "This hash key exists more than once"
+msgstr "Cette clé de confirmation est présente plus d'une fois dans la base."
+
msgid "This is a system group, you cannot delete it."
msgstr "Ceci est un groupe système, vous ne pouvez pas le supprimer."
@@ -887,6 +940,9 @@ msgstr "Import outils de suivi v3"
msgid "Unable to fetch the latest activities of the project"
msgstr "Impossible de récupérer les dernières activités du projet"
+msgid "Unauthorized action for anonymous"
+msgstr "Cette action n'est pas autorisée pour les anonymes"
+
msgid "Unix name"
msgstr "Now unix"
@@ -947,6 +1003,9 @@ msgstr "Bienvenue à bord"
msgid "Welcome message and information for users"
msgstr "Message de bienvenue et informations générales pour les utilisateurs"
+msgid "Welcome, %s."
+msgstr "Bienvenue, %s"
+
msgid ""
"Why don't you start by editing your dashboard <br> and adding some widgets?"
msgstr ""
@@ -1013,6 +1072,11 @@ msgstr ""
"Vous êtes sur le point de supprimer le widget \"%s\". Cette action est "
"irréversible. Merci de confirmer cette suppression."
+msgid "You are not the user who asked for email change"
+msgstr ""
+"Vous n'etes pas l'utilisateur à l'origine de la demande de changement d'e-"
+"mail"
+
msgid ""
"You can delegate to this group several permissions. All the members of this\n"
" group will take advantage of these permissions."
@@ -1063,6 +1127,22 @@ msgstr ""
"Vous n’avez pas les droits pour mettre à jour des tableaux de bord du projet "
"\"%s\"."
+#, php-format
+msgid ""
+"You have requested a change of email address on %s.\n"
+"Please visit the following URL to complete the email change:\n"
+"\n"
+"%s\n"
+"\n"
+"-- The %s Team"
+msgstr ""
+"Vous avez demandé a changer votre adresse e-mail en %s.\n"
+"Merci de visiter le lien ci-dessous pour confirmer ce changement :\n"
+"\n"
+"%s\n"
+"\n"
+"-- L'équipe %s"
+
msgid "You must be a project admin to edit this widget."
msgstr ""
"Vous devez être administrateur du projet pour pouvoir éditer ce widget."
@@ -1084,12 +1164,25 @@ msgstr ""
"Vous devez supprimer l'utilisateur des administrateurs d'annonces avant de "
"pouvoir l'enlever des rédacteurs"
+msgid ""
+"Your email change is complete. Your new email address is <strong>%s</strong>."
+msgstr ""
+"Votre changement d'adresse e-mail est confirmé. Votre nouvelle adresse e-"
+"mail est <strong>%s</strong>"
+
msgid "Your history is empty"
msgstr "Votre historique est vide"
msgid "Your platform does not allow restricted users."
msgstr "Votre plateforme n'authorise pas les utilisateurs restreints"
+#, php-format
+msgid "[%s] Email change confirmation"
+msgstr "[%s] Confirmation de changement d'e-mail"
+
+msgid "back to home page"
+msgstr "Retour à la page d'accueil"
+
msgid "categories"
msgstr "catégories"
--- 'a/site-content/fr_FR/account/account.tab'
+++ b/site-content/fr_FR/account/account.tab
@@ -102,29 +102,6 @@ account_preferences html_format HTML
account_preferences text_format Texte
#
#-----------------------------------------------
-# Script: SF/www/account/change_email.php
-#
-account_change_email title Changer l'adresse e-mail
-account_change_email message <P>Le changement d'adresse e-mail nécessite une confirmation depuis votre nouvelle adresse e-mail de façon à s'assurer que nous disposons d'une adresse valide. <P>La soumission de ce formulaire déclenchera l'envoi d'un e-mail à votre nouvelle adresse incluant un lien à visiter pour confirmer définitivement le changement.
-account_change_email label_new Nouvelle adresse e-mail
-account_change_email send_new Envoyer la confirmation
-#
-#-----------------------------------------------
-# Script: SF/www/account/change_email-confirm.php
-#
-account_change_email-confirm message Vous avez demandé a changer votre adresse e-mail en $1.\nMerci de visiter le lien ci-dessous pour confirmer ce changement :\n\n$2\n\n-- L'équipe $1
-account_change_email-confirm title Confirmation de changement d'adresse e-mail
-account_change_email-confirm mailsent Un courrier électronique vient d'être envoyé à votre nouvelle adresse e-mail. Suivez les instructions fournies dans ce message pour confirmer définitivement le changement.
-#
-#-----------------------------------------------
-# Script: SF/www/account/change_email-complete.php
-#
-account_change_email-complete invalid_hash Clé de confirmation invalide.
-account_change_email-complete duplicate_hash Cette clé de confirmation est présente plus d'une fois dans la base.
-account_change_email-complete title Changement d'e-mail confirmé
-account_change_email-complete message Bienvenue, $1.<P>Votre changement d'adresse e-mail est confirmé. Votre nouvelle adresse e-mail est <B>$2</B>. Les courriers électroniques envoyés à $3, utilisateur $1 (compte $4) seront désormais envoyés à cette nouvelle adresse e-mail.
-#
-#-----------------------------------------------
# Script: SF/www/account/change_pw.php
#
account_change_pw title_success Mot de passe modifié avec succès
--- 'a/site-content/tuleap-core.pot'
+++ b/site-content/tuleap-core.pot
@@ -70,6 +70,11 @@ msgid "Already used"
msgstr ""
msgid ""
+"An email has been sent to the new address. Follow the instructions in the "
+"email to complete the email change."
+msgstr ""
+
+msgid ""
"An error occured with your upload. Please try again or choose another image."
msgstr ""
@@ -148,6 +153,14 @@ msgstr ""
msgid "Categories"
msgstr ""
+msgid "Change email address"
+msgstr ""
+
+msgid ""
+"Changing your email address will require confirmation from your new email "
+"address, so that we can ensure we have a good email address on file."
+msgstr ""
+
msgid "Child projects"
msgstr ""
@@ -276,6 +289,15 @@ msgstr ""
msgid "Edit widget"
msgstr ""
+msgid "Email change complete"
+msgstr ""
+
+msgid "Email change confirmation"
+msgstr ""
+
+msgid "Email format invalid"
+msgstr ""
+
msgid "Emergency"
msgstr ""
@@ -445,6 +467,9 @@ msgstr ""
msgid "Nb members"
msgstr ""
+msgid "New email address:"
+msgstr ""
+
msgid "News"
msgstr ""
@@ -647,6 +672,9 @@ msgstr ""
msgid "See permissions"
msgstr ""
+msgid "Send confirmation to new address"
+msgstr ""
+
msgid "Service news is disabled for this project."
msgstr ""
@@ -677,6 +705,11 @@ msgstr ""
msgid "Style"
msgstr ""
+msgid ""
+"Submitting the form below will mail a confirmation URL to the new email "
+"address. Visiting this link will complete the email change."
+msgstr ""
+
msgid "System"
msgstr ""
@@ -715,6 +748,12 @@ msgstr ""
msgid "The last project administrator cannot be removed."
msgstr ""
+#, php-format
+msgid ""
+"The mail was not accepted for the delivery. Please contact the administrator "
+"at %s."
+msgstr ""
+
msgid "The name is missing for creating a dashboard."
msgstr ""
@@ -777,6 +816,9 @@ msgstr ""
msgid "This group does not have any members yet."
msgstr ""
+msgid "This hash key exists more than once"
+msgstr ""
+
msgid "This is a system group, you cannot delete it."
msgstr ""
@@ -837,6 +879,9 @@ msgstr ""
msgid "Unable to fetch the latest activities of the project"
msgstr ""
+msgid "Unauthorized action for anonymous"
+msgstr ""
+
msgid "Unix name"
msgstr ""
@@ -895,6 +940,9 @@ msgstr ""
msgid "Welcome message and information for users"
msgstr ""
+msgid "Welcome, %s."
+msgstr ""
+
msgid ""
"Why don't you start by editing your dashboard <br> and adding some widgets?"
msgstr ""
@@ -945,6 +993,9 @@ msgid ""
" This action is irreversible. Please confirm this deletion."
msgstr ""
+msgid "You are not the user who asked for email change"
+msgstr ""
+
msgid ""
"You can delegate to this group several permissions. All the members of this\n"
" group will take advantage of these permissions."
@@ -983,6 +1034,16 @@ msgstr ""
msgid "You have not rights to update dashboards of the project \"%s\"."
msgstr ""
+#, php-format
+msgid ""
+"You have requested a change of email address on %s.\n"
+"Please visit the following URL to complete the email change:\n"
+"\n"
+"%s\n"
+"\n"
+"-- The %s Team"
+msgstr ""
+
msgid "You must be a project admin to edit this widget."
msgstr ""
@@ -999,12 +1060,23 @@ msgid ""
"him from writers."
msgstr ""
+msgid ""
+"Your email change is complete. Your new email address is <strong>%s</strong>."
+msgstr ""
+
msgid "Your history is empty"
msgstr ""
msgid "Your platform does not allow restricted users."
msgstr ""
+#, php-format
+msgid "[%s] Email change confirmation"
+msgstr ""
+
+msgid "back to home page"
+msgstr ""
+
msgid "categories"
msgstr ""
--- 'a/src/common/autoload.php'
+++ b/src/common/autoload.php
@@ -2,7 +2,7 @@
// @codingStandardsIgnoreFile
// @codeCoverageIgnoreStart
// this is an autogenerated file - do not edit
-function autoload5968920175c8826d1e7743c6dd8b7ecc($class) {
+function autoload98e39cb101b034b8e47fa5f904bbcbfb($class) {
static $classes = null;
if ($classes === null) {
$classes = array(
@@ -1083,6 +1083,9 @@ function autoload5968920175c8826d1e7743c
'tuleap\\trove\\trovecatrouter' => '/trove/TroveCatRouter.php',
'tuleap\\trovecat\\trovecatlinkdao' => '/trove/TroveCatLinkDao.php',
'tuleap\\uri\\urimodifier' => '/URI/URIModifier.php',
+ 'tuleap\\user\\account\\changepasswordconfirmpresenter' => '/user/Account/ChangePasswordConfirmPresenter.php',
+ 'tuleap\\user\\account\\changepasswordcontroller' => '/user/Account/ChangePasswordController.php',
+ 'tuleap\\user\\account\\changepasswordpresenter' => '/user/Account/ChangePasswordPresenter.php',
'tuleap\\user\\admin\\pendingprojectbuilder' => '/user/Admin/PendingProjectBuilder.php',
'tuleap\\user\\admin\\pendinguserpresenter' => '/user/Admin/PendingUserPresenter.php',
'tuleap\\user\\admin\\pendinguserscollectionpresenter' => '/user/Admin/PendingUsersCollectionPresenter.php',
@@ -1344,5 +1347,5 @@ function autoload5968920175c8826d1e7743c
require dirname(__FILE__) . $classes[$cn];
}
}
-spl_autoload_register('autoload5968920175c8826d1e7743c6dd8b7ecc');
+spl_autoload_register('autoload98e39cb101b034b8e47fa5f904bbcbfb');
// @codeCoverageIgnoreEnd
--- 'a/src/common/dao/UserDao.class.php'
+++ b/src/common/dao/UserDao.class.php
@@ -769,4 +769,14 @@ class UserDao extends DataAccessObject {
$sql = "UPDATE user SET confirm_hash = null WHERE confirm_hash=$confirm_hash";
return $this->update($sql);
}
+
+ public function setEmailChangeConfirm($user_id, $confirm_hash, $email_new)
+ {
+ $user_id = $this->da->escapeInt($user_id);
+ $confirm_hash = $this->da->quoteSmart($confirm_hash);
+ $email_new = $this->da->quoteSmart($email_new);
+
+ $sql = "UPDATE user SET confirm_hash=$confirm_hash, email_new=$email_new WHERE user_id=$user_id";
+ return $this->update($sql);
+ }
}
--- 'a/src/common/event/Event.class.php'
+++ b/src/common/event/Event.class.php
@@ -68,16 +68,6 @@ class Event {
const LIST_SSH_KEYS = 'list_ssh_keys';
/**
- * The user has just changed his email address.
- *
- * Parameters:
- * 'user_id' => User ID
- *
- * No expected results
- */
- const USER_EMAIL_CHANGED = 'user_email_changed';
-
- /**
* Force aliases database update.
*
* No Parameters.
--- 'a/src/common/system_event/SystemEventManager.class.php'
+++ b/src/common/system_event/SystemEventManager.class.php
@@ -38,7 +38,6 @@ class SystemEventManager {
$event_manager = $this->_getEventManager();
$events_to_listen = array(
Event::SYSTEM_CHECK,
- Event::USER_EMAIL_CHANGED,
Event::PROJECT_RENAME,
Event::USER_RENAME,
Event::COMPUTE_MD5SUM,
@@ -157,11 +156,6 @@ class SystemEventManager {
$this->concatParameters($params, array('project_path', 'file_id', 'old_path' )),
SystemEvent::PRIORITY_HIGH);
break;
- case Event::USER_EMAIL_CHANGED:
- $this->createEvent(SystemEvent::TYPE_USER_EMAIL_CHANGED,
- $params['user_id'],
- SystemEvent::PRIORITY_LOW);
- break;
case 'approve_pending_project':
$this->createEvent(SystemEvent::TYPE_PROJECT_CREATE,
$params['group_id'],
--- /dev/null
+++ b/src/common/user/Account/ChangePasswordController.php
@@ -0,0 +1,171 @@
+<?php
+/**
+ * Copyright (c) Enalean, 2018. All Rights Reserved.
+ *
+ * This file is a part of Tuleap.
+ *
+ * Tuleap is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Tuleap 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tuleap. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Tuleap\User\Account;
+
+use Tuleap\Layout\BaseLayout;
+
+class ChangePasswordController
+{
+ const URL = '/account/change_email.php';
+
+ /**
+ * @var \UserManager
+ */
+ private $user_manager;
+ /**
+ * @var \EventManager
+ */
+ private $event_manager;
+
+ public function __construct(\UserManager $user_manager, \EventManager $event_manager)
+ {
+ $this->user_manager = $user_manager;
+ $this->event_manager = $event_manager;
+ }
+
+ public function change(\HTTPRequest $request, BaseLayout $response)
+ {
+ $this->event_manager->processEvent('before_change_email', array());
+
+ $current_user = $request->getCurrentUser();
+ if ($current_user->isAnonymous()) {
+ $response->addFeedback(\Feedback::ERROR, _('Unauthorized action for anonymous'));
+ $response->redirect('/');
+ }
+
+ $response->header(['title' =>_('Change email address')]);
+
+ $presenter = new ChangePasswordPresenter(
+ new \CSRFSynchronizerToken(self::URL),
+ $current_user->getId()
+ );
+
+ $renderer = \TemplateRendererFactory::build()->getRenderer(__DIR__.'/../../../templates/user');
+ $renderer->renderToPage('change-email', $presenter);
+
+ $response->footer(array());
+ }
+
+ public function confirm(\HTTPRequest $request, BaseLayout $response)
+ {
+ $this->event_manager->processEvent('before_change_email-confirm', []);
+
+ $token = new \CSRFSynchronizerToken(self::URL);
+ $token->check();
+
+ $current_user = $request->getCurrentUser();
+ if ($current_user->isAnonymous()) {
+ $response->addFeedback(\Feedback::ERROR, _('Unauthorized action for anonymous'));
+ $response->redirect('/');
+ }
+
+ $new_mail = $request->getValidated('form_newemail', new \Valid_Email(), '');
+ if ($new_mail === '') {
+ $response->addFeedback(\Feedback::ERROR, _('Email format invalid'));
+ $response->redirect('/change_email.php');
+ }
+
+ $confirmation_hash = (new \RandomNumberGenerator())->getNumber();
+ $this->user_manager->setEmailChangeConfirm($current_user->getId(), $confirmation_hash, $new_mail);
+
+ $subject = sprintf(
+ _('[%s] Email change confirmation'),
+ \ForgeConfig::get('sys_name')
+ );
+ $message = sprintf(
+ _("You have requested a change of email address on %s.\nPlease visit the following URL to complete the email change:\n\n%s\n\n-- The %s Team"),
+ \ForgeConfig::get('sys_name'),
+ $request->getServerUrl().$this->getChangeCompleteUrl($confirmation_hash),
+ \ForgeConfig::get('sys_name')
+ );
+
+ $mail = new \Mail();
+ $mail->setTo($new_mail, true);
+ $mail->setSubject($subject);
+ $mail->setBody($message);
+ $mail->setFrom(\ForgeConfig::get('sys_noreply'));
+ if (! $mail->send()) {
+ $error_message = sprintf(_('The mail was not accepted for the delivery. Please contact the administrator at %s.'), \ForgeConfig::get('sys_email_admin'));
+ $response->addFeedback(\Feedback::ERROR, $error_message);
+ $response->redirect('/change_email.php');
+ }
+
+ $response->header(['title' => _('Email change confirmation')]);
+
+ $renderer = \TemplateRendererFactory::build()->getRenderer(__DIR__.'/../../../templates/user');
+ $renderer->renderToPage('change-email-confirm', []);
+
+ $response->footer([]);
+ }
+
+ public function complete(\HTTPRequest $request, BaseLayout $response)
+ {
+ $this->event_manager->processEvent('before_change_email-complete', []);
+
+ $current_user = $request->getCurrentUser();
+ if ($current_user->isAnonymous()) {
+ $url_redirect = new \URLRedirect($this->event_manager);
+ $return_to = $this->getChangeCompleteUrl($request->getValidated('confirm_hash', 'string', ''));
+ $response->redirect($url_redirect->makeReturnToUrl('/account/login.php', $return_to));
+ }
+
+ $user = $this->user_manager->getUserByConfirmHash(
+ $request->getValidated('confirm_hash', 'string', '')
+ );
+
+ if ($user === null) {
+ $response->addFeedback(\Feedback::ERROR, _('This hash key exists more than once'));
+ $response->redirect('/');
+ }
+
+ if ($user->getId() != $current_user->getId()) {
+ $response->addFeedback(\Feedback::ERROR, _('You are not the user who asked for email change'));
+ $response->redirect('/');
+ }
+
+ $old_email_user = clone $user;
+ $user->clearConfirmHash();
+ $user->setEmail($old_email_user->getEmailNew());
+ $user->setEmailNew($old_email_user->getEmail());
+
+ $this->user_manager->updateDb($user);
+
+
+ $response->header(['title' => _('Email change complete')]);
+
+ $renderer = \TemplateRendererFactory::build()->getRenderer(__DIR__.'/../../../templates/user');
+ $renderer->renderToPage(
+ 'change-email-complete',
+ [
+ 'realname' => $user->getRealName(),
+ 'email' => $user->getEmail(),
+ ]
+ );
+
+ $response->footer([]);
+ }
+
+ private function getChangeCompleteUrl($confirmation_hash)
+ {
+ return '/account/change_email-complete.php?confirm_hash='.$confirmation_hash;
+ }
+}
--- /dev/null
+++ b/src/common/user/Account/ChangePasswordPresenter.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Copyright (c) Enalean, 2018. All Rights Reserved.
+ *
+ * This file is a part of Tuleap.
+ *
+ * Tuleap is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Tuleap 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tuleap. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Tuleap\User\Account;
+
+class ChangePasswordPresenter
+{
+ /**
+ * @var int
+ */
+ public $user_id;
+ /**
+ * @var CSRFSynchronizerToken
+ */
+ public $csrf_token;
+
+ public function __construct(\CSRFSynchronizerToken $csrf_token, $user_id)
+ {
+ $this->csrf_token = $csrf_token;
+ $this->user_id = $user_id;
+ }
+}
--- 'a/src/common/user/UserManager.class.php'
+++ b/src/common/user/UserManager.class.php
@@ -1006,4 +1006,9 @@ class UserManager {
$dao = $this->getDao();
$dao->removeConfirmHash($confirm_hash);
}
+
+ public function setEmailChangeConfirm($user_id, $confirm_hash, $email_new)
+ {
+ return $this->getDao()->setEmailChangeConfirm($user_id, $confirm_hash, $email_new);
+ }
}
--- /dev/null
+++ b/src/templates/user/change-email-complete.mustache
@@ -0,0 +1,9 @@
+<h2>{{# gettext }}Email change complete{{/ gettext}}</h2>
+
+<p>{{# gettext }}Welcome, %s.| {{ realname }}{{/ gettext }}</p>
+
+<p>{{# gettext }}Your email change is complete. Your new email address is <strong>%s</strong>. | {{ email }}{{/ gettext}}</p>
+
+<p>
+ <a href="/">{{# gettext }}back to home page{{/ gettext }}</a>
+</p>
--- /dev/null
+++ b/src/templates/user/change-email-confirm.mustache
@@ -0,0 +1,7 @@
+<h2>{{# gettext }}Email change confirmation{{/ gettext}}</h2>
+
+<p>{{# gettext }}An email has been sent to the new address. Follow the instructions in the email to complete the email change.{{/ gettext}}</p>
+
+<p>
+ <a href="/">{{# gettext }}back to home page{{/ gettext }}</a>
+</p>
--- /dev/null
+++ b/src/templates/user/change-email.mustache
@@ -0,0 +1,17 @@
+<h2>{{# gettext }}Change email address{{/ gettext}}</h2>
+
+<p>{{# gettext }}Changing your email address will require confirmation from your new email address, so that we can ensure we have a good email address on file.{{/ gettext }}</p>
+
+<p>{{# gettext }}Submitting the form below will mail a confirmation URL to the new email address. Visiting this link will complete the email change.{{/ gettext }}</p>
+
+<form action="change_email-confirm.php" method="post" class="form-inline">
+ {{# csrf_token }}
+ {{> csrf_token_input }}
+ {{/ csrf_token }}
+ {{# gettext }}New email address:{{/ gettext }} <input type="text" size="30" name="form_newemail" />
+ <input class="btn btn-primary" type="submit" name="Send Confirmation to New Address" value="{{# gettext }}Send confirmation to new address{{/ gettext }}">
+</form>
+
+<p>
+ <a href="/">{{# gettext }}back to home page{{/ gettext }}</a>
+</p>
--- 'a/src/www/account/change_email-complete.php'
+++ b/src/www/account/change_email-complete.php
@@ -1,6 +1,6 @@
<?php
-/* SourceForge: Breaking Down the Barriers to Open Source Development
- * Copyright (c) Enalean, 2015. All Rights Reserved.
+/**
+ * Copyright (c) Enalean, 2018. All rights reserved
*
* This file is a part of Tuleap.
*
@@ -11,50 +11,14 @@
*
* Tuleap 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
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with Tuleap. If not, see <http://www.gnu.org/licenses/>.
+ * along with Tuleap. If not, see <http://www.gnu.org/licenses/
*/
-require_once('pre.php');
+require_once 'pre.php';
-$em = EventManager::instance();
-$em->processEvent('before_change_email-complete', array());
-
-$hp = Codendi_HTMLPurifier::instance();
-$request = HTTPRequest::instance();
-$user_manager = UserManager::instance();
-
-
-/** @var PFUser */
-$user = $user_manager->getUserByConfirmHash($request->getValidated('confirm_hash', 'string', ''));
-
-if ($user === null) {
- $GLOBALS['Response']->addFeedback(Feedback::ERROR, $Language->getText('account_change_email-complete', 'duplicate_hash'));
- $GLOBALS['Response']->redirect('/');
-}
-
-$old_email_user = clone $user;
-$user->clearConfirmHash();
-$user->setEmail($old_email_user->getEmailNew());
-$user->setEmailNew($old_email_user->getEmail());
-
-$user_manager->updateDb($user);
-
-$em->processEvent(Event::USER_EMAIL_CHANGED, $user->getId());
-
-$HTML->header(array('title'=>$Language->getText('account_change_email-complete', 'title')));
-?>
-<p><b><?php echo $Language->getText('account_change_email-complete', 'title'); ?></b>
-<P><?php echo $Language->getText('account_change_email-complete', 'message',
- array( $hp->purify($user->getRealname(), CODENDI_PURIFIER_CONVERT_HTML) , $user->getEmail(),
- $GLOBALS['sys_name'], $user->getUsername())); ?>
-
-<P><A href="/">[ <?php echo $Language->getText('global', 'back_home'); ?> ]</A>
-
-<?php
-$HTML->footer(array());
-
-?>
+$controller = new \Tuleap\User\Account\ChangePasswordController(UserManager::instance(), EventManager::instance());
+$controller->complete(HTTPRequest::instance(), $GLOBALS['Response']);
--- 'a/src/www/account/change_email-confirm.php'
+++ b/src/www/account/change_email-confirm.php
@@ -1,58 +1,24 @@
<?php
-//
-// SourceForge: Breaking Down the Barriers to Open Source Development
-// Copyright 1999-2000 (c) The SourceForge Crew
-// http://sourceforge.net
-//
-//
+/**
+ * Copyright (c) Enalean, 2018. All rights reserved
+ *
+ * This file is a part of Tuleap.
+ *
+ * Tuleap is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Tuleap 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tuleap. If not, see <http://www.gnu.org/licenses/
+ */
-require_once('pre.php');
-require_once('common/mail/Mail.class.php');
-require_once('common/event/EventManager.class.php');
+require_once 'pre.php';
-
-$em =& EventManager::instance();
-$em->processEvent('before_change_email-confirm', array());
-
-$request =& HTTPRequest::instance();
-
-$confirm_hash = substr(md5($GLOBALS['session_hash'] . time()),0,16);
-
-$res_user = db_query("SELECT * FROM user WHERE user_id=".user_getid());
-if (db_numrows($res_user) < 1) exit_error("Invalid User","That user does not exist.");
-$row_user = db_fetch_array($res_user);
-
-$mail_is_sent = false;
-
-$form_newemail = $request->get('form_newemail');
-if(validate_email($form_newemail)) {
-
- db_query("UPDATE user SET confirm_hash='".$confirm_hash."',email_new='".db_es($form_newemail)."' "
- . "WHERE user_id=".$row_user['user_id']);
-
- $message = stripcslashes($Language->getText('account_change_email-confirm', 'message', array($GLOBALS['sys_name'], get_server_url()."/account/change_email-complete.php?confirm_hash=".$confirm_hash)));
-
- $mail = new Mail();
- $mail->setTo($form_newemail,true);
- $mail->setSubject($GLOBALS['sys_name'].': '.$Language->getText('account_change_email-confirm', 'title'));
- $mail->setBody($message);
- $mail->setFrom($GLOBALS['sys_noreply']);
- $mail_is_sent = $mail->send();
- if (!$mail_is_sent) {
- $GLOBALS['Response']->addFeedback('error', $GLOBALS['Language']->getText('global', 'mail_failed', array($GLOBALS['sys_email_admin'])));
- }
-} else {
- $GLOBALS['Response']->addFeedback('error', $GLOBALS['Language']->getText('include_utils', 'invalid_email'));
-}
-site_header(array('title'=>$Language->getText('account_change_email-confirm', 'title'))); ?>
-
-<P><B><?php if ($mail_is_sent) { echo $Language->getText('account_change_email-confirm', 'title'); ?></B>
-
-<P><?php echo $Language->getText('account_change_email-confirm', 'mailsent'); ?>.
-
-<?php
-}
-echo '<p><a href="/">['. $Language->getText('global', 'back_home'). ']</a></p>';
-site_footer(array());
-
-?>
+$controller = new \Tuleap\User\Account\ChangePasswordController(UserManager::instance(), EventManager::instance());
+$controller->confirm(HTTPRequest::instance(), $GLOBALS['Response']);
--- 'a/src/www/account/change_email.php'
+++ b/src/www/account/change_email.php
@@ -1,42 +1,24 @@
<?php
-//
-// SourceForge: Breaking Down the Barriers to Open Source Development
-// Copyright 1999-2000 (c) The SourceForge Crew
-// http://sourceforge.net
-//
-//
+/**
+ * Copyright (c) Enalean, 2018. All rights reserved
+ *
+ * This file is a part of Tuleap.
+ *
+ * Tuleap is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Tuleap 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tuleap. If not, see <http://www.gnu.org/licenses/
+ */
-require_once('pre.php');
-require_once('common/event/EventManager.class.php');
+require_once 'pre.php';
-$em =& EventManager::instance();
-$em->processEvent('before_change_email', array());
-
-session_require(array('isloggedin'=>1));
-
-
-$HTML->header(array('title'=> $Language->getText('account_change_email', 'title')));
-$csrf = new CSRFSynchronizerToken('/account/change_email.php');
-?>
-
-<h2><?php echo $Language->getText('account_change_email', 'title'); ?></h2>
-
-<?php echo $Language->getText('account_change_email', 'message'); ?>
-
-<FORM action="change_email-confirm.php" method="post" class="form-inline">
-<?php
-echo $csrf->fetchHTMLInput();
-?>
-<INPUT type="hidden" name="form_user" value="<?php print user_getid(); ?>">
-<BR>
-<?php echo $Language->getText('account_change_email', 'label_new'); ?>:
-<INPUT type="text" size="30" name="form_newemail">
-<INPUT class="btn btn-primary" type="submit" name="Send Confirmation to New Address" value="<?php echo $Language->getText('account_change_email', 'send_new'); ?>">
-</FORM>
-
-<A href="/">[<?php echo $Language->getText('global', 'back_home'); ?>]</A>
-
-<?php
-$HTML->footer(array());
-
-?>
+$controller = new \Tuleap\User\Account\ChangePasswordController(UserManager::instance(), EventManager::instance());
+$controller->change(HTTPRequest::instance(), $GLOBALS['Response']);
--- 'a/src/www/project/admin/editgenericmember.php'
+++ b/src/www/project/admin/editgenericmember.php
@@ -86,7 +86,7 @@ echo '<input type="hidden" name="group_i
'. $generic_user->getRealName() .'
</p>
<p>
- <label for="generic_user_email"><b>'. $Language->getText('account_change_email', 'title') .'</b>:</label><br />
+ <label for="generic_user_email"><b>'. _('Change email address') .'</b>:</label><br />
<input type="email" name="email" id="generic_user_email" value="'.
$hp->purify($generic_user->getEmail(), CODENDI_PURIFIER_CONVERT_HTML) .'" />
</p>