From cdd42360013b19f4c11a02392556ea84b6effad7 Mon Sep 17 00:00:00 2001
From: Tim van Dijen <tim.dijen@minbzk.nl>
Date: Fri, 2 Aug 2019 10:52:12 +0200
Subject: [PATCH] Convert TIMESTAMP to DATETIME; fixes #1155

---
 modules/saml/lib/SP/LogoutStore.php | 56 +++++++++++++++++++++++++++--
 1 file changed, 53 insertions(+), 3 deletions(-)

diff --git a/modules/saml/lib/SP/LogoutStore.php b/modules/saml/lib/SP/LogoutStore.php
index b1e4cecde..b1acee461 100644
--- a/modules/saml/lib/SP/LogoutStore.php
+++ b/modules/saml/lib/SP/LogoutStore.php
@@ -26,9 +26,59 @@ class LogoutStore
     private static function createLogoutTable(Store\SQL $store)
     {
         $tableVer = $store->getTableVersion('saml_LogoutStore');
-        if ($tableVer === 3) {
+        if ($tableVer === 4) {
             return;
+        } elseif ($tableVer === 3) {
+            /**
+             * Table version 4 fixes the column type for the _expire column.
+             * We now use DATETIME instead of TIMESTAMP to support MSSQL.
+             */
+            switch ($store->driver) {
+                case 'pgsql':
+                    // This does not affect the NOT NULL constraint
+                    $update = ['ALTER TABLE '.$store->prefix.
+                        '_saml_LogoutStore ALTER COLUMN _expire DATETIME'];
+                    break;
+                case  'sqlite':
+                    /**
+                     * TableVersion 2 increased the column size to 255 which is the maximum length of a FQDN
+                     * Because SQLite does not support field alterations, the approach is to:
+                     *     Create a new table without the proper column size
+                     *     Copy the current data to the new table
+                     *     Drop the old table
+                     *     Rename the new table correctly
+                     *     Read the index
+                     */
+                    $update = [
+                        'CREATE TABLE '.$store->prefix.'_saml_LogoutStore_new (_authSource VARCHAR(255) NOT NULL,'.
+                        '_nameId VARCHAR(40) NOT NULL, _sessionIndex VARCHAR(50) NOT NULL, _expire DATETIME NOT NULL,'.
+                        '_sessionId VARCHAR(50) NOT NULL, UNIQUE (_authSource, _nameID, _sessionIndex))',
+                        'INSERT INTO '.$store->prefix.'_saml_LogoutStore_new SELECT * FROM '.$store->prefix.'_saml_LogoutStore',
+                        'DROP TABLE '.$store->prefix.'_saml_LogoutStore',
+                        'ALTER TABLE '.$store->prefix.'_saml_LogoutStore_new RENAME TO '.$store->prefix.'_saml_LogoutStore',
+                        'CREATE INDEX '.$store->prefix.'_saml_LogoutStore_expire ON '.$store->prefix.'_saml_LogoutStore (_expire)',
+                        'CREATE INDEX '.$store->prefix.'_saml_LogoutStore_nameId ON '.$store->prefix.'_saml_LogoutStore (_authSource, _nameId)'
+                    ];
+                    break;
+                default:
+                    $update = ['ALTER TABLE '.$store->prefix.
+                        '_saml_LogoutStore MODIFY _expire DATETIME NOT NULL'];
+                    break;
+            }
+
+            try {
+                foreach ($update as $query) {
+                    $store->pdo->exec($query);
+                }
+            } catch (\Exception $e) {
+                Logger::warning('Database error: '.var_export($store->pdo->errorInfo(), true));
+                return;
+            }
+            $store->setTableVersion('saml_LogoutStore', 4);
+            return;
+
         } elseif ($tableVer === 2) {
+            // TableVersion 3 fixes the indexes that were set to 255 in version 2; they cannot be larger than 191
             // Drop old indexes
             $query = 'ALTER TABLE '.$store->prefix.'_saml_LogoutStore DROP INDEX '.$store->prefix.'_saml_LogoutStore_nameId';
             $store->pdo->exec($query);
@@ -96,7 +146,7 @@ class LogoutStore
             _authSource VARCHAR(255) NOT NULL,
             _nameId VARCHAR(40) NOT NULL,
             _sessionIndex VARCHAR(50) NOT NULL,
-            _expire TIMESTAMP NOT NULL,
+            _expire DATETIME NOT NULL,
             _sessionId VARCHAR(50) NOT NULL,
             UNIQUE (_authSource(191), _nameID, _sessionIndex)
         )';
@@ -110,7 +160,7 @@ class LogoutStore
         $query .= $store->prefix.'_saml_LogoutStore (_authSource(191), _nameId)';
         $store->pdo->exec($query);
 
-        $store->setTableVersion('saml_LogoutStore', 3);
+        $store->setTableVersion('saml_LogoutStore', 4);
     }
 
 
-- 
GitLab