[TASK] Migrate ext:rsaauth to use Doctrine DBAL. 16/48516/3
authorRolf Hofmann <rolf.hofmann@dkd.de>
Wed, 8 Jun 2016 18:39:39 +0000 (20:39 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Thu, 9 Jun 2016 08:15:40 +0000 (10:15 +0200)
Resolves: #76516
Releases: master
Change-Id: Idda46dc5c83c645f5c5c4aa274a1ae2c3fe31040
Reviewed-on: https://review.typo3.org/48516
Reviewed-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Tested-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/rsaauth/Classes/Storage/SplitStorage.php
typo3/sysext/rsaauth/Tests/Functional/Fixtures/tx_rsaauth_keys.xml [new file with mode: 0644]
typo3/sysext/rsaauth/Tests/Functional/Storage/SplitStorageTest.php [new file with mode: 0644]

index 8839ba8..d2bf106 100644 (file)
@@ -14,7 +14,8 @@ namespace TYPO3\CMS\Rsaauth\Storage;
  * The TYPO3 project - inspiring people to share!
  */
 
-use TYPO3\CMS\Core\Database\DatabaseConnection;
+use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 
 /**
@@ -24,22 +25,14 @@ use TYPO3\CMS\Core\Utility\MathUtility;
 class SplitStorage extends AbstractStorage
 {
     /**
-     * @var DatabaseConnection;
-     */
-    protected $databaseConnection;
-
-    /**
      * Creates an instance of this class. It checks and initializes PHP
      * sessions if necessary.
-     *
-     * @param DatabaseConnection $databaseConnection A database connection may be injected here
      */
-    public function __construct(DatabaseConnection $databaseConnection = null)
+    public function __construct()
     {
         if (session_id() === '') {
             session_start();
         }
-        $this->databaseConnection = $databaseConnection ?: $GLOBALS['TYPO3_DB'];
     }
 
     /**
@@ -53,14 +46,19 @@ class SplitStorage extends AbstractStorage
         $result = null;
         list($keyId, $keyPart1) = $_SESSION['tx_rsaauth_key'];
         if (MathUtility::canBeInterpretedAsInteger($keyId)) {
-            // Remove expired keys (more than 30 minutes old)
-            $this->databaseConnection->exec_DELETEquery('tx_rsaauth_keys', 'crdate<' . ($GLOBALS['EXEC_TIME'] - 30 * 60));
+            $this->removeExpiredKeys();
+
             // Get our value
-            $row = $this->databaseConnection->exec_SELECTgetSingleRow('key_value', 'tx_rsaauth_keys', 'uid=' . $keyId);
-            if (is_array($row)) {
-                $result = $keyPart1 . $row['key_value'];
+            $keyValue = GeneralUtility::makeInstance(ConnectionPool::class)
+                ->getConnectionForTable('tx_rsaauth_keys')
+                ->select(['key_value'], 'tx_rsaauth_keys', ['uid' => $keyId])
+                ->fetchColumn();
+
+            if ($keyValue !== false) {
+                $result = $keyPart1 . $keyValue;
             }
         }
+
         return $result;
     }
 
@@ -73,18 +71,29 @@ class SplitStorage extends AbstractStorage
      */
     public function put($key)
     {
+        $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('tx_rsaauth_keys');
         if ($key == null) {
             // Remove existing key
             list($keyId) = $_SESSION['tx_rsaauth_key'];
             if (MathUtility::canBeInterpretedAsInteger($keyId)) {
-                $this->databaseConnection->exec_DELETEquery('tx_rsaauth_keys', 'uid=' . $keyId);
+                $connection->delete(
+                    'tx_rsaauth_keys',
+                    ['uid' => $keyId]
+                );
                 unset($_SESSION['tx_rsaauth_key']);
                 if (empty($_SESSION)) {
                     $sessionName = session_name();
                     $sessionCookie = session_get_cookie_params();
                     session_destroy();
                     // By using setcookie with the second parameter set to false we actually delete the cookie
-                    setcookie($sessionName, false, $sessionCookie['lifetime'], $sessionCookie['path'], $sessionCookie['domain'], $sessionCookie['secure']);
+                    setcookie(
+                        $sessionName,
+                        false,
+                        $sessionCookie['lifetime'],
+                        $sessionCookie['path'],
+                        $sessionCookie['domain'],
+                        $sessionCookie['secure']
+                    );
                 }
             }
         } else {
@@ -101,16 +110,34 @@ class SplitStorage extends AbstractStorage
             // Notice: we may not use TCEmain below to insert key part into the
             // table because TCEmain requires a valid BE user!
             $time = $GLOBALS['EXEC_TIME'];
-            $this->databaseConnection->exec_INSERTquery('tx_rsaauth_keys', array(
-                'pid' => 0,
-                'crdate' => $time,
-                'key_value' => $keyPart2
-            ));
-            $keyId = $this->databaseConnection->sql_insert_id();
+            $connection->insert(
+                'tx_rsaauth_keys',
+                [
+                    'pid' => 0,
+                    'crdate' => $time,
+                    'key_value' => $keyPart2
+                ]
+            );
+            $keyId = $connection->lastInsertId();
             // Store another part in session
             $_SESSION['tx_rsaauth_key'] = array($keyId, $keyPart1);
         }
-        // Remove expired keys (more than 30 minutes old)
-        $this->databaseConnection->exec_DELETEquery('tx_rsaauth_keys', 'crdate<' . ($GLOBALS['EXEC_TIME'] - 30 * 60));
+
+        $this->removeExpiredKeys();
+    }
+
+    /**
+     * Remove expired keys (more than 30 minutes old).
+     *
+     * @return int The number of expired keys that have been removed
+     */
+    protected function removeExpiredKeys(): int
+    {
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_rsaauth_keys');
+        $count = $queryBuilder->delete('tx_rsaauth_keys')
+            ->where($queryBuilder->expr()->lt('crdate', ($GLOBALS['EXEC_TIME'] - 30 * 60)))
+            ->execute();
+
+        return (int)$count;
     }
 }
diff --git a/typo3/sysext/rsaauth/Tests/Functional/Fixtures/tx_rsaauth_keys.xml b/typo3/sysext/rsaauth/Tests/Functional/Fixtures/tx_rsaauth_keys.xml
new file mode 100644 (file)
index 0000000..a0cce58
--- /dev/null
@@ -0,0 +1,21 @@
+<dataset>
+       <tx_rsaauth_keys>
+               <uid>1</uid>
+               <pid>0</pid>
+               <crdate>1465391843</crdate><!-- Mi  8 Jun 2016 15:17:23 CEST  -->
+               <key_value>df67571bbdc5beca</key_value>
+       </tx_rsaauth_keys>
+       <tx_rsaauth_keys>
+               <uid>2</uid>
+               <pid>0</pid>
+               <crdate>1465391843</crdate><!-- Mi  8 Jun 2016 15:17:23 CEST  -->
+               <key_value>df67571bbdc5beca</key_value>
+       </tx_rsaauth_keys>
+       <tx_rsaauth_keys>
+               <uid>3</uid>
+               <pid>0</pid>
+               <crdate>1465389983</crdate><!-- Mi  8 Jun 2016 14:46:23 CEST  -->
+               <key_value>df67571bbdc5beca</key_value>
+       </tx_rsaauth_keys>
+</dataset>
+
diff --git a/typo3/sysext/rsaauth/Tests/Functional/Storage/SplitStorageTest.php b/typo3/sysext/rsaauth/Tests/Functional/Storage/SplitStorageTest.php
new file mode 100644 (file)
index 0000000..4a34fd3
--- /dev/null
@@ -0,0 +1,173 @@
+<?php
+namespace TYPO3\CMS\Rsaauth\Tests\Functional\Storage;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Rsaauth\Storage\SplitStorage;
+
+/**
+ * Test case.
+ */
+class SplitStorageTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase
+{
+    /**
+     * XML database fixtures to be loaded into database.
+     *
+     * @var array
+     */
+    protected $xmlDatabaseFixtures = [
+        'typo3/sysext/rsaauth/Tests/Functional/Fixtures/tx_rsaauth_keys.xml'
+    ];
+
+    /**
+     * Core extensions to load
+     *
+     * @var array
+     */
+    protected $testExtensionsToLoad = [
+        'typo3/sysext/rsaauth'
+    ];
+
+    /**
+     * @var SplitStorage
+     */
+    protected $subject;
+
+    /**
+     * @var string
+     */
+    protected $testKey = '666cb6d79dc65973df67571bbdc5beca';
+
+    /**
+     * @var string
+     */
+    protected $testKeyLeftPart = '666cb6d79dc65973';
+
+    /**
+     * @var string
+     */
+    protected $testKeyRightPart = 'df67571bbdc5beca';
+
+    /**
+     * Sets up this test suite.
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+        foreach ($this->xmlDatabaseFixtures as $fixture) {
+            $this->importDataSet($fixture);
+        }
+        $this->subject = GeneralUtility::makeInstance(SplitStorage::class);
+        // same timestamp as in Fixtures/tx_rsaauth_keys.xml
+        $GLOBALS['EXEC_TIME'] = 1465391843;
+        $_SESSION['tx_rsaauth_key'] = [1, $this->testKeyLeftPart];
+    }
+
+    /**
+     * @test
+     */
+    public function getReturnsKeyFromDatabase()
+    {
+        $key = $this->subject->get();
+        $this->assertEquals($this->testKey, $key);
+    }
+
+    /**
+     * @test
+     */
+    public function putInsertsKeyIntoDatabase()
+    {
+        $this->subject->put($this->testKey);
+        $this->assertEquals($this->testKey, $this->subject->get());
+    }
+
+    /**
+     * @test
+     */
+    public function getDeletesKeysOlderThan30Minutes()
+    {
+        $outDatedKeyId = 3;
+        $_SESSION['tx_rsaauth_key'] = [1, $this->testKeyLeftPart];
+
+        $key = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getConnectionForTable('tx_rsaauth_keys')
+            ->select(['key_value'], 'tx_rsaauth_keys', ['uid' => $outDatedKeyId])
+            ->fetchColumn();
+
+        $this->assertEquals($this->testKeyRightPart, $key);
+
+        $result = $this->subject->get();
+
+        $key = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getConnectionForTable('tx_rsaauth_keys')
+            ->select(['key_value'], 'tx_rsaauth_keys', ['uid' => $outDatedKeyId])
+            ->fetchColumn();
+
+        $this->assertFalse($key);
+    }
+
+    /**
+     * @test
+     */
+    public function putDeletesKeysOlderThan30Minutes()
+    {
+        $outDatedKeyId = 3;
+        $_SESSION['tx_rsaauth_key'] = [1, $this->testKeyLeftPart];
+
+        $key = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getConnectionForTable('tx_rsaauth_keys')
+            ->select(['key_value'], 'tx_rsaauth_keys', ['uid' => $outDatedKeyId])
+            ->fetchColumn();
+
+        $this->assertEquals($this->testKeyRightPart, $key);
+
+        $this->subject->put('testkey');
+
+        $key = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getConnectionForTable('tx_rsaauth_keys')
+            ->select(['key_value'], 'tx_rsaauth_keys', ['uid' => $outDatedKeyId])
+            ->fetchColumn();
+
+        $this->assertFalse($key);
+    }
+
+    /**
+     * @test
+     */
+    public function putDeletesCurrentKeyIfNullIsGiven()
+    {
+        $keyToBeDeleted = 1;
+        $_SESSION['tx_rsaauth_key'] = [$keyToBeDeleted, $this->testKeyLeftPart];
+
+        $key = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getConnectionForTable('tx_rsaauth_keys')
+            ->select(['key_value'], 'tx_rsaauth_keys', ['uid' => $keyToBeDeleted])
+            ->fetchColumn();
+
+        $this->assertEquals($this->testKeyRightPart, $key);
+
+        $this->subject->put(null);
+
+        $key = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getConnectionForTable('tx_rsaauth_keys')
+            ->select(['key_value'], 'tx_rsaauth_keys', ['uid' => $keyToBeDeleted])
+            ->fetchColumn();
+
+        $this->assertFalse($key);
+    }
+}