diff --git a/lib/SimpleSAML/Store/SQLStore.php b/lib/SimpleSAML/Store/SQLStore.php index 19df280d792e63d2006bcea2501a660da05532f4..640bbb5dafcb56c2041cb7b27cc696b76bd32e72 100644 --- a/lib/SimpleSAML/Store/SQLStore.php +++ b/lib/SimpleSAML/Store/SQLStore.php @@ -95,7 +95,7 @@ class SQLStore implements StoreInterface } while (($row = $fetchTableVersion->fetch(PDO::FETCH_ASSOC)) !== false) { - $this->tableVersions[$row['_name']] = (int) $row['_version']; + $this->tableVersions[$row['_name']] = intval($row['_version']); } } @@ -105,74 +105,37 @@ class SQLStore implements StoreInterface */ private function initKVTable(): void { - $current_version = $this->getTableVersion('kvstore'); + $tableVer = $this->getTableVersion('kvstore'); + if ($tableVer === 2) { + return; + } elseif ($tableVer < 2 && $tableVer > 0) { + throw new Exception('No upgrade path available. Please migrate to the latest 1.16+ version of SimpleSAMLphp first before upgrading to 2.x.'); + } $text_t = 'TEXT'; - $time_field = 'TIMESTAMP'; if ($this->driver === 'mysql') { // TEXT data type has size constraints that can be hit at some point, so we use LONGTEXT instead $text_t = 'LONGTEXT'; } + + $time_field = 'TIMESTAMP'; if ($this->driver === 'sqlsrv') { // TIMESTAMP will not work for MSSQL. TIMESTAMP is automatically generated and cannot be inserted // so we use DATETIME instead $time_field = 'DATETIME'; } - /** - * Queries for updates, grouped by version. - * New updates can be added as a new array in this array - */ - $table_updates = [ - [ - 'CREATE TABLE ' . $this->prefix . - '_kvstore (_type VARCHAR(30) NOT NULL, _key VARCHAR(50) NOT NULL, _value ' . $text_t . - ' NOT NULL, _expire ' . $time_field . ', PRIMARY KEY (_key, _type))', - $this->driver === 'sqlite' || $this->driver === 'sqlsrv' || $this->driver === 'pgsql' ? - 'CREATE INDEX ' . $this->prefix . '_kvstore_expire ON ' . $this->prefix . '_kvstore (_expire)' : - 'ALTER TABLE ' . $this->prefix . '_kvstore ADD INDEX ' . $this->prefix . '_kvstore_expire (_expire)' - ], - /** - * This upgrade removes the default NOT NULL constraint on the _expire field in MySQL. - * Because SQLite does not support field alterations, the approach is to: - * Create a new table without the NOT NULL constraint - * Copy the current data to the new table - * Drop the old table - * Rename the new table correctly - * Read the index - */ - [ - 'CREATE TABLE ' . $this->prefix . - '_kvstore_new (_type VARCHAR(30) NOT NULL, _key VARCHAR(50) NOT NULL, _value ' . $text_t . - ' NOT NULL, _expire ' . $time_field . ' NULL, PRIMARY KEY (_key, _type))', - 'INSERT INTO ' . $this->prefix . '_kvstore_new SELECT * FROM ' . $this->prefix . '_kvstore', - 'DROP TABLE ' . $this->prefix . '_kvstore', - // FOR MSSQL use EXEC sp_rename to rename a table (RENAME won't work) - $this->driver === 'sqlsrv' ? - 'EXEC sp_rename ' . $this->prefix . '_kvstore_new, ' . $this->prefix . '_kvstore' : - 'ALTER TABLE ' . $this->prefix . '_kvstore_new RENAME TO ' . $this->prefix . '_kvstore', - $this->driver === 'sqlite' || $this->driver === 'sqlsrv' || $this->driver === 'pgsql' ? - 'CREATE INDEX ' . $this->prefix . '_kvstore_expire ON ' . $this->prefix . '_kvstore (_expire)' : - 'ALTER TABLE ' . $this->prefix . '_kvstore ADD INDEX ' . $this->prefix . '_kvstore_expire (_expire)' - ] - ]; - - $latest_version = count($table_updates); - - if ($current_version == $latest_version) { - return; - } - - // Only run queries for after the current version - $updates_to_run = array_slice($table_updates, $current_version); + $query = 'CREATE TABLE ' . $this->prefix . + '_kvstore (_type VARCHAR(30) NOT NULL, _key VARCHAR(50) NOT NULL, _value ' . $text_t . + ' NOT NULL, _expire ' . $time_field . ' NULL, PRIMARY KEY (_key, _type))'; + $this->pdo->exec($query); - foreach ($updates_to_run as $version_updates) { - foreach ($version_updates as $query) { - $this->pdo->exec($query); - } - } + $query = $this->driver === 'sqlite' || $this->driver === 'sqlsrv' || $this->driver === 'pgsql' ? + 'CREATE INDEX ' . $this->prefix . '_kvstore_expire ON ' . $this->prefix . '_kvstore (_expire)' : + 'ALTER TABLE ' . $this->prefix . '_kvstore ADD INDEX ' . $this->prefix . '_kvstore_expire (_expire)'; + $this->pdo->exec($query); - $this->setTableVersion('kvstore', $latest_version); + $this->setTableVersion('kvstore', 2); } diff --git a/modules/saml/lib/SP/LogoutStore.php b/modules/saml/lib/SP/LogoutStore.php index c9bea7c808dec29172f7291a8e952ebaca30fb8b..ef6f258e9fef51bf8250a01facbeb74a338c21fe 100644 --- a/modules/saml/lib/SP/LogoutStore.php +++ b/modules/saml/lib/SP/LogoutStore.php @@ -32,156 +32,8 @@ class LogoutStore $tableVer = $store->getTableVersion('saml_LogoutStore'); 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 TYPE TIMESTAMP' - ]; - break; - case 'sqlsrv': - $update = [ - 'ALTER TABLE ' . $store->prefix . '_saml_LogoutStore ALTER COLUMN _expire DATETIME NOT NULL' - ]; - break; - case 'sqlite': - /** - * 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 on MySQL - */ - - if ($store->driver === 'mysql') { - // Drop old indexes - $query = 'ALTER TABLE ' . $store->prefix . '_saml_LogoutStore DROP INDEX ' . - $store->prefix . '_saml_LogoutStore_nameId'; - $store->pdo->exec($query); - $query = 'ALTER TABLE ' . $store->prefix . '_saml_LogoutStore DROP INDEX _authSource'; - $store->pdo->exec($query); - - // Create new indexes - $query = 'CREATE INDEX ' . $store->prefix . '_saml_LogoutStore_nameId ON '; - $query .= $store->prefix . '_saml_LogoutStore (_authSource(191), _nameId)'; - $store->pdo->exec($query); - - $query = 'ALTER TABLE ' . $store->prefix . - '_saml_LogoutStore ADD UNIQUE KEY (_authSource(191), _nameID, _sessionIndex)'; - $store->pdo->exec($query); - } - - $store->setTableVersion('saml_LogoutStore', 3); - return; - } elseif ($tableVer === 1) { - // TableVersion 2 increased the column size to 255 (191 for mysql) which is the maximum length of a FQDN - switch ($store->driver) { - case 'pgsql': - // This does not affect the NOT NULL constraint - $update = [ - 'ALTER TABLE ' . $store->prefix . - '_saml_LogoutStore ALTER COLUMN _authSource TYPE VARCHAR(255)']; - break; - case 'sqlsrv': - $update = [ - 'ALTER TABLE ' . $store->prefix . - '_saml_LogoutStore ALTER COLUMN _authSource VARCHAR(255) NOT NULL' - ]; - break; - case 'sqlite': - /** - * 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 TIMESTAMP 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; - case 'mysql': - $update = [ - 'ALTER TABLE ' . $store->prefix . - '_saml_LogoutStore MODIFY _authSource VARCHAR(191) NOT NULL' - ]; - break; - default: - $update = [ - 'ALTER TABLE ' . $store->prefix . - '_saml_LogoutStore MODIFY _authSource VARCHAR(255) 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', 2); - return; + } elseif ($tableVer < 4 && $tableVer > 0) { + throw new Exception('No upgrade path available. Please migrate to the latest 1.18+ version of SimpleSAMLphp first before upgrading to 2.x.'); } $query = 'CREATE TABLE ' . $store->prefix . '_saml_LogoutStore (