parent
7da11b83f5
commit
abc34a5f1a
|
@ -8,6 +8,7 @@ use Exception;
|
|||
use Zend_Config;
|
||||
use PDOException;
|
||||
use Icinga\Web\Setup\DbTool;
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Application\Config;
|
||||
use Icinga\Web\Setup\Installer;
|
||||
use Icinga\Config\PreservingIniWriter;
|
||||
|
@ -49,6 +50,17 @@ class WebInstaller implements Installer
|
|||
{
|
||||
$success = true;
|
||||
|
||||
if (isset($this->pageData['setup_db_resource']) && ! $this->pageData['setup_db_resource']['skip_validation']) {
|
||||
try {
|
||||
$this->setupDatabase();
|
||||
} catch (Exception $e) {
|
||||
$this->log(sprintf(t('Failed to set up the database: %s'), $e->getMessage()), false);
|
||||
return false; // Bail out as early as possible as not being able to setup the database is fatal
|
||||
}
|
||||
|
||||
$this->log(t('The database has been successfully set up!'));
|
||||
}
|
||||
|
||||
$configIniPath = Config::resolvePath('config.ini');
|
||||
try {
|
||||
$this->writeConfigIni($configIniPath);
|
||||
|
@ -189,6 +201,159 @@ class WebInstaller implements Installer
|
|||
$writer->write();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the database
|
||||
*/
|
||||
protected function setupDatabase()
|
||||
{
|
||||
$resourceConfig = $this->pageData['setup_db_resource'];
|
||||
if (isset($this->pageData['setup_database_creation'])) {
|
||||
$resourceConfig['username'] = $this->pageData['setup_database_creation']['username'];
|
||||
$resourceConfig['password'] = $this->pageData['setup_database_creation']['password'];
|
||||
}
|
||||
|
||||
$db = new DbTool($resourceConfig);
|
||||
if ($resourceConfig['db'] === 'mysql') {
|
||||
$this->setupMysqlDatabase($db);
|
||||
} elseif ($resourceConfig['db'] === 'pgsql') {
|
||||
$this->setupPgsqlDatabase($db);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a MySQL database
|
||||
*
|
||||
* @param DbTool $db The database connection wrapper to use
|
||||
*
|
||||
* @todo Escape user input or make use of prepared statements!
|
||||
*/
|
||||
private function setupMysqlDatabase(DbTool $db)
|
||||
{
|
||||
try {
|
||||
$db->connectToDb();
|
||||
$this->log(sprintf(
|
||||
t('Successfully connected to existing database "%s"...'),
|
||||
$this->pageData['setup_db_resource']['dbname']
|
||||
));
|
||||
} catch (PDOException $e) {
|
||||
$db->connectToHost();
|
||||
$this->log(sprintf(
|
||||
t('Creating new database "%s"...'),
|
||||
$this->pageData['setup_db_resource']['dbname']
|
||||
));
|
||||
$db->exec('CREATE DATABASE ' . $this->pageData['setup_db_resource']['dbname']);
|
||||
$db->reconnect($this->pageData['setup_db_resource']['dbname']);
|
||||
}
|
||||
|
||||
$loginIdent = "'" . $this->pageData['setup_db_resource']['username'] . "'@'" . Platform::getFqdn() . "'";
|
||||
if (false === array_search($loginIdent, $db->listLogins())) {
|
||||
$this->log(sprintf(
|
||||
t('Creating login "%s"...'),
|
||||
$this->pageData['setup_db_resource']['username']
|
||||
));
|
||||
$db->exec(
|
||||
"CREATE USER $loginIdent IDENTIFIED BY '" .
|
||||
$this->pageData['setup_db_resource']['password'] . "'"
|
||||
);
|
||||
} else {
|
||||
$this->log(sprintf(
|
||||
t('Login "%s" already exists...'),
|
||||
$this->pageData['setup_db_resource']['username']
|
||||
));
|
||||
}
|
||||
|
||||
$diff = array_diff(array('account', 'preference'), $db->listTables());
|
||||
if (empty($diff)) {
|
||||
$this->log(t('Database schema already exists...'));
|
||||
} else {
|
||||
$this->log(t('Creating database schema...'));
|
||||
$db->import(Icinga::app()->getApplicationDir() . '/../etc/schema/mysql.sql');
|
||||
}
|
||||
|
||||
$privileges = array('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'EXECUTE', 'CREATE TEMPORARY TABLES');
|
||||
if ($db->checkPrivileges(array_merge($privileges, array('GRANT OPTION')))) {
|
||||
$this->log(sprintf(
|
||||
t('Granting required privileges to login "%s"...'),
|
||||
$this->pageData['setup_db_resource']['username']
|
||||
));
|
||||
$db->exec(sprintf(
|
||||
"GRANT %s ON %s.* TO %s",
|
||||
join(',', $privileges),
|
||||
$this->pageData['setup_db_resource']['dbname'],
|
||||
$loginIdent
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a PostgreSQL database
|
||||
*
|
||||
* @param DbTool $db The database connection wrapper to use
|
||||
*
|
||||
* @todo Escape user input or make use of prepared statements!
|
||||
*/
|
||||
private function setupPgsqlDatabase(DbTool $db)
|
||||
{
|
||||
try {
|
||||
$db->connectToDb();
|
||||
$this->log(sprintf(
|
||||
t('Successfully connected to existing database "%s"...'),
|
||||
$this->pageData['setup_db_resource']['dbname']
|
||||
));
|
||||
} catch (PDOException $e) {
|
||||
$db->connectToHost();
|
||||
$this->log(sprintf(
|
||||
t('Creating new database "%s"...'),
|
||||
$this->pageData['setup_db_resource']['dbname']
|
||||
));
|
||||
$db->exec('CREATE DATABASE ' . $this->pageData['setup_db_resource']['dbname']);
|
||||
$db->reconnect($this->pageData['setup_db_resource']['dbname']);
|
||||
}
|
||||
|
||||
if (false === array_search($this->pageData['setup_db_resource']['username'], $db->listLogins())) {
|
||||
$this->log(sprintf(
|
||||
t('Creating login "%s"...'),
|
||||
$this->pageData['setup_db_resource']['username']
|
||||
));
|
||||
$db->exec(sprintf(
|
||||
"CREATE USER %s WITH PASSWORD '%s'",
|
||||
$this->pageData['setup_db_resource']['username'],
|
||||
$this->pageData['setup_db_resource']['password']
|
||||
));
|
||||
} else {
|
||||
$this->log(sprintf(
|
||||
t('Login "%s" already exists...'),
|
||||
$this->pageData['setup_db_resource']['username']
|
||||
));
|
||||
}
|
||||
|
||||
$diff = array_diff(array('account', 'preference'), $db->listTables());
|
||||
if (empty($diff)) {
|
||||
$this->log(t('Database schema already exists...'));
|
||||
} else {
|
||||
$this->log(t('Creating database schema...'));
|
||||
$db->import(Icinga::app()->getApplicationDir() . '/../etc/schema/pgsql.sql');
|
||||
}
|
||||
|
||||
$privileges = array('SELECT', 'INSERT', 'UPDATE', 'DELETE');
|
||||
if ($db->checkPrivileges(array_merge($privileges, array('GRANT OPTION')))) {
|
||||
$this->log(sprintf(
|
||||
t('Granting required privileges to login "%s"...'),
|
||||
$this->pageData['setup_db_resource']['username']
|
||||
));
|
||||
$db->exec(sprintf(
|
||||
"GRANT %s ON TABLE account TO %s",
|
||||
join(',', $privileges),
|
||||
$this->pageData['setup_db_resource']['username']
|
||||
));
|
||||
$db->exec(sprintf(
|
||||
"GRANT %s ON TABLE preference TO %s",
|
||||
join(',', $privileges),
|
||||
$this->pageData['setup_db_resource']['username']
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Installer::getSummary()
|
||||
*/
|
||||
|
|
|
@ -9,6 +9,7 @@ use PDOException;
|
|||
use LogicException;
|
||||
use Zend_Db_Adapter_Pdo_Mysql;
|
||||
use Zend_Db_Adapter_Pdo_Pgsql;
|
||||
use Icinga\Util\File;
|
||||
use Icinga\Exception\ConfigurationError;
|
||||
|
||||
/**
|
||||
|
@ -129,6 +130,18 @@ class DbTool
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reestablish a connection with the database or just the server by omitting the database name
|
||||
*
|
||||
* @param string $dbname The name of the database to connect to
|
||||
*/
|
||||
public function reconnect($dbname = null)
|
||||
{
|
||||
$this->pdoConn = null;
|
||||
$this->zendConn = null;
|
||||
$this->connect($dbname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Zend database adapter
|
||||
*
|
||||
|
@ -228,6 +241,35 @@ class DbTool
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a SQL statement and return the affected row count
|
||||
*
|
||||
* @param string $statement The statement to execute
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function exec($statement)
|
||||
{
|
||||
return $this->pdoConn->exec($statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the given SQL file
|
||||
*
|
||||
* @param string $filepath The file to import
|
||||
*/
|
||||
public function import($filepath)
|
||||
{
|
||||
$file = new File($filepath);
|
||||
$content = join(PHP_EOL, iterator_to_array($file)); // There is no fread() before PHP 5.5 :(
|
||||
|
||||
foreach (explode(';', $content) as $statement) {
|
||||
if (($statement = trim($statement)) !== '') {
|
||||
$this->exec($statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given privileges were granted
|
||||
*
|
||||
|
@ -250,4 +292,28 @@ class DbTool
|
|||
$this->assertConnectedToDb();
|
||||
return $this->zendConn->listTables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of all available database logins
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listLogins()
|
||||
{
|
||||
$users = array();
|
||||
|
||||
if ($this->config['db'] === 'mysql') {
|
||||
$query = $this->pdoConn->query('SELECT DISTINCT grantee FROM information_schema.user_privileges');
|
||||
foreach ($query->fetchAll() as $row) {
|
||||
$users[] = $row['grantee'];
|
||||
}
|
||||
} elseif ($this->config['db'] === 'pgsql') {
|
||||
$query = $this->pdoConn->query('SELECT usename FROM pg_catalog.pg_user');
|
||||
foreach ($query->fetchAll() as $row) {
|
||||
$users[] = $row['usename'];
|
||||
}
|
||||
}
|
||||
|
||||
return $users;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue