From 8064168e3ca222a6515a093323e888e9f998da4c Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 18 Nov 2014 09:48:17 +1300 Subject: [PATCH] MDL-47803 Add report that lists user sessions --- lib/classes/plugin_manager.php | 3 +- report/usersessions/db/access.php | 43 +++++++++ report/usersessions/index.php | 28 ++++++ .../lang/en/report_usersessions.php | 30 ++++++ report/usersessions/lib.php | 52 +++++++++++ report/usersessions/locallib.php | 91 +++++++++++++++++++ .../tests/behat/usersessions_report.feature | 10 ++ report/usersessions/user.php | 88 ++++++++++++++++++ report/usersessions/version.php | 30 ++++++ 9 files changed, 374 insertions(+), 1 deletion(-) create mode 100644 report/usersessions/db/access.php create mode 100644 report/usersessions/index.php create mode 100644 report/usersessions/lang/en/report_usersessions.php create mode 100644 report/usersessions/lib.php create mode 100644 report/usersessions/locallib.php create mode 100644 report/usersessions/tests/behat/usersessions_report.feature create mode 100644 report/usersessions/user.php create mode 100644 report/usersessions/version.php diff --git a/lib/classes/plugin_manager.php b/lib/classes/plugin_manager.php index a6c409ea316..c75a0042307 100644 --- a/lib/classes/plugin_manager.php +++ b/lib/classes/plugin_manager.php @@ -1112,7 +1112,8 @@ class core_plugin_manager { 'report' => array( 'backups', 'completion', 'configlog', 'courseoverview', 'eventlist', - 'log', 'loglive', 'outline', 'participation', 'progress', 'questioninstances', 'security', 'stats', 'performance' + 'log', 'loglive', 'outline', 'participation', 'progress', 'questioninstances', 'security', 'stats', 'performance', + 'usersessions', ), 'repository' => array( diff --git a/report/usersessions/db/access.php b/report/usersessions/db/access.php new file mode 100644 index 00000000000..ac2bd56b63b --- /dev/null +++ b/report/usersessions/db/access.php @@ -0,0 +1,43 @@ +. + +/** + * Capabilities for this report. + * + * @package report_usersessions + * @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @author Petr Skoda + */ + +defined('MOODLE_INTERNAL') || die(); + +$capabilities = array( + + 'report/usersessions:manageownsessions' => array( + 'captype' => 'write', + 'contextlevel' => CONTEXT_USER, + 'archetypes' => array( + 'user' => CAP_ALLOW, + ), + + // NOTE: shared accounts usually do not allow changing + // of own passwords, this is not very accurate but safer. + 'clonepermissionsfrom' => 'moodle/user:changeownpassword' + ), +); + + diff --git a/report/usersessions/index.php b/report/usersessions/index.php new file mode 100644 index 00000000000..ff57fd3f22c --- /dev/null +++ b/report/usersessions/index.php @@ -0,0 +1,28 @@ +. + +/** + * Listing of all sessions for current user. + * + * @package report_usersessions + * @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @author Petr Skoda + */ + +require(__DIR__ . '/../../config.php'); + +redirect(new moodle_url('/report/usersessions/user.php')); diff --git a/report/usersessions/lang/en/report_usersessions.php b/report/usersessions/lang/en/report_usersessions.php new file mode 100644 index 00000000000..ebbaf93ead9 --- /dev/null +++ b/report/usersessions/lang/en/report_usersessions.php @@ -0,0 +1,30 @@ +. + +/** + * Lang strings. + * + * @package report_usersessions + * @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @author Petr Skoda + */ + +$string['navigationlink'] = 'Browser sessions'; +$string['mysessions'] = 'My active sessions'; +$string['pluginname'] = 'User sessions report'; +$string['thissession'] = 'Current session'; +$string['usersessions:manageownsessions'] = 'Manage own browser sessions'; diff --git a/report/usersessions/lib.php b/report/usersessions/lib.php new file mode 100644 index 00000000000..04c213587a5 --- /dev/null +++ b/report/usersessions/lib.php @@ -0,0 +1,52 @@ +. + +/** + * Lib API functions. + * + * @package report_usersessions + * @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @author Petr Skoda + */ + +defined('MOODLE_INTERNAL') || die; + +/** + * This function extends the course navigation with the report items + * + * @param navigation_node $navigation The navigation node to extend + * @param stdClass $user + * @param stdClass $course The course to object for the report + */ +function report_usersessions_extend_navigation_user($navigation, $user, $course) { + global $USER; + + if (isguestuser() or !isloggedin()) { + return; + } + + if (\core\session\manager::is_loggedinas() or $USER->id != $user->id) { + // No peeking at somebody else's sessions! + return; + } + + $context = context_user::instance($USER->id); + if (has_capability('report/usersessions:manageownsessions', $context)) { + $navigation->add(get_string('navigationlink', 'report_usersessions'), + new moodle_url('/report/usersessions/user.php'), $navigation::TYPE_SETTING); + } +} diff --git a/report/usersessions/locallib.php b/report/usersessions/locallib.php new file mode 100644 index 00000000000..02f6b5ae313 --- /dev/null +++ b/report/usersessions/locallib.php @@ -0,0 +1,91 @@ +. + +/** + * Lib API functions. + * + * @package report_usersessions + * @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @author Petr Skoda + */ + +defined('MOODLE_INTERNAL') || die; + +require_once(__DIR__ . '/lib.php'); + +/** + * Show user friendly duration since last activity. + * + * @param int $duration in seconds + * @return string + */ +function report_usersessions_format_duration($duration) { + + // NOTE: The session duration is not accurate thanks to + // $CFG->session_update_timemodified_frequency setting. + // Also there is no point in showing days here because + // the session cleanup should purge all stale sessions + // regularly. + + if ($duration < 60) { + return get_string('now'); + } + + if ($duration < 60 * 60 * 2) { + $minutes = (int)($duration / 60); + $ago = $minutes . ' ' . get_string('minutes'); + return get_string('ago', 'core_message', $ago); + } + + $hours = (int)($duration / (60 * 60)); + $ago = $hours . ' ' . get_string('hours'); + return get_string('ago', 'core_message', $ago); +} + +/** + * Show some user friendly IP address info. + * + * @param string $ip + * @return string + */ +function report_usersessions_format_ip($ip) { + if (strpos($ip, ':') !== false) { + // For now ipv6 is not supported yet. + return $ip; + } + $url = new moodle_url('/iplookup/index.php', array('ip' => $ip)); + return html_writer::link($url, $ip); +} + +/** + * Kill user session. + * + * @param int $id + * @return void + */ +function report_usersessions_kill_session($id) { + global $DB, $USER; + + $session = $DB->get_record('sessions', array('id' => $id, 'userid' => $USER->id), 'id, sid'); + + if (!$session or $session->sid === session_id()) { + // Do not delete the current session! + return; + } + + \core\session\manager::kill_session($session->sid); +} diff --git a/report/usersessions/tests/behat/usersessions_report.feature b/report/usersessions/tests/behat/usersessions_report.feature new file mode 100644 index 00000000000..01067725e89 --- /dev/null +++ b/report/usersessions/tests/behat/usersessions_report.feature @@ -0,0 +1,10 @@ +@report @report_usersessions +Feature: In a report, admin can see current sessions + In order see usersession data + As a admin + I need to view usersessions report and see if the current session is listed + + Scenario: Check usersessions report shows current session + Given I log in as "admin" + When I navigate to "Browser sessions" node in "My profile settings > Activity reports" + Then I should see "Current session" diff --git a/report/usersessions/user.php b/report/usersessions/user.php new file mode 100644 index 00000000000..7af5d936e9a --- /dev/null +++ b/report/usersessions/user.php @@ -0,0 +1,88 @@ +. + +/** + * Listing of all sessions for current user. + * + * @package report_usersessions + * @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @author Petr Skoda + */ + +require(__DIR__ . '/../../config.php'); +require_once(__DIR__ . '/locallib.php'); + +require_login(null, false); + +if (isguestuser()) { + // No guests here! + redirect(new moodle_url('/')); + die; +} +if (\core\session\manager::is_loggedinas()) { + // No login-as users. + redirect(new moodle_url('/user/index.php')); + die; +} + +$context = context_user::instance($USER->id); +require_capability('report/usersessions:manageownsessions', $context); + +$delete = optional_param('delete', 0, PARAM_INT); + +$PAGE->set_url('/report/usersessions/user.php'); +$PAGE->set_context($context); +$PAGE->set_title(get_string('navigationlink', 'report_usersessions')); +$PAGE->set_pagelayout('admin'); + +if ($delete and confirm_sesskey()) { + report_usersessions_kill_session($delete); + redirect($PAGE->url); +} + +echo $OUTPUT->header(); +echo $OUTPUT->heading(get_string('mysessions', 'report_usersessions')); + +$data = array(); +$sql = "SELECT id, timecreated, timemodified, firstip, lastip, sid + FROM {sessions} + WHERE userid = :userid + ORDER BY timemodified DESC"; +$params = array('userid' => $USER->id, 'sid' => session_id()); + +$sessions = $DB->get_records_sql($sql, $params); +foreach ($sessions as $session) { + if ($session->sid === $params['sid']) { + $lastaccess = get_string('thissession', 'report_usersessions'); + $deletelink = ''; + + } else { + $lastaccess = report_usersessions_format_duration(time() - $session->timemodified); + $url = new moodle_url($PAGE->url, array('delete' => $session->id, 'sesskey' => sesskey())); + $deletelink = html_writer::link($url, get_string('logout')); + } + $data[] = array(userdate($session->timecreated), $lastaccess, report_usersessions_format_ip($session->lastip), $deletelink); +} + +$table = new html_table(); +$table->head = array(get_string('login'), get_string('lastaccess'), get_string('lastip'), get_string('action')); +$table->align = array('left', 'left', 'left', 'right'); +$table->data = $data; +echo html_writer::table($table); + +echo $OUTPUT->footer(); + diff --git a/report/usersessions/version.php b/report/usersessions/version.php new file mode 100644 index 00000000000..f2d6dae1785 --- /dev/null +++ b/report/usersessions/version.php @@ -0,0 +1,30 @@ +. + +/** + * Version info. + * + * @package report_usersessions + * @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @author Petr Skoda + */ + +defined('MOODLE_INTERNAL') || die; + +$plugin->version = 2014111800; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2014111300; // Requires this Moodle version. +$plugin->component = 'report_usersessions'; // Full name of the plugin (used for diagnostics).