diff options
author | Robin Appelman <icewind@owncloud.com> | 2016-07-12 13:50:54 +0200 |
---|---|---|
committer | Robin Appelman <icewind@owncloud.com> | 2016-07-12 14:38:24 +0200 |
commit | 7ffda5d10fa8831f65e42b327bbb56f847b68888 (patch) | |
tree | e3adaafbf669383f2f80f8a87c8dfc644385b2f9 /lib/private/Setup | |
parent | 8a79d314cf544cf2ca261cbac7ea07570e9ed8e5 (diff) | |
download | nextcloud-server-7ffda5d10fa8831f65e42b327bbb56f847b68888.tar.gz nextcloud-server-7ffda5d10fa8831f65e42b327bbb56f847b68888.zip |
use pdo for postgres setup
Diffstat (limited to 'lib/private/Setup')
-rw-r--r-- | lib/private/Setup/AbstractDatabase.php | 5 | ||||
-rw-r--r-- | lib/private/Setup/PostgreSQL.php | 185 |
2 files changed, 85 insertions, 105 deletions
diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php index 62e9b2e823f..8dee96b1ba5 100644 --- a/lib/private/Setup/AbstractDatabase.php +++ b/lib/private/Setup/AbstractDatabase.php @@ -101,10 +101,10 @@ abstract class AbstractDatabase { } /** + * @param array $configOverwrite * @return \OC\DB\Connection - * @throws \OC\DatabaseSetupException */ - protected function connect() { + protected function connect(array $configOverwrite = []) { $systemConfig = $this->config->getSystemConfig(); $cf = new ConnectionFactory(); $connectionParams = $cf->createConnectionParams($systemConfig); @@ -115,6 +115,7 @@ abstract class AbstractDatabase { if (!$connectionParams['password']) { $connectionParams['password'] = $this->dbPassword; } + $connectionParams = array_merge($connectionParams, $configOverwrite); return $cf->getConnection($systemConfig->getValue('dbtype', 'sqlite'), $connectionParams); } diff --git a/lib/private/Setup/PostgreSQL.php b/lib/private/Setup/PostgreSQL.php index 464d1e02e21..30ca88f53aa 100644 --- a/lib/private/Setup/PostgreSQL.php +++ b/lib/private/Setup/PostgreSQL.php @@ -26,42 +26,34 @@ */ namespace OC\Setup; +use OC\DatabaseException; +use OC\DB\QueryBuilder\Literal; +use OCP\IDBConnection; + class PostgreSQL extends AbstractDatabase { public $dbprettyname = 'PostgreSQL'; public function setupDatabase($username) { - $e_host = addslashes($this->dbHost); - $e_user = addslashes($this->dbUser); - $e_password = addslashes($this->dbPassword); - - // adding port support through installer - if(!empty($this->dbPort)) { - // casting to int to avoid malicious input - $port = (int)$this->dbPort; - } else if(strpos($e_host, ':')) { - list($e_host, $port)=explode(':', $e_host, 2); - } else { - $port=false; + $connection = $this->connect([ + 'dbname' => 'postgres' + ]); + //check for roles creation rights in postgresql + $builder = $connection->getQueryBuilder(); + $builder->automaticTablePrefix(false); + $query = $builder + ->select('rolname') + ->from('pg_roles') + ->where($builder->expr()->eq('rolcreaterole', new Literal('TRUE'))) + ->andWhere($builder->expr()->eq('rolname', $builder->createNamedParameter($this->dbUser))); + + try { + $result = $query->execute(); + $canCreateRoles = $result->rowCount() > 0; + } catch (DatabaseException $e) { + $canCreateRoles = false; } - //check if the database user has admin rights - $connection_string = "host='$e_host' dbname=postgres user='$e_user' port='$port' password='$e_password'"; - $connection = @pg_connect($connection_string); - if(!$connection) { - // Try if we can connect to the DB with the specified name - $e_dbname = addslashes($this->dbName); - $connection_string = "host='$e_host' dbname='$e_dbname' user='$e_user' port='$port' password='$e_password'"; - $connection = @pg_connect($connection_string); - - if(!$connection) - throw new \OC\DatabaseSetupException($this->trans->t('PostgreSQL connection failed'), - $this->trans->t('Please check your connection details.')); - } - $e_user = pg_escape_string($this->dbUser); - //check for roles creation rights in postgresql - $query="SELECT 1 FROM pg_roles WHERE rolcreaterole=TRUE AND rolname='$e_user'"; - $result = pg_query($connection, $query); - if($result and pg_num_rows($result) > 0) { + if($canCreateRoles) { //use the admin login data for the new database user //add prefix to the postgresql user name to prevent collisions @@ -72,7 +64,7 @@ class PostgreSQL extends AbstractDatabase { $this->createDBUser($connection); } - $systemConfig = \OC::$server->getSystemConfig(); + $systemConfig = $this->config->getSystemConfig(); $systemConfig->setValues([ 'dbuser' => $this->dbUser, 'dbpassword' => $this->dbPassword, @@ -80,98 +72,85 @@ class PostgreSQL extends AbstractDatabase { //create the database $this->createDatabase($connection); + $query = $connection->prepare("select count(*) FROM pg_class WHERE relname=? limit 1"); + $query->execute([$this->tablePrefix . "users"]); + $tablesSetup = $query->fetchColumn() > 0; // the connection to dbname=postgres is not needed anymore - pg_close($connection); + $connection->close(); // connect to the ownCloud database (dbname=$this->dbname) and check if it needs to be filled $this->dbUser = $systemConfig->getValue('dbuser'); $this->dbPassword = $systemConfig->getValue('dbpassword'); - - $e_host = addslashes($this->dbHost); - $e_dbname = addslashes($this->dbName); - $e_user = addslashes($this->dbUser); - $e_password = addslashes($this->dbPassword); - - // Fix database with port connection - if(strpos($e_host, ':')) { - list($e_host, $port)=explode(':', $e_host, 2); - } else { - $port=false; - } - - $connection_string = "host='$e_host' dbname='$e_dbname' user='$e_user' port='$port' password='$e_password'"; - $connection = @pg_connect($connection_string); - if(!$connection) { + $connection = $this->connect(); + try { + $connection->connect(); + } catch (\Exception $e) { + $this->logger->logException($e); throw new \OC\DatabaseSetupException($this->trans->t('PostgreSQL username and/or password not valid'), - $this->trans->t('You need to enter either an existing account or the administrator.')); + $this->trans->t('You need to enter either an existing account or the administrator.')); } - $query = "select count(*) FROM pg_class WHERE relname='".$this->tablePrefix."users' limit 1"; - $result = pg_query($connection, $query); - if($result) { - $row = pg_fetch_row($result); - } - if(!$result or $row[0]==0) { + + + if(!$tablesSetup) { \OC_DB::createDbFromStructure($this->dbDefinitionFile); } } - private function createDatabase($connection) { - //we can't use OC_BD functions here because we need to connect as the administrative user. - $e_name = pg_escape_string($this->dbName); - $e_user = pg_escape_string($this->dbUser); - $query = "select datname from pg_database where datname = '$e_name'"; - $result = pg_query($connection, $query); - if(!$result) { - $entry = $this->trans->t('DB Error: "%s"', array(pg_last_error($connection))) . '<br />'; - $entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />'; - \OCP\Util::writeLog('setup.pg', $entry, \OCP\Util::WARN); - } - if(! pg_fetch_row($result)) { + private function createDatabase(IDBConnection $connection) { + if(!$this->databaseExists($connection)) { //The database does not exists... let's create it - $query = "CREATE DATABASE \"$e_name\" OWNER \"$e_user\""; - $result = pg_query($connection, $query); - if(!$result) { - $entry = $this->trans->t('DB Error: "%s"', array(pg_last_error($connection))) . '<br />'; - $entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />'; - \OCP\Util::writeLog('setup.pg', $entry, \OCP\Util::WARN); + $query = $connection->prepare("CREATE DATABASE " . addslashes($this->dbName) . " OWNER " . addslashes($this->dbUser)); + try { + $query->execute(); + } catch (DatabaseException $e) { + $this->logger->error('Error while trying to create database'); + $this->logger->logException($e); } - else { - $query = "REVOKE ALL PRIVILEGES ON DATABASE \"$e_name\" FROM PUBLIC"; - pg_query($connection, $query); + } else { + $query = $connection->prepare("REVOKE ALL PRIVILEGES ON DATABASE " . addslashes($this->dbName) . " FROM PUBLIC"); + try { + $query->execute(); + } catch (DatabaseException $e) { + $this->logger->error('Error while trying to restrict database permissions'); + $this->logger->logException($e); } } } - private function createDBUser($connection) { - $e_name = pg_escape_string($this->dbUser); - $e_password = pg_escape_string($this->dbPassword); - $query = "select * from pg_roles where rolname='$e_name';"; - $result = pg_query($connection, $query); - if(!$result) { - $entry = $this->trans->t('DB Error: "%s"', array(pg_last_error($connection))) . '<br />'; - $entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />'; - \OCP\Util::writeLog('setup.pg', $entry, \OCP\Util::WARN); - } + private function userExists(IDBConnection $connection) { + $builder = $connection->getQueryBuilder(); + $builder->automaticTablePrefix(false); + $query = $builder->select('*') + ->from('pg_roles') + ->where($builder->expr()->eq('rolname', $builder->createNamedParameter($this->dbUser))); + $result = $query->execute(); + return $result->rowCount() > 0; + } - if(! pg_fetch_row($result)) { - //user does not exists let's create it :) - $query = "CREATE USER \"$e_name\" CREATEDB PASSWORD '$e_password';"; - $result = pg_query($connection, $query); - if(!$result) { - $entry = $this->trans->t('DB Error: "%s"', array(pg_last_error($connection))) . '<br />'; - $entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />'; - \OCP\Util::writeLog('setup.pg', $entry, \OCP\Util::WARN); - } - } - else { // change password of the existing role - $query = "ALTER ROLE \"$e_name\" WITH PASSWORD '$e_password';"; - $result = pg_query($connection, $query); - if(!$result) { - $entry = $this->trans->t('DB Error: "%s"', array(pg_last_error($connection))) . '<br />'; - $entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />'; - \OCP\Util::writeLog('setup.pg', $entry, \OCP\Util::WARN); + private function databaseExists(IDBConnection $connection) { + $builder = $connection->getQueryBuilder(); + $builder->automaticTablePrefix(false); + $query = $builder->select('datname') + ->from('pg_database') + ->where($builder->expr()->eq('datname', $builder->createNamedParameter($this->dbName))); + $result = $query->execute(); + return $result->rowCount() > 0; + } + + private function createDBUser(IDBConnection $connection) { + try { + if ($this->userExists($connection, $this->dbUser)) { + // change the password + $query = $connection->prepare("ALTER ROLE " . addslashes($this->dbUser) . " CREATEDB WITH PASSWORD " . addslashes($this->dbPassword)); + } else { + // create the user + $query = $connection->prepare("CREATE USER " . addslashes($this->dbUser) . " CREATEDB PASSWORD " . addslashes($this->dbPassword)); } + $query->execute(); + } catch (DatabaseException $e) { + $this->logger->error('Error while trying to create database user'); + $this->logger->logException($e); } } } |