diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md index ccc5b146f2..d58cb07477 100644 --- a/phpBB/docs/events.md +++ b/phpBB/docs/events.md @@ -2730,6 +2730,62 @@ ucp_prefs_view_select_menu_prepend * Purpose: Add options to the top of the drop-down lists block of the Edit Display Options screen +ucp_profile_autologin_keys_tbody_key_after +=== +* Locations: + + styles/prosilver/template/ucp_profile_autologin_keys.html +* Since: 3.3.2-RC1 +* Purpose: Add table column after the first column. + +ucp_profile_autologin_keys_tbody_key_before +=== +* Locations: + + styles/prosilver/template/ucp_profile_autologin_keys.html +* Since: 3.3.2-RC1 +* Purpose: Add table column before the first column. + +ucp_profile_autologin_keys_tbody_mark_after +=== +* Locations: + + styles/prosilver/template/ucp_profile_autologin_keys.html +* Since: 3.3.2-RC1 +* Purpose: Add table column after the last column. + +ucp_profile_autologin_keys_tbody_mark_before +=== +* Locations: + + styles/prosilver/template/ucp_profile_autologin_keys.html +* Since: 3.3.2-RC1 +* Purpose: Add table column before the last column. + +ucp_profile_autologin_keys_thead_key_after +=== +* Locations: + + styles/prosilver/template/ucp_profile_autologin_keys.html +* Since: 3.3.2-RC1 +* Purpose: Add table header content after the first column. + +ucp_profile_autologin_keys_thead_key_before +=== +* Locations: + + styles/prosilver/template/ucp_profile_autologin_keys.html +* Since: 3.3.2-RC1 +* Purpose: Add table header content before the first column. + +ucp_profile_autologin_keys_thead_mark_after +=== +* Locations: + + styles/prosilver/template/ucp_profile_autologin_keys.html +* Since: 3.3.2-RC1 +* Purpose: Add table header content after the last column. + +ucp_profile_autologin_keys_thead_mark_before +=== +* Locations: + + styles/prosilver/template/ucp_profile_autologin_keys.html +* Since: 3.3.2-RC1 +* Purpose: Add table header content before the last column. + ucp_profile_profile_info_after === * Locations: diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index dca7e7eeb7..53a042f173 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -810,23 +810,50 @@ class ucp_profile $error = array_map(array($user, 'lang'), $error); } - $sql = 'SELECT key_id, last_ip, last_login - FROM ' . SESSIONS_KEYS_TABLE . ' - WHERE user_id = ' . (int) $user->data['user_id'] . ' - ORDER BY last_login ASC'; + $sql_ary = [ + 'SELECT' => 'sk.key_id, sk.last_ip, sk.last_login', + 'FROM' => [SESSIONS_KEYS_TABLE => 'sk'], + 'WHERE' => 'sk.user_id = ' . (int) $user->data['user_id'], + 'ORDER_BY' => 'sk.last_login ASC', + ]; - $result = $db->sql_query($sql); + /** + * Event allows changing SQL query for autologin keys + * + * @event core.ucp_profile_autologin_keys_sql + * @var array sql_ary Array with autologin keys SQL query + * @since 3.3.2-RC1 + */ + $vars = ['sql_ary']; + extract($phpbb_dispatcher->trigger_event('core.ucp_profile_autologin_keys_sql', compact($vars))); - while ($row = $db->sql_fetchrow($result)) + $result = $db->sql_query($db->sql_build_query('SELECT', $sql_ary)); + $sessions = (array) $db->sql_fetchrowset($result); + $db->sql_freeresult($result); + + $template_vars = []; + foreach ($sessions as $row) { - $template->assign_block_vars('sessions', array( - 'KEY' => substr($row['key_id'], 0, 8), + $key = substr($row['key_id'], 0, 8); + $template_vars[$key] = [ + 'KEY' => $key, 'IP' => $row['last_ip'], 'LOGIN_TIME' => $user->format_date($row['last_login']), - )); + ]; } - $db->sql_freeresult($result); + /** + * Event allows changing template variables + * + * @event core.ucp_profile_autologin_keys_template_vars + * @var array sessions Array with session keys data + * @var array template_vars Array with template variables + * @since 3.3.2-RC1 + */ + $vars = ['sessions', 'template_vars']; + extract($phpbb_dispatcher->trigger_event('core.ucp_profile_autologin_keys_template_vars', compact($vars))); + + $template->assign_block_vars_array('sessions', $template_vars); break; } diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index c6af4158a7..d15f72a289 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -1459,7 +1459,7 @@ class session */ function set_login_key($user_id = false, $key = false, $user_ip = false) { - global $db; + global $db, $phpbb_dispatcher; $user_id = ($user_id === false) ? $this->data['user_id'] : $user_id; $user_ip = ($user_ip === false) ? $this->ip : $user_ip; @@ -1491,6 +1491,29 @@ class session { $sql = 'INSERT INTO ' . SESSIONS_KEYS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); } + + /** + * Event to adjust autologin keys process + * + * @event core.set_login_key + * @var string|false key Current autologin key if exists, false otherwise + * @var string key_id New autologin key + * @var string sql SQL query to update/insert autologin key + * @var array sql_ary Aray with autologin key data + * @var int user_id Current user's ID + * @var string user_ip Current user's IP address + * @since 3.3.2-RC1 + */ + $vars = [ + 'key', + 'key_id', + 'sql', + 'sql_ary', + 'user_id', + 'user_ip', + ]; + extract($phpbb_dispatcher->trigger_event('core.set_login_key', compact($vars))); + $db->sql_query($sql); $this->cookie_data['k'] = $key_id; diff --git a/phpBB/styles/prosilver/template/ucp_profile_autologin_keys.html b/phpBB/styles/prosilver/template/ucp_profile_autologin_keys.html index 3f63c5b3c0..540f98c240 100644 --- a/phpBB/styles/prosilver/template/ucp_profile_autologin_keys.html +++ b/phpBB/styles/prosilver/template/ucp_profile_autologin_keys.html @@ -7,25 +7,34 @@

{L_PROFILE_AUTOLOGIN_KEYS}

{ERROR}

+ {% DEFINE COLSPAN = 4 %} + {% EVENT ucp_profile_autologin_keys_thead_key_before %} + {% EVENT ucp_profile_autologin_keys_thead_key_after %} + {% EVENT ucp_profile_autologin_keys_thead_mark_before %} + {% EVENT ucp_profile_autologin_keys_thead_mark_after %} + {% EVENT ucp_profile_autologin_keys_tbody_key_before %} + {% EVENT ucp_profile_autologin_keys_tbody_key_after %} + {% EVENT ucp_profile_autologin_keys_tbody_mark_before %} + {% EVENT ucp_profile_autologin_keys_tbody_mark_after %} - +
{L_LOGIN_KEY}{L_IP} {L_LOGIN_TIME}{L_MARK}
{sessions.IP} {sessions.LOGIN_TIME}
{L_PROFILE_NO_AUTOLOGIN_KEYS}
{L_PROFILE_NO_AUTOLOGIN_KEYS}
diff --git a/tests/functional/ucp_profile_test.php b/tests/functional/ucp_profile_test.php index 68263c11f7..10d3cb2da1 100644 --- a/tests/functional/ucp_profile_test.php +++ b/tests/functional/ucp_profile_test.php @@ -54,7 +54,7 @@ class phpbb_functional_ucp_profile_test extends phpbb_functional_test_case $this->assertContainsLang('UCP_PROFILE_PROFILE_INFO', $crawler->filter('#cp-main h2')->text()); $form = $crawler->selectButton('Submit')->form([ - 'pf_phpbb_location' => '😁', // grinning face with smiling eyes Emoji + 'pf_phpbb_location' => '😁', // grinning face with smiling eyes Emoji ]); $crawler = self::submit($form); $this->assertContainsLang('PROFILE_UPDATED', $crawler->filter('#message')->text()); @@ -63,4 +63,37 @@ class phpbb_functional_ucp_profile_test extends phpbb_functional_test_case $form = $crawler->selectButton('Submit')->form(); $this->assertEquals('😁', $form->get('pf_phpbb_location')->getValue()); } + + public function test_autologin_keys_manage() + { + $this->add_lang('ucp'); + $this->login('admin', true); + $db = $this->get_db(); + + $crawler = self::request('GET', 'ucp.php?i=ucp_profile&mode=autologin_keys'); + $this->assertContainsLang('UCP_PROFILE_AUTOLOGIN_KEYS', $crawler->filter('#cp-main h2')->text()); + + $profile_url = $crawler->filter('a[title="Profile"]')->attr('href'); + $user_id = $this->get_parameter_from_link($profile_url, 'u'); + + $sql_ary = [ + 'SELECT' => 'sk.key_id', + 'FROM' => [SESSIONS_KEYS_TABLE => 'sk'], + 'WHERE' => 'sk.user_id = ' . (int) $user_id, + 'ORDER_BY' => 'sk.last_login ASC', + ]; + $result = $db->sql_query_limit($db->sql_build_query('SELECT', $sql_ary), 1); + $key_id = substr($db->sql_fetchfield('key_id'), 0, 8); + $db->sql_freeresult($result); + + $this->assertContains($key_id, $crawler->filter('label[for="' . $key_id . '"]')->text()); + + $form = $crawler->selectButton('submit')->form(); + $form['keys'][0]->tick(); + $crawler = self::submit($form); + $this->assertContains($this->lang('AUTOLOGIN_SESSION_KEYS_DELETED'), $crawler->filter('html')->text()); + + $crawler = self::request('GET', 'ucp.php?i=ucp_profile&mode=autologin_keys'); + $this->assertContains($this->lang('PROFILE_NO_AUTOLOGIN_KEYS'), $crawler->filter('tbody > tr > td[class="bg1"]')->text()); + } } diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index 804426d1a4..87b69fc88e 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -788,7 +788,7 @@ class phpbb_functional_test_case extends phpbb_test_case return group_user_add($group_id, false, $usernames, $group_name, $default, $leader); } - protected function login($username = 'admin') + protected function login($username = 'admin', $autologin = false) { $this->add_lang('ucp'); @@ -796,6 +796,10 @@ class phpbb_functional_test_case extends phpbb_test_case $this->assertContains($this->lang('LOGIN_EXPLAIN_UCP'), $crawler->filter('html')->text()); $form = $crawler->selectButton($this->lang('LOGIN'))->form(); + if ($autologin) + { + $form['autologin']->tick(); + } $crawler = self::submit($form, array('username' => $username, 'password' => $username . $username)); $this->assertNotContains($this->lang('LOGIN'), $crawler->filter('.navbar')->text());