Skip to content

Commit f961127

Browse files
author
Adam Tomat
committed
Make session storage a bit more resilliant
1 parent 11e6cc7 commit f961127

6 files changed

Lines changed: 71 additions & 19 deletions

File tree

src/Session/EncryptedStore.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,14 @@ protected function prepareForStorage($data)
3232

3333
protected function prepareForUnserialize($data)
3434
{
35+
if ($data === '') {
36+
return '';
37+
}
38+
3539
try {
3640
return $this->encrypter->decrypt($data);
3741
} catch (Exception $e) {
38-
$this->exceptionHandler->report($e);
42+
$this->exceptionHandler?->report($e);
3943
return '';
4044
}
4145
}

src/Session/FileSessionHandler.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,13 @@
88

99
class FileSessionHandler implements SessionHandlerInterface
1010
{
11-
public function __construct(protected $path, protected $prefix = 'lumberjack_session_')
11+
protected $path;
12+
protected $prefix;
13+
14+
public function __construct($path, $prefix = 'lumberjack_session_')
1215
{
16+
$this->path = $path;
17+
$this->prefix = $prefix;
1318
}
1419

1520
#[\ReturnTypeWillChange]

src/Session/SessionManager.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Rareloop\Lumberjack\Application;
66
use Rareloop\Lumberjack\Config;
77
use Rareloop\Lumberjack\Contracts\Encrypter as EncrypterContract;
8+
use Rareloop\Lumberjack\Exceptions\HandlerInterface;
89
use Rareloop\Lumberjack\Manager;
910

1011
class SessionManager extends Manager
@@ -54,8 +55,9 @@ protected function buildSession($handler)
5455

5556
if ($this->config->get('session.encrypt')) {
5657
$encrypter = $this->app->get(EncrypterContract::class);
58+
$exceptionHandler = $this->app->get(HandlerInterface::class);
5759

58-
return new EncryptedStore($this->name, $handler, $encrypter, $sessionId);
60+
return new EncryptedStore($this->name, $handler, $encrypter, $sessionId, $exceptionHandler);
5961
}
6062

6163
return new Store($this->name, $handler, $sessionId);

tests/Unit/Exceptions/HandlerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,6 @@ class HandlerWithBlacklist extends Handler
124124
];
125125
}
126126

127-
class BlacklistedException extends \Exception
127+
class BlacklistedException extends \Exception
128128
{
129129
}

tests/Unit/Session/EncryptedStoreTest.php

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,14 @@ public function data_is_decrypted_before_it_is_loaded()
5454

5555
/**
5656
* @test
57-
* @dataProvider unexpectedSessionData
5857
*/
59-
public function unexpected_session_data_is_handled_gracefully($previousSessionValue)
58+
public function unexpected_session_data_is_handled_gracefully()
6059
{
6160
$encryptionKey = 'encryption-key';
6261

6362
// Use a mock handler to fake a previously stored state
6463
$handler = Mockery::mock(NullSessionHandler::class . '[read]');
65-
$handler->shouldReceive('read')->andReturn($previousSessionValue);
64+
$handler->shouldReceive('read')->andReturn(@serialize(['foo' => 'bar']));
6665

6766
$errorHandler = Mockery::mock(HandlerInterface::class);
6867
$errorHandler->shouldReceive('report')->once();
@@ -73,11 +72,40 @@ public function unexpected_session_data_is_handled_gracefully($previousSessionVa
7372
$this->assertSame(null, $store->get('foo'));
7473
}
7574

76-
public function unexpectedSessionData()
75+
/**
76+
* @test
77+
*/
78+
public function gracefully_handle_case_with_no_exception_handler()
7779
{
78-
return [
79-
[@serialize(['foo' => 'bar'])],
80-
[''],
81-
];
80+
$encryptionKey = 'encryption-key';
81+
82+
// Use a mock handler to fake a previously stored state
83+
$handler = Mockery::mock(NullSessionHandler::class . '[read]');
84+
$handler->shouldReceive('read')->andReturn(@serialize(['foo' => 'bar']));
85+
86+
$store = new EncryptedStore('session-name', $handler, new Encrypter($encryptionKey), 'session-id');
87+
$store->start();
88+
89+
$this->assertSame(null, $store->get('foo'));
90+
}
91+
92+
/**
93+
* @test
94+
*/
95+
public function empty_session_data_is_ignored()
96+
{
97+
$encryptionKey = 'encryption-key';
98+
99+
// Use a mock handler to fake a previously stored state
100+
$handler = Mockery::mock(NullSessionHandler::class . '[read]');
101+
$handler->shouldReceive('read')->andReturn('');
102+
103+
$errorHandler = Mockery::mock(HandlerInterface::class);
104+
$errorHandler->shouldNotHaveReceived('report');
105+
106+
$store = new EncryptedStore('session-name', $handler, new Encrypter($encryptionKey), 'session-id', $errorHandler);
107+
$store->start();
108+
109+
$this->assertSame(null, $store->get('foo'));
82110
}
83111
}

tests/Unit/Session/SessionManagerTest.php

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,20 @@
33
namespace Rareloop\Lumberjack\Test;
44

55
use Mockery;
6+
use ReflectionClass;
7+
use org\bovigo\vfs\vfsStream;
68
use PHPUnit\Framework\TestCase;
7-
use Rareloop\Lumberjack\Application;
89
use Rareloop\Lumberjack\Config;
9-
use Rareloop\Lumberjack\Contracts\Encrypter as EncrypterContract;
1010
use Rareloop\Lumberjack\Encrypter;
11+
use Rareloop\Lumberjack\Application;
12+
use Rareloop\Lumberjack\Session\Store;
13+
use Rareloop\Lumberjack\Exceptions\Handler;
1114
use Rareloop\Lumberjack\Session\EncryptedStore;
12-
use Rareloop\Lumberjack\Session\FileSessionHandler;
1315
use Rareloop\Lumberjack\Session\SessionManager;
14-
use Rareloop\Lumberjack\Session\Store;
16+
use Rareloop\Lumberjack\Session\FileSessionHandler;
17+
use Rareloop\Lumberjack\Exceptions\HandlerInterface;
1518
use Rareloop\Lumberjack\Test\Unit\Session\NullSessionHandler;
16-
use org\bovigo\vfs\vfsStream;
19+
use Rareloop\Lumberjack\Contracts\Encrypter as EncrypterContract;
1720

1821
class SessionManagerTest extends TestCase
1922
{
@@ -93,12 +96,22 @@ public function can_create_an_unencrypted_store()
9396
/** @test */
9497
public function can_create_an_encrypted_store()
9598
{
96-
$app = $app = $this->appWithSessionDriverConfig('file', 'lumberjack', $encrypted = true);
99+
$app = $this->appWithSessionDriverConfig('file', 'lumberjack', $encrypted = true);
97100
$app->bind(EncrypterContract::class, new Encrypter('encryption-key'));
98101

102+
$handler = Mockery::mock(Handler::class);
103+
$app->bind(HandlerInterface::class, $handler);
104+
99105
$manager = new SessionManager($app);
100106

101-
$this->assertInstanceOf(EncryptedStore::class, $manager->driver());
107+
$driver = $manager->driver();
108+
$this->assertInstanceOf(EncryptedStore::class, $driver);
109+
110+
$reflection = new ReflectionClass($driver);
111+
$property = $reflection->getProperty('exceptionHandler');
112+
$property->setAccessible(true);
113+
114+
$this->assertInstanceOf(HandlerInterface::class, $property->getValue($driver));
102115
}
103116
}
104117

0 commit comments

Comments
 (0)