Merge branch 'wip_MDL-47834_m29_concurrentlogins' of https://github.com/skodak/moodle

This commit is contained in:
Dan Poltawski 2014-11-24 11:07:20 +00:00
commit 3111b66fbd
7 changed files with 191 additions and 0 deletions

View file

@ -622,6 +622,62 @@ class manager {
}
}
/**
* Terminate other sessions of current user depending
* on $CFG->limitconcurrentlogins restriction.
*
* This is expected to be called right after complete_user_login().
*
* NOTE:
* * Do not use from SSO auth plugins, this would not work.
* * Do not use from web services because they do not have sessions.
*
* @param int $userid
* @param string $sid session id to be always keep, usually the current one
* @return void
*/
public static function apply_concurrent_login_limit($userid, $sid = null) {
global $CFG, $DB;
// NOTE: the $sid parameter is here mainly to allow testing,
// in most cases it should be current session id.
if (isguestuser($userid) or empty($userid)) {
// This applies to real users only!
return;
}
if (empty($CFG->limitconcurrentlogins) or $CFG->limitconcurrentlogins < 0) {
return;
}
$count = $DB->count_records('sessions', array('userid' => $userid));
if ($count <= $CFG->limitconcurrentlogins) {
return;
}
$i = 0;
$select = "userid = :userid";
$params = array('userid' => $userid);
if ($sid) {
if ($DB->record_exists('sessions', array('sid' => $sid, 'userid' => $userid))) {
$select .= " AND sid <> :sid";
$params['sid'] = $sid;
$i = 1;
}
}
$sessions = $DB->get_records_select('sessions', $select, $params, 'timecreated DESC', 'id, sid');
foreach ($sessions as $session) {
$i++;
if ($i <= $CFG->limitconcurrentlogins) {
continue;
}
self::kill_session($session->sid);
}
}
/**
* Set current user.
*

View file

@ -326,6 +326,129 @@ class core_session_manager_testcase extends advanced_testcase {
$this->assertEquals(1, $DB->count_records('sessions', array('userid' => $userid, 'sid' => md5('pokus5'))));
}
public function test_apply_concurrent_login_limit() {
global $DB;
$this->resetAfterTest();
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$guest = guest_user();
$record = new \stdClass();
$record->state = 0;
$record->sessdata = null;
$record->userid = $user1->id;
$record->timemodified = time();
$record->firstip = $record->lastip = '10.0.0.1';
$record->sid = md5('hokus1');
$record->timecreated = 20;
$DB->insert_record('sessions', $record);
$record->sid = md5('hokus2');
$record->timecreated = 10;
$DB->insert_record('sessions', $record);
$record->sid = md5('hokus3');
$record->timecreated = 30;
$DB->insert_record('sessions', $record);
$record->userid = $user2->id;
$record->sid = md5('pokus1');
$record->timecreated = 20;
$DB->insert_record('sessions', $record);
$record->sid = md5('pokus2');
$record->timecreated = 10;
$DB->insert_record('sessions', $record);
$record->sid = md5('pokus3');
$record->timecreated = 30;
$DB->insert_record('sessions', $record);
$record->timecreated = 10;
$record->userid = $guest->id;
$record->sid = md5('g1');
$DB->insert_record('sessions', $record);
$record->sid = md5('g2');
$DB->insert_record('sessions', $record);
$record->sid = md5('g3');
$DB->insert_record('sessions', $record);
$record->userid = 0;
$record->sid = md5('nl1');
$DB->insert_record('sessions', $record);
$record->sid = md5('nl2');
$DB->insert_record('sessions', $record);
$record->sid = md5('nl3');
$DB->insert_record('sessions', $record);
set_config('limitconcurrentlogins', 0);
$this->assertCount(12, $DB->get_records('sessions'));
\core\session\manager::apply_concurrent_login_limit($user1->id);
\core\session\manager::apply_concurrent_login_limit($user2->id);
\core\session\manager::apply_concurrent_login_limit($guest->id);
\core\session\manager::apply_concurrent_login_limit(0);
$this->assertCount(12, $DB->get_records('sessions'));
set_config('limitconcurrentlogins', -1);
\core\session\manager::apply_concurrent_login_limit($user1->id);
\core\session\manager::apply_concurrent_login_limit($user2->id);
\core\session\manager::apply_concurrent_login_limit($guest->id);
\core\session\manager::apply_concurrent_login_limit(0);
$this->assertCount(12, $DB->get_records('sessions'));
set_config('limitconcurrentlogins', 2);
\core\session\manager::apply_concurrent_login_limit($user1->id);
$this->assertCount(11, $DB->get_records('sessions'));
$this->assertTrue($DB->record_exists('sessions', array('userid' => $user1->id, 'timecreated' => 20)));
$this->assertTrue($DB->record_exists('sessions', array('userid' => $user1->id, 'timecreated' => 30)));
$this->assertFalse($DB->record_exists('sessions', array('userid' => $user1->id, 'timecreated' => 10)));
$this->assertTrue($DB->record_exists('sessions', array('userid' => $user2->id, 'timecreated' => 20)));
$this->assertTrue($DB->record_exists('sessions', array('userid' => $user2->id, 'timecreated' => 30)));
$this->assertTrue($DB->record_exists('sessions', array('userid' => $user2->id, 'timecreated' => 10)));
set_config('limitconcurrentlogins', 2);
\core\session\manager::apply_concurrent_login_limit($user2->id, md5('pokus2'));
$this->assertCount(10, $DB->get_records('sessions'));
$this->assertFalse($DB->record_exists('sessions', array('userid' => $user2->id, 'timecreated' => 20)));
$this->assertTrue($DB->record_exists('sessions', array('userid' => $user2->id, 'timecreated' => 30)));
$this->assertTrue($DB->record_exists('sessions', array('userid' => $user2->id, 'timecreated' => 10)));
\core\session\manager::apply_concurrent_login_limit($guest->id);
\core\session\manager::apply_concurrent_login_limit(0);
$this->assertCount(10, $DB->get_records('sessions'));
set_config('limitconcurrentlogins', 1);
\core\session\manager::apply_concurrent_login_limit($user1->id, md5('grrr'));
$this->assertCount(9, $DB->get_records('sessions'));
$this->assertFalse($DB->record_exists('sessions', array('userid' => $user1->id, 'timecreated' => 20)));
$this->assertTrue($DB->record_exists('sessions', array('userid' => $user1->id, 'timecreated' => 30)));
$this->assertFalse($DB->record_exists('sessions', array('userid' => $user1->id, 'timecreated' => 10)));
\core\session\manager::apply_concurrent_login_limit($user1->id);
$this->assertCount(9, $DB->get_records('sessions'));
$this->assertFalse($DB->record_exists('sessions', array('userid' => $user1->id, 'timecreated' => 20)));
$this->assertTrue($DB->record_exists('sessions', array('userid' => $user1->id, 'timecreated' => 30)));
$this->assertFalse($DB->record_exists('sessions', array('userid' => $user1->id, 'timecreated' => 10)));
\core\session\manager::apply_concurrent_login_limit($user2->id, md5('pokus2'));
$this->assertCount(8, $DB->get_records('sessions'));
$this->assertFalse($DB->record_exists('sessions', array('userid' => $user2->id, 'timecreated' => 20)));
$this->assertFalse($DB->record_exists('sessions', array('userid' => $user2->id, 'timecreated' => 30)));
$this->assertTrue($DB->record_exists('sessions', array('userid' => $user2->id, 'timecreated' => 10)));
\core\session\manager::apply_concurrent_login_limit($user2->id);
$this->assertCount(8, $DB->get_records('sessions'));
$this->assertFalse($DB->record_exists('sessions', array('userid' => $user2->id, 'timecreated' => 20)));
$this->assertFalse($DB->record_exists('sessions', array('userid' => $user2->id, 'timecreated' => 30)));
$this->assertTrue($DB->record_exists('sessions', array('userid' => $user2->id, 'timecreated' => 10)));
\core\session\manager::apply_concurrent_login_limit($guest->id);
\core\session\manager::apply_concurrent_login_limit(0);
$this->assertCount(8, $DB->get_records('sessions'));
}
public function test_kill_all_sessions() {
global $DB, $USER;
$this->resetAfterTest();