MDL-17942 more session refactoring

This commit is contained in:
skodak
2009-01-18 18:00:44 +00:00
parent 27d41812c3
commit e8656befac
7 changed files with 133 additions and 114 deletions
+2 -2
View File
@@ -52,7 +52,7 @@ switch ($action) {
if ($auth == $CFG->registerauth) {
set_config('registerauth', '');
}
session_get_instance()->gc(); // remove stale sessions
session_gc(); // remove stale sessions
break;
case 'enable':
@@ -62,7 +62,7 @@ switch ($action) {
$authsenabled = array_unique($authsenabled);
set_config('auth', implode(',', $authsenabled));
}
session_get_instance()->gc(); // remove stale sessions
session_gc(); // remove stale sessions
break;
case 'down':
+1 -1
View File
@@ -87,7 +87,7 @@
/// Session gc
mtrace("Cleaning up stale sessions");
session_get_instance()->gc();
session_gc();
/// Run all cron jobs for each module
+1 -1
View File
@@ -80,7 +80,7 @@
} else {
notify(get_string('deletednot', '', fullname($user, true)));
}
session_get_instance()->gc(); // remove stale sessions
session_gc(); // remove stale sessions
}
} else if ($acl and confirm_sesskey()) {
if (!has_capability('moodle/user:delete', $sitecontext)) {
+1 -1
View File
@@ -35,7 +35,7 @@ if ($confirm and confirm_sesskey()) {
}
$rs->close;
}
session_get_instance()->gc(); // remove stale sessions
session_gc(); // remove stale sessions
redirect($return, get_string('changessaved'));
} else {
+10 -1
View File
@@ -343,7 +343,16 @@ class auth_plugin_base {
//override if needed
}
function ignore_timeout_hook($userid, $userauth, $sid, $timecreated, $timemodified) {
/**
* Hook called before timing out of database session.
* This is usueful for SSO and MNET.
* @param object $user
* @param string $sid session id
* @param int $timecreated start of session
* @param int $timemodified user last seen
* @return bool true means do not timeout session yet
*/
function ignore_timeout_hook($user, $sid, $timecreated, $timemodified) {
return false;
}
+117 -107
View File
@@ -10,8 +10,12 @@ function session_get_instance() {
static $session = null;
if (is_null($session)) {
if (empty($CFG->sessiontimeout)) {
$CFG->sessiontimeout = 7200;
}
if (defined('SESSION_CUSTOM')) {
// this is a hook for custom session handling, webservices, etc.
// this is a hook for webservices, key based login, etc.
if (defined('SESSION_CUSTOM_FILE')) {
require_once($CFG->dirroot.SESSION_CUSTOM_FILE);
}
@@ -38,26 +42,12 @@ interface moodle_session {
*/
public function terminate_current();
/**
* Terminates all sessions, auth hooks are not executed.
* Useful in ugrade scripts.
*/
public function terminate_all();
/**
* No more changes in session expected.
* Unblocks the sesions, other scripts may start executing in parallel.
* @return void
*/
public function write_close();
/**
* Session garbage collection
* - verify timeout for all users
* - kill sessions of all deleted users
* - kill sessions of users with disabled plugins or 'nologin' plugin
*/
public function gc();
}
/**
@@ -304,9 +294,6 @@ class legacy_file_session extends session_stub {
ini_set('session.gc_probability', 1);
}
if (empty($CFG->sessiontimeout)) {
$CFG->sessiontimeout = 7200;
}
ini_set('session.gc_maxlifetime', $CFG->sessiontimeout);
if (!file_exists($CFG->dataroot .'/sessions')) {
@@ -317,25 +304,6 @@ class legacy_file_session extends session_stub {
}
ini_set('session.save_path', $CFG->dataroot .'/sessions');
}
/**
* Terminates all sessions, auth hooks are not executed.
* Useful in ugrade scripts.
*/
public function terminate_all() {
// TODO
}
/**
* Session garbage collection
* - verify timeout for all users
* - kill sessions of all deleted users
* - kill sessions of users with disabled plugins or 'nologin' plugin
*/
public function gc() {
// difficult/slow
}
}
/**
@@ -357,9 +325,6 @@ class database_session extends session_stub {
// gc only from CRON - individual user timeouts now checked during each access
ini_set('session.gc_probability', 0);
if (empty($CFG->sessiontimeout)) {
$CFG->sessiontimeout = 7200;
}
ini_set('session.gc_maxlifetime', $CFG->sessiontimeout);
$result = session_set_save_handler(array($this, 'handler_open'),
@@ -373,72 +338,6 @@ class database_session extends session_stub {
}
}
/**
* Terminates all sessions, auth hooks are not executed.
* Useful in ugrade scripts.
*/
public function terminate_all() {
try {
// do not show any warnings - might be during upgrade/installation
$this->database->delete_records('sessions');
} catch (dml_exception $ignored) {
}
}
/**
* Session garbage collection
* - verify timeout for all users
* - kill sessions of all deleted users
* - kill sessions of users with disabled plugins or 'nologin' plugin
*/
public function gc() {
global $CFG;
$maxlifetime = $CFG->sessiontimeout;
if (empty($CFG->rolesactive)) {
return;
}
try {
/// kill all sessions of deleted users
$this->database->delete_records_select('sessions', "userid IN (SELECT id FROM {user} WHERE deleted <> 0)");
/// kill sessions of users with disabled plugins
$auth_sequence = get_enabled_auth_plugins(true);
$auth_sequence = array_flip($auth_sequence);
unset($auth_sequence['nologin']); // no login allowed
$auth_sequence = array_flip($auth_sequence);
$notplugins = null;
list($notplugins, $params) = $this->database->get_in_or_equal($auth_sequence, SQL_PARAMS_QM, '', false);
$this->database->delete_records_select('sessions', "userid IN (SELECT id FROM {user} WHERE auth $notplugins)", $params);
/// now get a list of time-out candidates
$sql = "SELECT s.*, u.auth, u.username
FROM {sessions} s
JOIN {user} u ON u.id = s.userid
WHERE s.timemodified + ? < ?";
$params = array($maxlifetime, time());
$authplugins = array();
foreach($auth_sequence as $authname) {
$authplugins[$authname] = get_auth_plugin($authname);
}
$records = $this->database->get_records_sql($sql, $params);
foreach ($records as $record) {
if (!empty($record->userid) and $record->username !== 'guest') { // skips not logged in and guests
foreach ($authplugins as $authplugin) {
if ($authplugin->ignore_timeout_hook($record->userid, $records->auth, $record->sid, $record->timecreated, $record->timemodified)) {
continue;
}
}
}
$this->database->delete_records('sessions', array('id'=>$record->id));
}
} catch (dml_exception $ex) {
error_log('Error gc-ing sessions');
}
}
public function handler_open($save_path, $session_name) {
return true;
}
@@ -489,7 +388,7 @@ class database_session extends session_stub {
$authsequence = get_enabled_auth_plugins(); // auths, in sequence
foreach($authsequence as $authname) {
$authplugin = get_auth_plugin($authname);
if ($authplugin->ignore_timeout_hook($user->id, $user->auth, $record->sid, $record->timecreated, $record->timemodified)) {
if ($authplugin->ignore_timeout_hook($user, $record->sid, $record->timecreated, $record->timemodified)) {
$ignoretimeout = true;
break;
}
@@ -593,7 +492,117 @@ class database_session extends session_stub {
$this->gc();
return true;
}
}
/**
* Terminates all sessions, auth hooks are not executed.
* Useful in ugrade scripts.
*/
function session_kill_all() {
global $CFG, $DB;
try {
// do not show any warnings - might be during upgrade/installation
$DB->delete_records('sessions');
} catch (dml_exception $ignored) {
}
$sessiondir = "$CFG->dataroot/sessions/";
if (is_dir($sessiondir)) {
// TODO: delete all files, watch out some might be locked
}
}
/**
* Terminates one sessions, auth hooks are not executed.
*
* @param string $sid session id
*/
function session_kill($sid) {
global $CFG, $DB;
try {
// do not show any warnings - might be during upgrade/installation
$$DB->delete_records('sessions', array('sid'=>$sid));
} catch (dml_exception $ignored) {
}
$sessionfile = clean_param("$CFG->dataroot/sessions/$sid", PARAM_FILE);
if (file_exists($sessionfile)) {
// TODO: delete file, watch out might be locked
}
}
/**
* Terminates all sessions of one user, auth hooks are not executed.
* NOTE: This can not work for file based sessions!
*
* @param int $userid user id
*/
function session_kill_user($userid) {
global $CFG, $DB;
try {
// do not show any warnings - might be during upgrade/installation
$$DB->delete_records('sessions', array('userid'=>$userid));
} catch (dml_exception $ignored) {
}
}
/**
* Session garbage collection
* - verify timeout for all users
* - kill sessions of all deleted users
* - kill sessions of users with disabled plugins or 'nologin' plugin
*
* NOTE: this can not work when legacy file sessions used!
*/
function session_gc() {
global $CFG, $DB;
$maxlifetime = $CFG->sessiontimeout;
if (empty($CFG->rolesactive)) {
return;
}
try {
/// kill all sessions of deleted users
$DB->delete_records_select('sessions', "userid IN (SELECT id FROM {user} WHERE deleted <> 0)");
/// kill sessions of users with disabled plugins
$auth_sequence = get_enabled_auth_plugins(true);
$auth_sequence = array_flip($auth_sequence);
unset($auth_sequence['nologin']); // no login allowed
$auth_sequence = array_flip($auth_sequence);
$notplugins = null;
list($notplugins, $params) = $DB->get_in_or_equal($auth_sequence, SQL_PARAMS_QM, '', false);
$DB->delete_records_select('sessions', "userid IN (SELECT id FROM {user} WHERE auth $notplugins)", $params);
/// now get a list of time-out candidates
$sql = "SELECT u.*, s.sid, s.timecreated AS s_timecreated, s.timemodified AS s_timemodified
FROM {user} u
JOIN {sessions} s ON s.userid = u.id
WHERE s.timemodified + ? < ? AND u.username <> 'guest'";
$params = array($maxlifetime, time());
$authplugins = array();
foreach($auth_sequence as $authname) {
$authplugins[$authname] = get_auth_plugin($authname);
}
$rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $user) {
foreach ($authplugins as $authplugin) {
if ($authplugin->ignore_timeout_hook($user, $user->sid, $user->s_timecreated, $user->s_timemodified)) {
continue;
}
}
$DB->delete_records('sessions', array('sid'=>$user->sid));
}
$rs->close();
} catch (dml_exception $ex) {
error_log('Error gc-ing sessions');
}
}
/**
@@ -689,6 +698,7 @@ function get_moodle_cookie() {
}
}
/**
* Setup $USER object - called during login, loginas, etc.
* Preloads capabilities and checks enrolment plugins
+1 -1
View File
@@ -177,7 +177,7 @@
redirect("$CFG->wwwroot/user/view.php?id=$USER->id&course=$course->id");
}
} else {
session_get_instance()->gc(); // remove stale sessions
session_gc(); // remove stale sessions
redirect("$CFG->wwwroot/$CFG->admin/user.php");
}
//never reached