implementing key/value store of Persistance in Database storage
This commit is contained in:
parent
7901ec74a7
commit
a203e6322b
8 changed files with 86 additions and 65 deletions
|
@ -11,6 +11,7 @@
|
||||||
* CHANGED: Upgrading libraries to: random_compat 2.0.20
|
* CHANGED: Upgrading libraries to: random_compat 2.0.20
|
||||||
* CHANGED: Removed automatic `.ini` configuration file migration (#808)
|
* CHANGED: Removed automatic `.ini` configuration file migration (#808)
|
||||||
* CHANGED: Removed configurable `dir` for `traffic` & `purge` limiters (#419)
|
* CHANGED: Removed configurable `dir` for `traffic` & `purge` limiters (#419)
|
||||||
|
* CHANGED: Server salt, traffic and purge limiter now stored in the storage backend (#419)
|
||||||
* **1.3.5 (2021-04-05)**
|
* **1.3.5 (2021-04-05)**
|
||||||
* ADDED: Translation for Hebrew, Lithuanian, Indonesian and Catalan
|
* ADDED: Translation for Hebrew, Lithuanian, Indonesian and Catalan
|
||||||
* ADDED: Make the project info configurable (#681)
|
* ADDED: Make the project info configurable (#681)
|
||||||
|
|
|
@ -28,6 +28,15 @@ abstract class AbstractData
|
||||||
*/
|
*/
|
||||||
protected static $_instance = null;
|
protected static $_instance = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cache for the traffic limiter
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @static
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected static $_traffic_limiter_cache = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enforce singleton, disable constructor
|
* Enforce singleton, disable constructor
|
||||||
*
|
*
|
||||||
|
@ -138,7 +147,16 @@ abstract class AbstractData
|
||||||
* @param int $time
|
* @param int $time
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
abstract public function purgeValues($namespace, $time);
|
public function purgeValues($namespace, $time)
|
||||||
|
{
|
||||||
|
if ($namespace === 'traffic_limiter') {
|
||||||
|
foreach (self::$_traffic_limiter_cache as $key => $last_access) {
|
||||||
|
if ($last_access <= $time) {
|
||||||
|
unset(self::$_traffic_limiter_cache[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a value.
|
* Save a value.
|
||||||
|
|
|
@ -423,23 +423,6 @@ class Database extends AbstractData
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Purge outdated entries.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $namespace
|
|
||||||
* @param int $time
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function purgeValues($namespace, $time)
|
|
||||||
{
|
|
||||||
switch ($namespace) {
|
|
||||||
case 'traffic_limiter':
|
|
||||||
;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a value.
|
* Save a value.
|
||||||
*
|
*
|
||||||
|
@ -451,21 +434,20 @@ class Database extends AbstractData
|
||||||
*/
|
*/
|
||||||
public function setValue($value, $namespace, $key = '')
|
public function setValue($value, $namespace, $key = '')
|
||||||
{
|
{
|
||||||
switch ($namespace) {
|
if ($namespace === 'traffic_limiter') {
|
||||||
case 'purge_limiter':
|
self::$_traffic_limiter_cache[$key] = $value;
|
||||||
;
|
try {
|
||||||
break;
|
$value = Json::encode(self::$_traffic_limiter_cache);
|
||||||
case 'salt':
|
} catch (Exception $e) {
|
||||||
;
|
|
||||||
break;
|
|
||||||
case 'traffic_limiter':
|
|
||||||
;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return self::_exec(
|
||||||
|
'UPDATE ' . self::_sanitizeIdentifier('config') .
|
||||||
|
' SET value = ? WHERE id = ?',
|
||||||
|
array($value, strtoupper($namespace))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a value.
|
* Load a value.
|
||||||
|
@ -477,7 +459,36 @@ class Database extends AbstractData
|
||||||
*/
|
*/
|
||||||
public function getValue($namespace, $key = '')
|
public function getValue($namespace, $key = '')
|
||||||
{
|
{
|
||||||
|
$configKey = strtoupper($namespace);
|
||||||
|
$value = $this->_getConfig($configKey);
|
||||||
|
if ($value === '') {
|
||||||
|
// initialize the row, so that setValue can rely on UPDATE queries
|
||||||
|
self::_exec(
|
||||||
|
'INSERT INTO ' . self::_sanitizeIdentifier('config') .
|
||||||
|
' VALUES(?,?)',
|
||||||
|
array($configKey, '')
|
||||||
|
);
|
||||||
|
|
||||||
|
// migrate filesystem based salt into database
|
||||||
|
$file = 'data' . DIRECTORY_SEPARATOR . 'salt.php';
|
||||||
|
if ($namespace === 'salt' && is_readable($file)) {
|
||||||
|
$value = Filesystem::getInstance(array('dir' => 'data'))->getValue('salt');
|
||||||
|
$this->setValue($value, 'salt');
|
||||||
|
@unlink($file);
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($value && $namespace === 'traffic_limiter') {
|
||||||
|
try {
|
||||||
|
self::$_traffic_limiter_cache = Json::decode($value);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
self::$_traffic_limiter_cache = array();
|
||||||
|
}
|
||||||
|
if (array_key_exists($key, self::$_traffic_limiter_cache)) {
|
||||||
|
return self::$_traffic_limiter_cache[$key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (string) $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -629,7 +640,7 @@ class Database extends AbstractData
|
||||||
'SELECT value FROM ' . self::_sanitizeIdentifier('config') .
|
'SELECT value FROM ' . self::_sanitizeIdentifier('config') .
|
||||||
' WHERE id = ?', array($key), true
|
' WHERE id = ?', array($key), true
|
||||||
);
|
);
|
||||||
return $row['value'];
|
return $row ? $row['value']: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -38,15 +38,6 @@ class Filesystem extends AbstractData
|
||||||
*/
|
*/
|
||||||
private static $_path = 'data';
|
private static $_path = 'data';
|
||||||
|
|
||||||
/**
|
|
||||||
* cache for the traffic limiter
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
* @static
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private static $_traffic_limiter_cache = array();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get instance of singleton
|
* get instance of singleton
|
||||||
*
|
*
|
||||||
|
@ -249,27 +240,6 @@ class Filesystem extends AbstractData
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Purge outdated entries.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $namespace
|
|
||||||
* @param int $time
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function purgeValues($namespace, $time)
|
|
||||||
{
|
|
||||||
switch ($namespace) {
|
|
||||||
case 'traffic_limiter':
|
|
||||||
foreach (self::$_traffic_limiter_cache as $key => $last_access) {
|
|
||||||
if ($last_access <= $time) {
|
|
||||||
unset(self::$_traffic_limiter_cache[$key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a value.
|
* Save a value.
|
||||||
*
|
*
|
||||||
|
|
|
@ -227,10 +227,11 @@ class GoogleCloudStorage extends AbstractData
|
||||||
*/
|
*/
|
||||||
public function purgeValues($namespace, $time)
|
public function purgeValues($namespace, $time)
|
||||||
{
|
{
|
||||||
switch ($namespace) {
|
if ($namespace === 'traffic_limiter') {
|
||||||
case 'traffic_limiter':
|
// TODO implement purging of keys in namespace that are <= $time
|
||||||
;
|
// if GCS has no easy way to iterate all keys, consider using the
|
||||||
break;
|
// self::$_traffic_limiter_cache in a similar way as the other
|
||||||
|
// implementations.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ class ControllerTest extends PHPUnit_Framework_TestCase
|
||||||
/* Setup Routine */
|
/* Setup Routine */
|
||||||
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
|
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
|
||||||
$this->_data = Filesystem::getInstance(array('dir' => $this->_path));
|
$this->_data = Filesystem::getInstance(array('dir' => $this->_path));
|
||||||
|
ServerSalt::setStore($this->_data);
|
||||||
TrafficLimiter::setStore($this->_data);
|
TrafficLimiter::setStore($this->_data);
|
||||||
$this->reset();
|
$this->reset();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use PrivateBin\Data\Database;
|
use PrivateBin\Data\Database;
|
||||||
|
use PrivateBin\Persistence\ServerSalt;
|
||||||
|
use PrivateBin\Persistence\TrafficLimiter;
|
||||||
|
|
||||||
require_once 'ControllerTest.php';
|
require_once 'ControllerTest.php';
|
||||||
|
|
||||||
|
@ -24,6 +26,8 @@ class ControllerWithDbTest extends ControllerTest
|
||||||
}
|
}
|
||||||
$this->_options['dsn'] = 'sqlite:' . $this->_path . DIRECTORY_SEPARATOR . 'tst.sq3';
|
$this->_options['dsn'] = 'sqlite:' . $this->_path . DIRECTORY_SEPARATOR . 'tst.sq3';
|
||||||
$this->_data = Database::getInstance($this->_options);
|
$this->_data = Database::getInstance($this->_options);
|
||||||
|
ServerSalt::setStore($this->_data);
|
||||||
|
TrafficLimiter::setStore($this->_data);
|
||||||
$this->reset();
|
$this->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
use PrivateBin\Controller;
|
use PrivateBin\Controller;
|
||||||
use PrivateBin\Data\Database;
|
use PrivateBin\Data\Database;
|
||||||
|
use PrivateBin\Data\Filesystem;
|
||||||
|
use PrivateBin\Persistence\ServerSalt;
|
||||||
|
|
||||||
class DatabaseTest extends PHPUnit_Framework_TestCase
|
class DatabaseTest extends PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
@ -31,6 +33,19 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSaltMigration()
|
||||||
|
{
|
||||||
|
ServerSalt::setStore(Filesystem::getInstance(array('dir' => 'data')));
|
||||||
|
$salt = ServerSalt::get();
|
||||||
|
$file = 'data' . DIRECTORY_SEPARATOR . 'salt.php';
|
||||||
|
$this->assertFileExists($file, 'ServerSalt got initialized and stored on disk');
|
||||||
|
$this->assertNotEquals($salt, '');
|
||||||
|
ServerSalt::setStore($this->_model);
|
||||||
|
ServerSalt::get();
|
||||||
|
$this->assertFileNotExists($file, 'legacy ServerSalt got removed');
|
||||||
|
$this->assertEquals($salt, ServerSalt::get(), 'ServerSalt got preserved & migrated');
|
||||||
|
}
|
||||||
|
|
||||||
public function testDatabaseBasedDataStoreWorks()
|
public function testDatabaseBasedDataStoreWorks()
|
||||||
{
|
{
|
||||||
$this->_model->delete(Helper::getPasteId());
|
$this->_model->delete(Helper::getPasteId());
|
||||||
|
|
Loading…
Reference in a new issue