Ver Fonte

implementing key/value store of Persistance in Database storage

El RIDO há 5 anos atrás
pai
commit
a203e6322b

+ 1 - 0
CHANGELOG.md

@@ -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)

+ 19 - 1
lib/Data/AbstractData.php

@@ -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.

+ 41 - 30
lib/Data/Database.php

@@ -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,20 +434,19 @@ class Database extends AbstractData
      */
      */
     public function setValue($value, $namespace, $key = '')
     public function setValue($value, $namespace, $key = '')
     {
     {
-        switch ($namespace) {
-            case 'purge_limiter':
-                ;
-                break;
-            case 'salt':
-                ;
-                break;
-            case 'traffic_limiter':
-                ;
-                break;
-            default:
+        if ($namespace === 'traffic_limiter') {
+            self::$_traffic_limiter_cache[$key] = $value;
+            try {
+                $value = Json::encode(self::$_traffic_limiter_cache);
+            } catch (Exception $e) {
                 return false;
                 return false;
-                break;
+            }
         }
         }
+        return self::_exec(
+            'UPDATE ' . self::_sanitizeIdentifier('config') .
+            ' SET value = ? WHERE id = ?',
+            array($value, strtoupper($namespace))
+        );
     }
     }
 
 
     /**
     /**
@@ -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']: '';
     }
     }
 
 
     /**
     /**

+ 0 - 30
lib/Data/Filesystem.php

@@ -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.
      *
      *

+ 5 - 4
lib/Data/GoogleCloudStorage.php

@@ -227,10 +227,11 @@ class GoogleCloudStorage extends AbstractData
      */
      */
     public function purgeValues($namespace, $time)
     public function purgeValues($namespace, $time)
     {
     {
-        switch ($namespace) {
-            case 'traffic_limiter':
-                ;
-                break;
+        if ($namespace === '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
+            // self::$_traffic_limiter_cache in a similar way as the other
+            // implementations.
         }
         }
     }
     }
 
 

+ 1 - 0
tst/ControllerTest.php

@@ -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();
     }
     }

+ 4 - 0
tst/ControllerWithDbTest.php

@@ -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();
     }
     }
 
 

+ 15 - 0
tst/Data/DatabaseTest.php

@@ -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());