MDL-38303 cache: fixed purging of session cache when switching users
This commit is contained in:
Vendored
+54
@@ -1410,6 +1410,17 @@ class cache_application extends cache implements cache_loader_with_locking {
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class cache_session extends cache {
|
||||
/**
|
||||
* The user the session has been established for.
|
||||
* @var int
|
||||
*/
|
||||
protected static $loadeduserid = null;
|
||||
|
||||
/**
|
||||
* The userid this cache is currently using.
|
||||
* @var int
|
||||
*/
|
||||
protected $currentuserid = null;
|
||||
/**
|
||||
* Override the cache::construct method.
|
||||
*
|
||||
@@ -1426,6 +1437,8 @@ class cache_session extends cache {
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(cache_definition $definition, cache_store $store, $loader = null) {
|
||||
// First up copy the loadeduserid to the current user id.
|
||||
$this->currentuserid = self::$loadeduserid;
|
||||
parent::__construct($definition, $store, $loader);
|
||||
if ($definition->has_invalidation_events()) {
|
||||
$lastinvalidation = $this->get('lastsessioninvalidation');
|
||||
@@ -1474,6 +1487,47 @@ class cache_session extends cache {
|
||||
$this->set('lastsessioninvalidation', cache::now());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the key turning it into a string (or array is required) suitable to be passed to the cache store.
|
||||
*
|
||||
* This function is called for every operation that uses keys. For this reason we use this function to also check
|
||||
* that the current user is the same as the user who last used this cache.
|
||||
*
|
||||
* @param string|int $key As passed to get|set|delete etc.
|
||||
* @return string|array String unless the store supports multi-identifiers in which case an array if returned.
|
||||
*/
|
||||
protected function parse_key($key) {
|
||||
$this->check_tracked_user();
|
||||
return parent::parse_key($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that this cache instance is tracking the current user.
|
||||
*/
|
||||
protected function check_tracked_user() {
|
||||
if (isset($_SESSION['USER']->id)) {
|
||||
// Get the id of the current user.
|
||||
$new = $_SESSION['USER']->id;
|
||||
} else {
|
||||
// No user set up yet.
|
||||
$new = 0;
|
||||
}
|
||||
if ($new !== self::$loadeduserid) {
|
||||
// The current user doesn't match the tracker userid for this request.
|
||||
if (!is_null(self::$loadeduserid)) {
|
||||
// Purge the data we have for the old user.
|
||||
// This way we don't bloat the session.
|
||||
$this->purge();
|
||||
}
|
||||
self::$loadeduserid = $new;
|
||||
$this->currentuserid = $new;
|
||||
} else if ($new !== $this->currentuserid) {
|
||||
// The current user matches the loaded user but not the user last used by this cache.
|
||||
$this->purge();
|
||||
$this->currentuserid = $new;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Vendored
+59
@@ -866,4 +866,63 @@ class cache_phpunit_tests extends advanced_testcase {
|
||||
$this->assertTrue($cache->set('test', 'test'));
|
||||
$this->assertEquals('test', $cache->get('test'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test switching users with session caches.
|
||||
*/
|
||||
public function test_session_cache_switch_user() {
|
||||
$this->resetAfterTest(true);
|
||||
$cache = cache::make_from_params(cache_store::MODE_SESSION, 'phpunit', 'sessioncache');
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
|
||||
// Log in as the first user.
|
||||
$this->setUser($user1);
|
||||
$sesskey1 = sesskey();
|
||||
|
||||
// Set a basic value in the cache.
|
||||
$cache->set('var', 1);
|
||||
$this->assertTrue($cache->has('var'));
|
||||
$this->assertEquals(1, $cache->get('var'));
|
||||
|
||||
// Change to the second user.
|
||||
$this->setUser($user2);
|
||||
$sesskey2 = sesskey();
|
||||
|
||||
// Make sure the cache doesn't give us the data for the last user.
|
||||
$this->assertNotEquals($sesskey1, $sesskey2);
|
||||
$this->assertFalse($cache->has('var'));
|
||||
$this->assertEquals(false, $cache->get('var'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test multiple session caches when switching user.
|
||||
*/
|
||||
public function test_session_cache_switch_user_multiple() {
|
||||
$this->resetAfterTest(true);
|
||||
$cache1 = cache::make_from_params(cache_store::MODE_SESSION, 'phpunit', 'sessioncache1');
|
||||
$cache2 = cache::make_from_params(cache_store::MODE_SESSION, 'phpunit', 'sessioncache2');
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
|
||||
// Log in as the first user.
|
||||
$this->setUser($user1);
|
||||
$sesskey1 = sesskey();
|
||||
|
||||
// Set a basic value in the caches.
|
||||
$cache1->set('var', 1);
|
||||
$cache2->set('var', 2);
|
||||
$this->assertEquals(1, $cache1->get('var'));
|
||||
$this->assertEquals(2, $cache2->get('var'));
|
||||
|
||||
// Change to the second user.
|
||||
$this->setUser($user2);
|
||||
$sesskey2 = sesskey();
|
||||
|
||||
// Make sure the cache doesn't give us the data for the last user.
|
||||
// Also make sure that switching the user has lead to both caches being purged.
|
||||
$this->assertNotEquals($sesskey1, $sesskey2);
|
||||
$this->assertEquals(false, $cache1->get('var'));
|
||||
$this->assertEquals(false, $cache2->get('var'));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user