Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

binary safe session persistence #33

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ env:
matrix:
fast_finish: true
include:
- php: 5.6
env: DB=MYSQL PHPUNIT_TEST=1 PHPCS_TEST=1
- php: 7.0
env: DB=MYSQL PHPUNIT_TEST=1
- php: 7.1
env: DB=MYSQL PHPUNIT_TEST=1
- php: 7.2
env: DB=MYSQL PHPUNIT_TEST=1 PHPCS_TEST=1
- php: 7.3
env: DB=MYSQL PHPUNIT_TEST=1

before_script:
- composer self-update || true
Expand Down
82 changes: 82 additions & 0 deletions code/DynamoDbClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

namespace SilverStripe\DynamoDb;

/**
* DynamoDbClient extension that handles sessions as binary strings rather than textual content.
*
* Current AWS SDK PHP (<= 3.102.1) implementation passes session data as 'S'.
* This class overloads DynamoDbClient::updateItem method, intercepts the session table updates
* and substitutes the data type from 'S' to 'B' (from string to binary).
* PHP string is the php binary data type, so this should work seamlessly.
*
* @see https://github.com/silverstripe/silverstripe-dynamodb/issues/32
*/
class DynamoDbClient extends \Aws\DynamoDb\DynamoDbClient
{
/**
* The name of the DynamoDB table where
* sessions are stored
*
* @var string
*/
private $sessionTable;
dnsl48 marked this conversation as resolved.
Show resolved Hide resolved

/**
* The name of the data attribute of the session table
* where sessions are stored
*
* @var string
*/
private $dataAttribute;

/**
* Initialize the client with the session table
*
* @param string $sessionTable The session table name
*
* {@inheritdoc}
*/
public function __construct($sessionTable, ...$args)
{
$this->sessionTable = $sessionTable;
parent::__construct(...$args);
}

/**
* Initialize the client with the session data attribute (within the session table)
* This method must be used to finish the client initialization, otherwise session updates will not be
* intercepted and amended
*
* @param string $dataAttribute attribute of the session table where session data is persisted
*/
public function setSessionTableDataAttribute($dataAttribute)
{
$this->dataAttribute = $dataAttribute;
}

public function updateItem($attributes, ...$extra)
{
$this->patchSessionUpdate($attributes);
return parent::updateItem($attributes, ...$extra);
}

/**
* Update the session data type from 'S' to 'B' (from string to binary)
*
* @param mixed &$data Data to be updated in-place
*/
private function patchSessionUpdate(&$data)
{
if (!isset($data['TableName']) || $data['TableName'] !== $this->sessionTable) {
return;
}

if (!isset($data['AttributeUpdates'][$this->dataAttribute]['Value']['S'])) {
return;
}

$data['AttributeUpdates'][$this->dataAttribute]['Value']['B'] = $data['AttributeUpdates'][$this->dataAttribute]['Value']['S'];
unset($data['AttributeUpdates'][$this->dataAttribute]['Value']['S']);
}
}
7 changes: 4 additions & 3 deletions code/Model/DynamoDbSession.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace SilverStripe\DynamoDb\Model;

use Aws\DynamoDb\DynamoDbClient;
use Aws\DynamoDb\SessionHandler;
use SilverStripe\DynamoDb\DynamoDbClient;
use SilverStripe\DynamoDb\SessionHandler;
use Aws\DoctrineCacheAdapter;
use Doctrine\Common\Cache\ApcuCache;
use SilverStripe\Core\Config\Config;
Expand Down Expand Up @@ -78,7 +78,8 @@ public static function get()

public function __construct($options, $table)
{
$this->client = new DynamoDbClient(array_merge(['version' => '2012-08-10'], $options));
$this->client = new DynamoDbClient($table, array_merge(['version' => '2012-08-10'], $options));

$this->table = $table;
$this->handler = SessionHandler::fromClient(
$this->client,
Expand Down
36 changes: 36 additions & 0 deletions code/SessionHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace SilverStripe\DynamoDb;

use Aws\DynamoDb\SessionConnectionInterface;

/**
* The only purpose of this class is to finish our custom
* \SilverStripe\DynamoDb\DynamoDbClient initialization.
* To do so it simply needs to pass session data attribute
* from SessionConnection to DynamoDbClient::setSessionTableDataAttribute
* so the latter may intercept session table updates intelligently.
*
* @see \SilverStripe\DynamoDb\DynamoDbClient
*/
class SessionHandler extends \Aws\DynamoDb\SessionHandler
{
/**
* @var SessionConnectionInterface
*/
private $connection;

public static function fromClient(\Aws\DynamoDb\DynamoDbClient $client, array $config = [])
{
$handler = parent::fromClient($client, $config);
$client->setSessionTableDataAttribute($handler->connection->getDataAttribute());

return $handler;
}

public function __construct(SessionConnectionInterface $connection)
{
$this->connection = $connection;
parent::__construct($connection);
}
}
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"silverstripe/framework": "^4@dev"
},
"require-dev": {
"phpunit/PHPUnit": "^5.7"
"phpunit/PHPUnit": "^5.7",
"squizlabs/php_codesniffer": "^3.0"
},
"autoload": {
"psr-4": {
Expand Down