diff options
author | Marc Alexander <admin@m-a-styles.de> | 2019-08-10 15:09:35 +0200 |
---|---|---|
committer | Marc Alexander <admin@m-a-styles.de> | 2019-08-10 15:09:35 +0200 |
commit | e991df195baa75cc2bb36a34621eb8aea1f9f9e7 (patch) | |
tree | abd25016a629b5b29a0df5432900544d8f29d8f1 /phpBB/phpbb/ucp | |
parent | 1d1d963c14d9db54df69469758163f1f50a9b4b3 (diff) | |
download | forums-e991df195baa75cc2bb36a34621eb8aea1f9f9e7.tar forums-e991df195baa75cc2bb36a34621eb8aea1f9f9e7.tar.gz forums-e991df195baa75cc2bb36a34621eb8aea1f9f9e7.tar.bz2 forums-e991df195baa75cc2bb36a34621eb8aea1f9f9e7.tar.xz forums-e991df195baa75cc2bb36a34621eb8aea1f9f9e7.zip |
[ticket/11327] Continue with implementation of password reset functionality
PHPBB3-11327
Diffstat (limited to 'phpBB/phpbb/ucp')
-rw-r--r-- | phpBB/phpbb/ucp/controller/reset_password.php | 255 |
1 files changed, 133 insertions, 122 deletions
diff --git a/phpBB/phpbb/ucp/controller/reset_password.php b/phpBB/phpbb/ucp/controller/reset_password.php index 4b2660aebb..3d34c4740b 100644 --- a/phpBB/phpbb/ucp/controller/reset_password.php +++ b/phpBB/phpbb/ucp/controller/reset_password.php @@ -22,6 +22,7 @@ use phpbb\passwords\manager; use phpbb\request\request_interface; use phpbb\template\template; use phpbb\user; +use Symfony\Component\HttpFoundation\Response; /** * ucp_remind @@ -94,18 +95,32 @@ class reset_password $this->request = $request; $this->template = $template; $this->user = $user; + $this->tables = $tables; $this->root_path = $root_path; $this->php_ext = $php_ext; } - public function request() + /** + * Init controller + */ + protected function init_controller() { $this->language->add_lang('ucp'); if (!$this->config['allow_password_reset']) { - trigger_error($this->language->lang('UCP_PASSWORD_RESET_DISABLED', '<a href="mailto:' . htmlspecialchars($this->config['board_contact']) . '">', '</a>')); + $this->helper->message($this->language->lang('UCP_PASSWORD_RESET_DISABLED', '<a href="mailto:' . htmlspecialchars($this->config['board_contact']) . '">', '</a>')); } + } + + /** + * Handle password reset request + * + * @return Response + */ + public function request() + { + $this->init_controller(); $submit = $this->request->is_set_post('submit'); $username = $this->request->variable('username', '', true); @@ -125,13 +140,13 @@ class reset_password trigger_error('NO_EMAIL_USER'); } - $sql_array = array( + $sql_array = [ 'SELECT' => 'user_id, username, user_permissions, user_email, user_jabber, user_notify_type, user_type,' . ' user_lang, user_inactive_reason, reset_token, reset_token_expiration', - 'FROM' => array(USERS_TABLE => 'u'), + 'FROM' => [$this->tables['users'] => 'u'], 'WHERE' => "user_email_hash = '" . $this->db->sql_escape(phpbb_email_hash($email)) . "'" . (!empty($username) ? " AND username_clean = '" . $this->db->sql_escape(utf8_clean_string($username)) . "'" : ''), - ); + ]; /** * Change SQL query for fetching user data @@ -141,12 +156,13 @@ class reset_password * @var string username User's username from the form * @var array sql_array Fully assembled SQL query with keys SELECT, FROM, WHERE * @since 3.1.11-RC1 + * @changed 3.3.0-b1 Moved to reset password controller */ - $vars = array( + $vars = [ 'email', 'username', 'sql_array', - ); + ]; extract($this->dispatcher->trigger_event('core.ucp_remind_modify_select_sql', compact($vars))); $sql = $this->db->sql_build_query('SELECT', $sql_array); @@ -157,10 +173,10 @@ class reset_password { $this->db->sql_freeresult($result); - $this->template->assign_vars(array( + $this->template->assign_vars([ 'USERNAME_REQUIRED' => true, 'EMAIL' => $email, - )); + ]); } else { @@ -194,15 +210,13 @@ class reset_password trigger_error($message); } - $server_url = generate_board_url(); - // Generate reset token - $reset_token = gen_rand_string_friendly(32); + $reset_token = strtolower(gen_rand_string(32)); - $sql_ary = array( + $sql_ary = [ 'reset_token' => $reset_token, 'reset_token_expiration' => time() + $this->config['reset_token_lifetime'], - ); + ]; $sql = 'UPDATE ' . $this->tables['users'] . ' SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' @@ -214,16 +228,19 @@ class reset_password /** @var \messenger $messenger */ $messenger = new \messenger(false); - $messenger->template('user_activate_passwd', $user_row['user_lang']); + $messenger->template('user_forgot_password', $user_row['user_lang']); $messenger->set_addresses($user_row); $messenger->anti_abuse_headers($this->config, $this->user); - $messenger->assign_vars(array( + $messenger->assign_vars([ 'USERNAME' => htmlspecialchars_decode($user_row['username']), - 'U_RESET_PASSWORD' => $this->helper->route('phpbb_ucp_reset_password_controller') - )); + 'U_RESET_PASSWORD' => generate_board_url(true) . $this->helper->route('phpbb_ucp_reset_password_controller', [ + 'u' => $user_row['user_id'], + 'token' => $reset_token, + ], false) + ]); $messenger->send($user_row['user_notify_type']); @@ -231,11 +248,11 @@ class reset_password } } - $this->template->assign_vars(array( + $this->template->assign_vars([ 'USERNAME' => $username, 'EMAIL' => $email, 'S_PROFILE_ACTION' => $this->helper->route('phpbb_ucp_forgot_password_controller'), - )); + ]); return $this->helper->render('ucp_remind.html', $this->language->lang('UCP_REMIND')); } @@ -243,25 +260,73 @@ class reset_password /** * Handle controller requests * - * @return \Symfony\Component\HttpFoundation\Response + * @return Response */ public function reset() { - $this->language->add_lang('ucp'); + $this->init_controller(); - if (!$this->config['allow_password_reset']) + $submit = $this->request->is_set_post('submit'); + $reset_token = $this->request->variable('token', ''); + $user_id = $this->request->variable('u', 0); + + if (empty($reset_token)) { - trigger_error($this->language->lang('UCP_PASSWORD_RESET_DISABLED', '<a href="mailto:' . htmlspecialchars($this->config['board_contact']) . '">', '</a>')); + $this->helper->message('NO_RESET_TOKEN'); } - $submit = $this->request->is_set_post('submit'); - $username = $this->request->variable('username', '', true); - $email = strtolower($this->request->variable('email', '')); - $key = $this->request->variable('key', ''); - $user_id = $this->request->variable('user_id', 0); + if (!$user_id) + { + $this->helper->message('NO_USER'); + } add_form_key('ucp_remind'); + $sql_array = [ + 'SELECT' => 'user_id, username, user_permissions, user_email, user_jabber, user_notify_type, user_type,' + . ' user_lang, user_inactive_reason, reset_token, reset_token_expiration', + 'FROM' => [$this->tables['users'] => 'u'], + 'WHERE' => 'user_id = ' . $user_id, + ]; + + /** + * Change SQL query for fetching user data + * + * @event core.ucp_reset_password_modify_select_sql + * @var int user_id User ID from the form + * @var string reset_token Reset token + * @var array sql_array Fully assembled SQL query with keys SELECT, FROM, WHERE + * @since 3.3.0-b1 + */ + $vars = [ + 'user_id', + 'reset_token', + 'sql_array', + ]; + extract($this->dispatcher->trigger_event('core.ucp_reset_password_modify_select_sql', compact($vars))); + + $sql = $this->db->sql_build_query('SELECT', $sql_array); + $result = $this->db->sql_query_limit($sql, 1); + $user_row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $message = $this->language->lang('RESET_TOKEN_EXPIRED_OR_INVALID') . '<br /><br />' . $this->language->lang('RETURN_INDEX', '<a href="' . append_sid("{$this->root_path}index.{$this->php_ext}") . '">', '</a>'); + + if (empty($user_row)) + { + $this->helper->message($message); + } + + if (!hash_equals($reset_token, $user_row['reset_token'])) + { + $this->helper->message($message); + } + + if ($user_row['reset_token_expiration'] < time()) + { + $this->helper->message($message); + } + if ($submit) { if (!check_form_key('ucp_remind')) @@ -269,119 +334,65 @@ class reset_password trigger_error('FORM_INVALID'); } - if (empty($email)) + $message = $this->language->lang('PASSWORD_UPDATED_IF_EXISTED') . '<br /><br />' . $this->language->lang('RETURN_INDEX', '<a href="' . append_sid("{$this->root_path}index.{$this->php_ext}") . '">', '</a>'); + + if ($user_row['user_type'] == USER_IGNORE || $user_row['user_type'] == USER_INACTIVE) { - trigger_error('NO_EMAIL_USER'); + trigger_error($message); } - $sql_array = array( - 'SELECT' => 'user_id, username, user_permissions, user_email, user_jabber, user_notify_type, user_type, user_lang, user_inactive_reason', - 'FROM' => array(USERS_TABLE => 'u'), - 'WHERE' => "user_email_hash = '" . $this->db->sql_escape(phpbb_email_hash($email)) . "'" . - (!empty($username) ? " AND username_clean = '" . $this->db->sql_escape(utf8_clean_string($username)) . "'" : ''), - ); - - /** - * Change SQL query for fetching user data - * - * @event core.ucp_remind_modify_select_sql - * @var string email User's email from the form - * @var string username User's username from the form - * @var array sql_array Fully assembled SQL query with keys SELECT, FROM, WHERE - * @since 3.1.11-RC1 - */ - $vars = array( - 'email', - 'username', - 'sql_array', - ); - extract($this->dispatcher->trigger_event('core.ucp_remind_modify_select_sql', compact($vars))); - - $sql = $this->db->sql_build_query('SELECT', $sql_array); - $result = $this->db->sql_query_limit($sql, 2); // don't waste resources on more rows than we need - $rowset = $this->db->sql_fetchrowset($result); + // Check users permissions + $auth2 = new \phpbb\auth\auth(); + $auth2->acl($user_row); - if (count($rowset) > 1) + if (!$auth2->acl_get('u_chgpasswd')) { - $this->db->sql_freeresult($result); - - $this->template->assign_vars(array( - 'USERNAME_REQUIRED' => true, - 'EMAIL' => $email, - )); + trigger_error($message); } - else - { - $message = $this->language->lang('PASSWORD_UPDATED_IF_EXISTED') . '<br /><br />' . $this->language->lang('RETURN_INDEX', '<a href="' . append_sid("{$this->root_path}index.{$this->php_ext}") . '">', '</a>'); - if (empty($rowset)) - { - trigger_error($message); - } + $server_url = generate_board_url(); - $user_row = $rowset[0]; - $this->db->sql_freeresult($result); + // Make password at least 8 characters long, make it longer if admin wants to. + // gen_rand_string() however has a limit of 12 or 13. + $user_password = gen_rand_string_friendly(max(8, mt_rand((int) $this->config['min_pass_chars'], (int) $this->config['max_pass_chars']))); - if (!$user_row) - { - trigger_error($message); - } + // For the activation key a random length between 6 and 10 will do. + $user_actkey = gen_rand_string(mt_rand(6, 10)); - if ($user_row['user_type'] == USER_IGNORE || $user_row['user_type'] == USER_INACTIVE) - { - trigger_error($message); - } + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_newpasswd = '" . $this->db->sql_escape($this->passwords_manager->hash($user_password)) . "', user_actkey = '" . $this->db->sql_escape($user_actkey) . "' + WHERE user_id = " . $user_row['user_id']; + $this->db->sql_query($sql); - // Check users permissions - $auth2 = new \phpbb\auth\auth(); - $auth2->acl($user_row); + include_once($this->root_path . 'includes/functions_messenger.' . $this->php_ext); - if (!$auth2->acl_get('u_chgpasswd')) - { - trigger_error($message); - } + $messenger = new messenger(false); - $server_url = generate_board_url(); + $messenger->template('user_activate_passwd', $user_row['user_lang']); - // Make password at least 8 characters long, make it longer if admin wants to. - // gen_rand_string() however has a limit of 12 or 13. - $user_password = gen_rand_string_friendly(max(8, mt_rand((int) $this->config['min_pass_chars'], (int) $this->config['max_pass_chars']))); + $messenger->set_addresses($user_row); - // For the activation key a random length between 6 and 10 will do. - $user_actkey = gen_rand_string(mt_rand(6, 10)); + $messenger->anti_abuse_headers($this->config, $this->user); - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_newpasswd = '" . $this->db->sql_escape($this->passwords_manager->hash($user_password)) . "', user_actkey = '" . $this->db->sql_escape($user_actkey) . "' - WHERE user_id = " . $user_row['user_id']; - $this->db->sql_query($sql); - - include_once($this->root_path . 'includes/functions_messenger.' . $this->php_ext); + $messenger->assign_vars([ + 'USERNAME' => htmlspecialchars_decode($user_row['username']), + 'PASSWORD' => htmlspecialchars_decode($user_password), + 'U_ACTIVATE' => "$server_url/ucp.{$this->php_ext}?mode=activate&u={$user_row['user_id']}&k=$user_actkey" + ]); - $messenger = new messenger(false); + $messenger->send($user_row['user_notify_type']); - $messenger->template('user_activate_passwd', $user_row['user_lang']); - - $messenger->set_addresses($user_row); - - $messenger->anti_abuse_headers($this->config, $this->user); - - $messenger->assign_vars(array( - 'USERNAME' => htmlspecialchars_decode($user_row['username']), - 'PASSWORD' => htmlspecialchars_decode($user_password), - 'U_ACTIVATE' => "$server_url/ucp.{$this->php_ext}?mode=activate&u={$user_row['user_id']}&k=$user_actkey") - ); - - $messenger->send($user_row['user_notify_type']); - - trigger_error($message); - } + trigger_error($message); } - $this->template->assign_vars(array( - 'USERNAME' => $username, - 'EMAIL' => $email, - 'S_PROFILE_ACTION' => $this->helper->route('phpbb_ucp_reset_password_controller'), - )); + $this->template->assign_vars([ + 'S_IS_PASSWORD_RESET' => true, + 'S_PROFILE_ACTION' => $this->helper->route('phpbb_ucp_reset_password_controller'), + 'S_HIDDEN_FIELDS' => build_hidden_fields([ + 'u' => $user_id, + 'token' => $reset_token, + ]), + ]); return $this->helper->render('ucp_remind.html', $this->language->lang('UCP_REMIND')); } |