From 0c98f13eee10a61cabdc13e7aa75916d50b8b078 Mon Sep 17 00:00:00 2001 From: Philip Häusler Date: Thu, 26 Dec 2013 13:34:48 +0100 Subject: user password recovery --- includes/controller/users_controller.php | 84 +++++++++++++++++++++++++ includes/helper/email_helper.php | 16 +++++ includes/helper/internationalization_helper.php | 16 ++++- includes/model/User_model.php | 46 +++++++++++++- includes/pages/guest_login.php | 3 + includes/sys_auth.php | 2 +- includes/view/User_view.php | 66 +++++++++++++------ 7 files changed, 211 insertions(+), 22 deletions(-) create mode 100644 includes/controller/users_controller.php create mode 100644 includes/helper/email_helper.php (limited to 'includes') diff --git a/includes/controller/users_controller.php b/includes/controller/users_controller.php new file mode 100644 index 00000000..8e0aace7 --- /dev/null +++ b/includes/controller/users_controller.php @@ -0,0 +1,84 @@ += MIN_PASSWORD_LENGTH) { + if ($_REQUEST['password'] != $_REQUEST['password2']) { + $ok = false; + error(_("Your passwords don't match.")); + } + } else { + $ok = false; + error(_("Your password is to short (please use at least 6 characters).")); + } + + if ($ok) { + $result = set_password($user_source['UID'], $_REQUEST['password']); + if ($result === false) + engelsystem_error(_("Password could not be updated.")); + + success(_("Password saved.")); + redirect(page_link_to('login')); + } + } + + return User_password_set_view(); + } else { + if (isset($_REQUEST['submit'])) { + $ok = true; + + if (isset($_REQUEST['email']) && strlen(strip_request_item('email')) > 0) { + $email = strip_request_item('email'); + if (check_email($email)) { + $user_source = User_by_email($email); + if ($user_source === false) + engelsystem_error("Unable to load user."); + if ($user_source == null) { + $ok = false; + $msg .= error(_("E-mail address is not correct."), true); + } + } else { + $ok = false; + $msg .= error(_("E-mail address is not correct."), true); + } + } else { + $ok = false; + $msg .= error(_("Please enter your e-mail."), true); + } + + if ($ok) { + $token = User_generate_password_recovery_token($user_source); + if ($token === false) + engelsystem_error("Unable to generate password recovery token."); + $result = engelsystem_email_to_user($user_source, _("Password recovery"), sprintf(_("Please visit %s to recover your password."), page_link_to_absolute('user_password_recovery') . '&token=' . $token)); + if ($result === false) + engelsystem_error("Unable to send password recovery email."); + + success(_("We sent an email containing your password recovery link.")); + redirect(page_link_to('login')); + } + } + + return User_password_recovery_view(); + } +} + +function user_password_recovery_title() { + return _("Password recovery"); +} + +?> \ No newline at end of file diff --git a/includes/helper/email_helper.php b/includes/helper/email_helper.php new file mode 100644 index 00000000..98cfd0f3 --- /dev/null +++ b/includes/helper/email_helper.php @@ -0,0 +1,16 @@ +"); +} + +?> \ No newline at end of file diff --git a/includes/helper/internationalization_helper.php b/includes/helper/internationalization_helper.php index ae88eb21..db150fec 100644 --- a/includes/helper/internationalization_helper.php +++ b/includes/helper/internationalization_helper.php @@ -17,13 +17,25 @@ function gettext_init() { elseif (! isset($_SESSION['locale'])) $_SESSION['locale'] = $default_locale; - putenv('LC_ALL=' . $_SESSION['locale']); - setlocale(LC_ALL, $_SESSION['locale']); + gettext_locale(); bindtextdomain('default', '../locale'); bind_textdomain_codeset('default', 'UTF-8'); textdomain('default'); } +/** + * Swich gettext locale. + * + * @param string $locale + */ +function gettext_locale($locale = null) { + if ($locale == null) + $locale = $_SESSION['locale']; + + putenv('LC_ALL=' . $locale); + setlocale(LC_ALL, $locale); +} + /** * Renders language selection. * diff --git a/includes/model/User_model.php b/includes/model/User_model.php index 884aeae8..523685df 100644 --- a/includes/model/User_model.php +++ b/includes/model/User_model.php @@ -30,10 +30,40 @@ function User_by_api_key($api_key) { return $user[0]; } +/** + * Returns User by email. + * + * @param string $email + * @return Matching user, null or false on error + */ +function User_by_email($email) { + $user = sql_select("SELECT * FROM `User` WHERE `email`='" . sql_escape($email) . "' LIMIT 1"); + if ($user === false) + return false; + if (count($user) == 0) + return null; + return $user[0]; +} + +/** + * Returns User by password token. + * + * @param string $token + * @return Matching user, null or false on error + */ +function User_by_password_recovery_token($token) { + $user = sql_select("SELECT * FROM `User` WHERE `password_recovery_token`='" . sql_escape($token) . "' LIMIT 1"); + if ($user === false) + return false; + if (count($user) == 0) + return null; + return $user[0]; +} + /** * Generates a new api key for given user. * - * @param User $user + * @param User $user */ function User_reset_api_key(&$user) { $user['api_key'] = md5($user['Nick'] . time() . rand()); @@ -43,4 +73,18 @@ function User_reset_api_key(&$user) { engelsystem_log("API key resetted."); } +/** + * Generates a new password recovery token for given user. + * + * @param User $user + */ +function User_generate_password_recovery_token(&$user) { + $user['password_recovery_token'] = md5($user['Nick'] . time() . rand()); + $result = sql_query("UPDATE `User` SET `password_recovery_token`='" . sql_escape($user['password_recovery_token']) . "' WHERE `UID`='" . sql_escape($user['UID']) . "' LIMIT 1"); + if ($result === false) + return false; + engelsystem_log("Password recovery for " . $user['Nick'] . " started."); + return $user['password_recovery_token']; +} + ?> \ No newline at end of file diff --git a/includes/pages/guest_login.php b/includes/pages/guest_login.php index f072e411..605d32b1 100644 --- a/includes/pages/guest_login.php +++ b/includes/pages/guest_login.php @@ -216,6 +216,9 @@ function guest_login() { form_password('password', _("Password")), form_submit('submit', _("Login")) )), + buttons(array( + button(page_link_to('user_password_recovery'), _("I forgot my password")) + )), info(_("Please note: You have to activate cookies!"), true) )); } diff --git a/includes/sys_auth.php b/includes/sys_auth.php index 3902aea2..e9fa197d 100644 --- a/includes/sys_auth.php +++ b/includes/sys_auth.php @@ -30,7 +30,7 @@ function generate_salt($length = 16) { // set the password of a user function set_password($uid, $password) { - return sql_query("UPDATE `User` SET `Passwort` = '" . sql_escape(crypt($password, CRYPT_ALG . '$' . generate_salt(16) . '$')) . "' WHERE `UID` = " . intval($uid) . " LIMIT 1"); + return sql_query("UPDATE `User` SET `Passwort` = '" . sql_escape(crypt($password, CRYPT_ALG . '$' . generate_salt(16) . '$')) . "', `password_recovery_token`=NULL WHERE `UID` = " . intval($uid) . " LIMIT 1"); } // verify a password given a precomputed salt. diff --git a/includes/view/User_view.php b/includes/view/User_view.php index ef4f9831..eda29d58 100644 --- a/includes/view/User_view.php +++ b/includes/view/User_view.php @@ -3,25 +3,55 @@ /** * Available T-Shirt sizes */ -$tshirt_sizes = array ( - '' => _("Please select..."), - 'S' => "S", - 'M' => "M", - 'L' => "L", - 'XL' => "XL", - '2XL' => "2XL", - '3XL' => "3XL", - '4XL' => "4XL", - '5XL' => "5XL", - 'S-G' => "S Girl", - 'M-G' => "M Girl", - 'L-G' => "L Girl", - 'XL-G' => "XL Girl" +$tshirt_sizes = array( + '' => _("Please select..."), + 'S' => "S", + 'M' => "M", + 'L' => "L", + 'XL' => "XL", + '2XL' => "2XL", + '3XL' => "3XL", + '4XL' => "4XL", + '5XL' => "5XL", + 'S-G' => "S Girl", + 'M-G' => "M Girl", + 'L-G' => "L Girl", + 'XL-G' => "XL Girl" ); +/** + * View for password recovery step 1: E-Mail + */ +function User_password_recovery_view() { + return page(array( + msg(), + _("We will send you an e-mail with a password recovery link. Please use the email address you used for registration."), + form(array( + form_text('email', _("E-Mail"), ""), + form_submit('submit', _("Recover")) + )) + )); +} + +/** + * View for password recovery step 2: New password + */ +function User_password_set_view() { + return page(array( + msg(), + _("Please enter a new password."), + form(array( + form_password('password', _("Password")), + form_password('password2', _("Confirm password")), + form_submit('submit', _("Save")) + )) + )); +} + /** * Render a users avatar. - * @param User $user + * + * @param User $user * @return string */ function User_Avatar_render($user) { @@ -30,16 +60,16 @@ function User_Avatar_render($user) { /** * Render a user nickname. - * @param User $user_source + * + * @param User $user_source * @return string */ function User_Nick_render($user_source) { global $user, $privileges; - if($user['UID'] == $user_source['UID'] || in_array('user_shifts_admin', $privileges)) + if ($user['UID'] == $user_source['UID'] || in_array('user_shifts_admin', $privileges)) return '' . htmlspecialchars($user_source['Nick']) . ''; else return htmlspecialchars($user_source['Nick']); } - ?> \ No newline at end of file -- cgit v1.2.3-70-g09d2