2010-04-12 05:32:28 +02:00
|
|
|
<?php
|
|
|
|
|
2016-10-14 03:30:05 +02:00
|
|
|
namespace SilverStripe\Control\Tests;
|
|
|
|
|
2018-07-18 11:16:06 +02:00
|
|
|
use http\Exception\BadMessageException;
|
|
|
|
use SilverStripe\Control\Cookie;
|
2016-08-19 00:51:35 +02:00
|
|
|
use SilverStripe\Control\Session;
|
2017-06-22 12:50:45 +02:00
|
|
|
use SilverStripe\Dev\SapphireTest;
|
2017-06-26 01:24:50 +02:00
|
|
|
use SilverStripe\Control\HTTPRequest;
|
2016-08-19 00:51:35 +02:00
|
|
|
|
2010-04-12 05:32:28 +02:00
|
|
|
/**
|
|
|
|
* Tests to cover the {@link Session} class
|
|
|
|
*/
|
2016-12-16 05:34:21 +01:00
|
|
|
class SessionTest extends SapphireTest
|
|
|
|
{
|
2017-06-22 12:50:45 +02:00
|
|
|
/**
|
|
|
|
* @var Session
|
|
|
|
*/
|
|
|
|
protected $session = null;
|
|
|
|
|
|
|
|
protected function setUp()
|
|
|
|
{
|
|
|
|
$this->session = new Session([]);
|
|
|
|
return parent::setUp();
|
|
|
|
}
|
2016-12-16 05:34:21 +01:00
|
|
|
|
2018-07-18 11:16:06 +02:00
|
|
|
/**
|
|
|
|
* @runInSeparateProcess
|
|
|
|
* @preserveGlobalState disabled
|
|
|
|
*/
|
|
|
|
public function testInitDoesNotStartSessionWithoutIdentifier()
|
|
|
|
{
|
|
|
|
$req = new HTTPRequest('GET', '/');
|
|
|
|
$session = new Session(null); // unstarted session
|
|
|
|
$session->init($req);
|
|
|
|
$this->assertFalse($session->isStarted());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @runInSeparateProcess
|
|
|
|
* @preserveGlobalState disabled
|
|
|
|
*/
|
|
|
|
public function testInitStartsSessionWithIdentifier()
|
|
|
|
{
|
|
|
|
$req = new HTTPRequest('GET', '/');
|
|
|
|
Cookie::set(session_name(), '1234');
|
|
|
|
$session = new Session(null); // unstarted session
|
|
|
|
$session->init($req);
|
|
|
|
$this->assertTrue($session->isStarted());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @runInSeparateProcess
|
|
|
|
* @preserveGlobalState disabled
|
|
|
|
*/
|
|
|
|
public function testInitStartsSessionWithData()
|
|
|
|
{
|
|
|
|
$req = new HTTPRequest('GET', '/');
|
|
|
|
$session = new Session([]);
|
|
|
|
$session->init($req);
|
|
|
|
$this->assertTrue($session->isStarted());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @runInSeparateProcess
|
|
|
|
* @preserveGlobalState disabled
|
|
|
|
*/
|
|
|
|
public function testStartUsesDefaultCookieNameWithHttp()
|
|
|
|
{
|
|
|
|
$req = (new HTTPRequest('GET', '/'))
|
|
|
|
->setScheme('http');
|
|
|
|
Cookie::set(session_name(), '1234');
|
|
|
|
$session = new Session(null); // unstarted session
|
|
|
|
$session->start($req);
|
|
|
|
$this->assertNotEquals(session_name(), $session->config()->get('cookie_name_secure'));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @runInSeparateProcess
|
|
|
|
* @preserveGlobalState disabled
|
|
|
|
*/
|
|
|
|
public function testStartUsesDefaultCookieNameWithHttpsAndCookieSecureOff()
|
|
|
|
{
|
|
|
|
$req = (new HTTPRequest('GET', '/'))
|
|
|
|
->setScheme('https');
|
|
|
|
Cookie::set(session_name(), '1234');
|
|
|
|
$session = new Session(null); // unstarted session
|
|
|
|
$session->start($req);
|
|
|
|
$this->assertNotEquals(session_name(), $session->config()->get('cookie_name_secure'));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @runInSeparateProcess
|
|
|
|
* @preserveGlobalState disabled
|
|
|
|
*/
|
|
|
|
public function testStartUsesSecureCookieNameWithHttpsAndCookieSecureOn()
|
|
|
|
{
|
|
|
|
$req = (new HTTPRequest('GET', '/'))
|
|
|
|
->setScheme('https');
|
|
|
|
Cookie::set(session_name(), '1234');
|
|
|
|
$session = new Session(null); // unstarted session
|
|
|
|
$session->config()->update('cookie_secure', true);
|
|
|
|
$session->start($req);
|
|
|
|
$this->assertEquals(session_name(), $session->config()->get('cookie_name_secure'));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @runInSeparateProcess
|
|
|
|
* @preserveGlobalState disabled
|
|
|
|
* @expectedException BadMethodCallException
|
|
|
|
* @expectedExceptionMessage Session has already started
|
|
|
|
*/
|
|
|
|
public function testStartErrorsWhenStartingTwice()
|
|
|
|
{
|
|
|
|
$req = new HTTPRequest('GET', '/');
|
|
|
|
$session = new Session(null); // unstarted session
|
|
|
|
$session->start($req);
|
|
|
|
$session->start($req);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @runInSeparateProcess
|
|
|
|
* @preserveGlobalState disabled
|
|
|
|
*/
|
|
|
|
public function testStartRetainsInMemoryData()
|
|
|
|
{
|
|
|
|
$this->markTestIncomplete('Test');
|
|
|
|
// TODO Figure out how to simulate session vars without a session_start() resetting them
|
|
|
|
// $_SESSION['existing'] = true;
|
|
|
|
// $_SESSION['merge'] = 1;
|
|
|
|
$req = new HTTPRequest('GET', '/');
|
|
|
|
$session = new Session(null); // unstarted session
|
|
|
|
$session->set('new', true);
|
|
|
|
$session->set('merge', 2);
|
|
|
|
$session->start($req); // simulate lazy start
|
|
|
|
$this->assertEquals(
|
|
|
|
[
|
|
|
|
// 'existing' => true,
|
|
|
|
'new' => true,
|
|
|
|
'merge' => 2
|
|
|
|
],
|
|
|
|
$session->getAll()
|
|
|
|
);
|
|
|
|
|
|
|
|
unset($_SESSION);
|
|
|
|
}
|
|
|
|
|
2016-12-16 05:34:21 +01:00
|
|
|
public function testGetSetBasics()
|
|
|
|
{
|
2017-06-22 12:50:45 +02:00
|
|
|
$this->session->set('Test', 'Test');
|
2016-12-16 05:34:21 +01:00
|
|
|
|
2017-06-22 12:50:45 +02:00
|
|
|
$this->assertEquals($this->session->get('Test'), 'Test');
|
2016-12-16 05:34:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testClearElement()
|
|
|
|
{
|
2017-06-22 12:50:45 +02:00
|
|
|
$this->session->set('Test', 'Test');
|
|
|
|
$this->session->clear('Test');
|
2016-12-16 05:34:21 +01:00
|
|
|
|
2017-06-22 12:50:45 +02:00
|
|
|
$this->assertEquals($this->session->get('Test'), '');
|
2016-12-16 05:34:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testClearAllElements()
|
|
|
|
{
|
2017-06-22 12:50:45 +02:00
|
|
|
$this->session->set('Test', 'Test');
|
|
|
|
$this->session->set('Test-1', 'Test-1');
|
2016-12-16 05:34:21 +01:00
|
|
|
|
2017-06-22 12:50:45 +02:00
|
|
|
$this->session->clearAll();
|
2016-12-16 05:34:21 +01:00
|
|
|
|
|
|
|
// should session get return null? The array key should probably be
|
|
|
|
// unset from the data array
|
2017-06-22 12:50:45 +02:00
|
|
|
$this->assertEquals($this->session->get('Test'), '');
|
|
|
|
$this->assertEquals($this->session->get('Test-1'), '');
|
2016-12-16 05:34:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testGetAllElements()
|
|
|
|
{
|
2017-06-22 12:50:45 +02:00
|
|
|
$this->session->clearAll(); // Remove all session that might've been set by the test harness
|
2016-12-16 05:34:21 +01:00
|
|
|
|
2017-06-22 12:50:45 +02:00
|
|
|
$this->session->set('Test', 'Test');
|
|
|
|
$this->session->set('Test-2', 'Test-2');
|
2016-12-16 05:34:21 +01:00
|
|
|
|
2017-06-22 12:50:45 +02:00
|
|
|
$session = $this->session->getAll();
|
2016-12-16 05:34:21 +01:00
|
|
|
unset($session['HTTP_USER_AGENT']);
|
|
|
|
|
|
|
|
$this->assertEquals($session, array('Test' => 'Test', 'Test-2' => 'Test-2'));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testSettingExistingDoesntClear()
|
|
|
|
{
|
2017-06-22 12:50:45 +02:00
|
|
|
$s = new Session(array('something' => array('does' => 'exist')));
|
2016-12-16 05:34:21 +01:00
|
|
|
|
2017-06-22 12:50:45 +02:00
|
|
|
$s->set('something.does', 'exist');
|
|
|
|
$result = $s->changedData();
|
2016-12-16 05:34:21 +01:00
|
|
|
unset($result['HTTP_USER_AGENT']);
|
|
|
|
$this->assertEquals(array(), $result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check that changedData isn't populated with junk when clearing non-existent entries.
|
|
|
|
*/
|
|
|
|
public function testClearElementThatDoesntExist()
|
|
|
|
{
|
2018-02-02 00:51:00 +01:00
|
|
|
$s = new Session(['something' => ['does' => 'exist']]);
|
2017-06-22 12:50:45 +02:00
|
|
|
$s->clear('something.doesnt.exist');
|
2016-12-16 05:34:21 +01:00
|
|
|
|
2018-02-02 00:51:00 +01:00
|
|
|
// Clear without existing data
|
|
|
|
$data = $s->get('something.doesnt.exist');
|
|
|
|
$this->assertEquals(array(), $s->changedData());
|
|
|
|
$this->assertNull($data);
|
|
|
|
|
|
|
|
// Clear with existing change
|
2017-06-22 12:50:45 +02:00
|
|
|
$s->set('something-else', 'val');
|
|
|
|
$s->clear('something-new');
|
2018-02-02 00:51:00 +01:00
|
|
|
$data = $s->get('something-else');
|
|
|
|
$this->assertEquals(['something-else' => true], $s->changedData());
|
|
|
|
$this->assertEquals('val', $data);
|
2016-12-16 05:34:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check that changedData is populated with clearing data.
|
|
|
|
*/
|
|
|
|
public function testClearElementThatDoesExist()
|
|
|
|
{
|
2018-02-02 00:51:00 +01:00
|
|
|
$s = new Session(['something' => ['does' => 'exist']]);
|
2016-12-16 05:34:21 +01:00
|
|
|
|
2018-02-02 00:51:00 +01:00
|
|
|
// Ensure keys are properly removed and not simply nullified
|
2017-06-22 12:50:45 +02:00
|
|
|
$s->clear('something.does');
|
2018-02-02 00:51:00 +01:00
|
|
|
$this->assertEquals(
|
|
|
|
['something' => ['does' => true]],
|
|
|
|
$s->changedData()
|
|
|
|
);
|
|
|
|
$this->assertEquals(
|
|
|
|
[], // 'does' removed
|
|
|
|
$s->get('something')
|
|
|
|
);
|
|
|
|
|
|
|
|
// Clear at more specific level should also clear other changes
|
|
|
|
$s->clear('something');
|
|
|
|
$this->assertEquals(
|
|
|
|
['something' => true],
|
|
|
|
$s->changedData()
|
|
|
|
);
|
|
|
|
$this->assertEquals(
|
|
|
|
null, // Should be removed not just empty array
|
|
|
|
$s->get('something')
|
|
|
|
);
|
2016-12-16 05:34:21 +01:00
|
|
|
}
|
|
|
|
|
2018-07-18 11:16:06 +02:00
|
|
|
public function testRequestContainsSessionId()
|
|
|
|
{
|
|
|
|
$req = new HTTPRequest('GET', '/');
|
|
|
|
$session = new Session(null); // unstarted session
|
|
|
|
$this->assertFalse($session->requestContainsSessionId($req));
|
|
|
|
Cookie::set(session_name(), '1234');
|
|
|
|
$this->assertTrue($session->requestContainsSessionId($req));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testRequestContainsSessionIdRespectsCookieNameSecure()
|
|
|
|
{
|
|
|
|
$req = (new HTTPRequest('GET', '/'))
|
|
|
|
->setScheme('https');
|
|
|
|
$session = new Session(null); // unstarted session
|
|
|
|
Cookie::set($session->config()->get('cookie_name_secure'), '1234');
|
|
|
|
$session->config()->update('cookie_secure', true);
|
|
|
|
$this->assertTrue($session->requestContainsSessionId($req));
|
|
|
|
}
|
|
|
|
|
2016-12-16 05:34:21 +01:00
|
|
|
public function testUserAgentLockout()
|
|
|
|
{
|
|
|
|
// Set a user agent
|
2017-06-26 01:24:50 +02:00
|
|
|
$req1 = new HTTPRequest('GET', '/');
|
2017-06-25 05:12:29 +02:00
|
|
|
$req1->addHeader('User-Agent', 'Test Agent');
|
2016-12-16 05:34:21 +01:00
|
|
|
|
|
|
|
// Generate our session
|
2017-06-22 12:50:45 +02:00
|
|
|
$s = new Session(array());
|
2017-06-26 01:24:50 +02:00
|
|
|
$s->init($req1);
|
2017-06-22 12:50:45 +02:00
|
|
|
$s->set('val', 123);
|
2017-06-26 01:24:50 +02:00
|
|
|
$s->finalize($req1);
|
2016-12-16 05:34:21 +01:00
|
|
|
|
|
|
|
// Change our UA
|
2017-06-26 01:24:50 +02:00
|
|
|
$req2 = new HTTPRequest('GET', '/');
|
2017-06-25 05:12:29 +02:00
|
|
|
$req2->addHeader('User-Agent', 'Fake Agent');
|
2016-12-16 05:34:21 +01:00
|
|
|
|
|
|
|
// Verify the new session reset our values
|
2017-06-22 12:50:45 +02:00
|
|
|
$s2 = new Session($s);
|
2017-06-26 01:24:50 +02:00
|
|
|
$s2->init($req2);
|
2017-06-22 12:50:45 +02:00
|
|
|
$this->assertNotEquals($s2->get('val'), 123);
|
2016-12-16 05:34:21 +01:00
|
|
|
}
|
2018-02-02 00:51:00 +01:00
|
|
|
|
|
|
|
public function testSave()
|
|
|
|
{
|
|
|
|
$request = new HTTPRequest('GET', '/');
|
|
|
|
|
|
|
|
// Test change of nested array type
|
|
|
|
$s = new Session($_SESSION = ['something' => ['some' => 'value', 'another' => 'item']]);
|
|
|
|
$s->set('something', 'string');
|
|
|
|
$s->save($request);
|
|
|
|
$this->assertEquals(
|
|
|
|
['something' => 'string'],
|
|
|
|
$_SESSION
|
|
|
|
);
|
|
|
|
|
|
|
|
// Test multiple changes combine safely
|
|
|
|
$s = new Session($_SESSION = ['something' => ['some' => 'value', 'another' => 'item']]);
|
|
|
|
$s->set('something.another', 'newanother');
|
|
|
|
$s->clear('something.some');
|
|
|
|
$s->set('something.newkey', 'new value');
|
|
|
|
$s->save($request);
|
|
|
|
$this->assertEquals(
|
|
|
|
[
|
|
|
|
'something' => [
|
|
|
|
'another' => 'newanother',
|
|
|
|
'newkey' => 'new value',
|
|
|
|
]
|
|
|
|
],
|
|
|
|
$_SESSION
|
|
|
|
);
|
|
|
|
|
|
|
|
// Test cleared keys are restorable
|
|
|
|
$s = new Session($_SESSION = ['bookmarks' => [ 1 => 1, 2 => 2]]);
|
|
|
|
$s->clear('bookmarks');
|
|
|
|
$s->set('bookmarks', [
|
|
|
|
1 => 1,
|
|
|
|
3 => 3,
|
|
|
|
]);
|
|
|
|
$s->save($request);
|
|
|
|
$this->assertEquals(
|
|
|
|
[
|
|
|
|
'bookmarks' => [
|
|
|
|
1 => 1,
|
|
|
|
3 => 3,
|
|
|
|
]
|
|
|
|
],
|
|
|
|
$_SESSION
|
|
|
|
);
|
|
|
|
}
|
2012-03-24 04:04:52 +01:00
|
|
|
}
|