From 3ecc840572ac2a208859cd0d31f7125fc015b75f Mon Sep 17 00:00:00 2001 From: Stephen Shkardoon Date: Fri, 22 Mar 2013 03:04:51 +1300 Subject: [PATCH] Check for ALTER TABLE in installer (fixes #853) --- dev/install/DatabaseConfigurationHelper.php | 10 +++++ .../MySQLDatabaseConfigurationHelper.php | 41 +++++++++++++++++++ dev/install/install.php5 | 27 +++++++++++- 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/dev/install/DatabaseConfigurationHelper.php b/dev/install/DatabaseConfigurationHelper.php index 2a194c6b5..fd086b26e 100644 --- a/dev/install/DatabaseConfigurationHelper.php +++ b/dev/install/DatabaseConfigurationHelper.php @@ -39,4 +39,14 @@ interface DatabaseConfigurationHelper { */ public function requireDatabaseOrCreatePermissions($databaseConfig); + + /** + * Ensure we have permissions to alter tables. + * + * @param array $databaseConfig Associative array of db configuration, e.g. "server", "username" etc + * @return array Result - e.g. array('okay' => true, 'applies' => true), where applies is whether + * the test is relevant for the database + */ + public function requireDatabaseAlterPermissions($databaseConfig); + } diff --git a/dev/install/MySQLDatabaseConfigurationHelper.php b/dev/install/MySQLDatabaseConfigurationHelper.php index f86009610..dec1044e1 100644 --- a/dev/install/MySQLDatabaseConfigurationHelper.php +++ b/dev/install/MySQLDatabaseConfigurationHelper.php @@ -134,4 +134,45 @@ class MySQLDatabaseConfigurationHelper implements DatabaseConfigurationHelper { ); } + /** + * Ensure we have permissions to alter tables. + * + * @param array $databaseConfig Associative array of db configuration, e.g. "server", "username" etc + * @return array Result - e.g. array('okay' => true, 'applies' => true), where applies is whether + * the test is relevant for the database + */ + public function requireDatabaseAlterPermissions($databaseConfig) { + $success = false; + $conn = new MySQLi($databaseConfig['server'], $databaseConfig['username'], $databaseConfig['password']); + if($conn) { + if ($res = $conn->query('SHOW GRANTS')) { + // Annoyingly, MySQL 'escapes' the database, so we need to do it too. + $db = str_replace(array('%', '_', '`'), array('\%', '\_', '``'), $databaseConfig['database']); + while ($row = $res->fetch_array()) { + if (preg_match('/^GRANT (.+) ON (.+) TO/', $row[0], $matches) && (count($matches) == 2)) { + // Need to change to an array of permissions, because ALTER is contained in ALTER ROUTINES. + $permission = array_map('trim', explode(',', $matches[1])); + $on_database = $matches[2]; + // The use of both ` and " is because of ANSI mode. + if (in_array('ALL PRIVILEGES', $permission) and ( + ($on_database == '*.*') or ($on_database == '`' . $db . '`.*') + or ($on_database == '"' . $db . '".*'))) { + $success = true; + break; + } + if (in_array('ALTER', $permission) and ( + ($on_database == '*.*') or ($on_database == '`' . $db . '`.*') + or ($on_database == '"' . $db . '".*'))) { + $success = true; + break; + } + } + } + } + } + return array( + 'success' => $success, + 'applies' => true + ); + } } diff --git a/dev/install/install.php5 b/dev/install/install.php5 index 08aff9a80..2eaae5872 100644 --- a/dev/install/install.php5 +++ b/dev/install/install.php5 @@ -311,14 +311,23 @@ class InstallRequirements { 'Version ' . $this->getDatabaseConfigurationHelper($databaseConfig['type'])->getDatabaseVersion($databaseConfig) ) )) { - $this->requireDatabaseOrCreatePermissions( + if($this->requireDatabaseOrCreatePermissions( $databaseConfig, array( "Database Configuration", "Can I access/create the database", "I can't create new databases and the database '$databaseConfig[database]' doesn't exist" ) - ); + )) { + $this->requireDatabaseAlterPermissions( + $databaseConfig, + array( + "Database Configuration", + "Can I ALTER tables", + "I don't have permission to ALTER tables" + ) + ); + } } } } @@ -913,6 +922,20 @@ class InstallRequirements { } } + function requireDatabaseAlterPermissions($databaseConfig, $testDetails) { + $this->testing($testDetails); + $helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']); + $result = $helper->requireDatabaseAlterPermissions($databaseConfig); + if ($result['success']) { + return true; + } else { + $testDetails[2] = "Silverstripe cannot alter tables. This won't prevent installation, however it may " + . "cause issues if you try to run a /dev/build once installed."; + $this->warning($testDetails); + return; + } + } + function requireServerVariables($varNames, $errorMessage) { //$this->testing($testDetails); foreach($varNames as $varName) {