icingaweb2/application/forms/Setup/DatabaseCreationPage.php
Matthias Jentsch 2e8c0cffe6 Check privileges of database user accounts before continuing with the setup
Implement owner and privilege checks for postgresql, and fix some errors in
existing MySQL privilege checks.

resolves #7389
2014-10-27 15:08:52 +01:00

204 lines
6.1 KiB
PHP

<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Setup;
use PDOException;
use Icinga\Web\Form;
use Icinga\Web\Form\Element\Note;
use Icinga\Web\Setup\DbTool;
/**
* Wizard page to define a database user that is able to create databases and tables
*/
class DatabaseCreationPage extends Form
{
/**
* The resource configuration to use
*
* @var array
*/
protected $config;
/**
* The required database privileges
*
* @var array
*/
protected $databasePrivileges;
/**
* Initialize this page
*/
public function init()
{
$this->setName('setup_database_creation');
}
/**
* Set the resource configuration to use
*
* @param array $config
*
* @return self
*/
public function setResourceConfig(array $config)
{
$this->config = $config;
return $this;
}
/**
* Set the required database privileges
*
* @param array $privileges The required privileges
*
* @return self
*/
public function setDatabasePrivileges(array $privileges)
{
$this->databasePrivileges = $privileges;
return $this;
}
/**
* @see Form::createElements()
*/
public function createElements(array $formData)
{
$this->addElement(
new Note(
'description',
array(
'value' => t(
'It seems that either the database you defined earlier does not yet exist and cannot be created'
. ' using the provided access credentials or the database does not have the required schema to '
. 'be operated by Icinga Web 2. Please provide appropriate access credentials to solve this.'
)
)
)
);
$skipValidation = isset($formData['skip_validation']) && $formData['skip_validation'];
$this->addElement(
'text',
'username',
array(
'required' => false === $skipValidation,
'label' => t('Username'),
'description' => t('A user which is able to create databases and/or touch the database schema')
)
);
$this->addElement(
'password',
'password',
array(
'label' => t('Password'),
'description' => t('The password for the database user defined above')
)
);
if ($skipValidation) {
$this->addSkipValidationCheckbox();
} else {
$this->addElement(
'hidden',
'skip_validation',
array(
'required' => true,
'value' => 0
)
);
}
}
/**
* Validate the given form data and check whether the defined user has sufficient access rights
*
* @param array $data The data to validate
*
* @return bool
*/
public function isValid($data)
{
if (false === parent::isValid($data)) {
return false;
}
if (isset($data['skip_validation']) && $data['skip_validation']) {
return true;
}
$this->config['username'] = $this->getValue('username');
$this->config['password'] = $this->getValue('password');
$db = new DbTool($this->config);
$database = $this->config['dbname'];
$dbtype = $this->config['db'];
try {
$error = false;
$msg = '';
if ($dbtype === 'pgsql') {
$db->connectToHost();
if (
false === $db->checkPgsqlGrantOption($this->databasePrivileges, $database, 'account') &&
false === $db->checkPgsqlGrantOption($this->databasePrivileges, $database, 'preference')
) {
$error = true;
$msg = sprintf(t('The role does not seem to have permission to create ' .
' or to grant access to the database "%s" and the tables "account", "preference".'), $database);
}
} else if ($dbtype === 'mysql') {
$db->connectToHost();
if (false === $db->checkMysqlGrantOption($this->databasePrivileges)) {
$error = true;
$msg = sprintf(t('The user does not seem to have permission to create ' .
' or to grant access to the database %s.'), $database);
}
}
if ($error) {
$this->addSkipValidationCheckbox();
$this->addError(t(
'The provided credentials do not have the required access rights to create the database schema: '
) . $msg);
return false;
}
} catch (PDOException $e) {
try {
$db->connectToHost();
if (false === $db->checkPrivileges($this->databasePrivileges)) {
$this->addError(
t('The provided credentials cannot be used to create the database and/or the user.')
);
$this->addSkipValidationCheckbox();
return false;
}
} catch (PDOException $e) {
$this->addError($e->getMessage());
$this->addSkipValidationCheckbox();
return false;
}
}
return true;
}
/**
* Add a checkbox to the form by which the user can skip the login and privilege validation
*/
protected function addSkipValidationCheckbox()
{
$this->addElement(
'checkbox',
'skip_validation',
array(
'order' => 1,
'required' => true,
'label' => t('Skip Validation'),
'description' => t('Check this to not to validate the ability to login and required privileges')
)
);
}
}