2023-07-24 13:14:00 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/* Icinga Web 2 | (c) 2023 Icinga GmbH | GPLv2+ */
|
|
|
|
|
|
|
|
namespace Icinga\Forms;
|
|
|
|
|
2023-09-14 17:17:16 +02:00
|
|
|
use Icinga\Application\MigrationManager;
|
|
|
|
use ipl\Html\Attributes;
|
|
|
|
use ipl\Html\FormElement\CheckboxElement;
|
|
|
|
use ipl\Html\FormElement\FieldsetElement;
|
|
|
|
use ipl\Html\HtmlElement;
|
|
|
|
use ipl\Html\Text;
|
|
|
|
use ipl\I18n\Translation;
|
|
|
|
use ipl\Validator\CallbackValidator;
|
2023-07-24 13:14:00 +02:00
|
|
|
use ipl\Web\Common\CsrfCounterMeasure;
|
|
|
|
use ipl\Web\Common\FormUid;
|
2023-09-15 16:56:22 +02:00
|
|
|
use ipl\Web\Compat\CompatForm;
|
2023-09-14 17:17:16 +02:00
|
|
|
use ipl\Web\FormDecorator\IcingaFormDecorator;
|
|
|
|
use PDOException;
|
2023-07-24 13:14:00 +02:00
|
|
|
|
2023-09-15 16:56:22 +02:00
|
|
|
class MigrationForm extends CompatForm
|
2023-07-24 13:14:00 +02:00
|
|
|
{
|
|
|
|
use CsrfCounterMeasure;
|
|
|
|
use FormUid;
|
2023-09-14 17:17:16 +02:00
|
|
|
use Translation;
|
2023-07-24 13:14:00 +02:00
|
|
|
|
|
|
|
protected $defaultAttributes = [
|
|
|
|
'class' => ['icinga-form', 'migration-form', 'icinga-controls'],
|
|
|
|
'name' => 'migration-form'
|
|
|
|
];
|
|
|
|
|
2023-09-14 17:17:16 +02:00
|
|
|
/** @var bool Whether to allow changing the current database user and password */
|
|
|
|
protected $renderDatabaseUserChange = false;
|
|
|
|
|
2023-09-11 15:52:56 +02:00
|
|
|
public function hasBeenSubmitted(): bool
|
|
|
|
{
|
|
|
|
if (! $this->hasBeenSent()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$pressedButton = $this->getPressedSubmitElement();
|
2023-09-14 17:17:16 +02:00
|
|
|
|
2023-09-11 15:52:56 +02:00
|
|
|
return $pressedButton && strpos($pressedButton->getName(), 'migrate-') !== false;
|
|
|
|
}
|
|
|
|
|
2023-09-14 17:17:16 +02:00
|
|
|
public function setRenderDatabaseUserChange(bool $value = true): self
|
|
|
|
{
|
|
|
|
$this->renderDatabaseUserChange = $value;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2023-09-15 16:56:22 +02:00
|
|
|
public function hasDefaultElementDecorator()
|
|
|
|
{
|
|
|
|
// The base implementation registers a decorator we don't want here
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-07-24 13:14:00 +02:00
|
|
|
protected function assemble(): void
|
|
|
|
{
|
|
|
|
$this->addHtml($this->createUidElement());
|
2023-09-14 17:17:16 +02:00
|
|
|
|
|
|
|
if ($this->renderDatabaseUserChange) {
|
|
|
|
$mm = MigrationManager::instance();
|
|
|
|
$newDbSetup = new FieldsetElement('database_setup', ['required' => true]);
|
|
|
|
$newDbSetup
|
|
|
|
->setDefaultElementDecorator(new IcingaFormDecorator())
|
|
|
|
->addElement('text', 'username', [
|
|
|
|
'required' => true,
|
|
|
|
'label' => $this->translate('Username'),
|
|
|
|
'description' => $this->translate(
|
|
|
|
'A user which is able to create and/or alter the database schema.'
|
|
|
|
)
|
|
|
|
])
|
|
|
|
->addElement('password', 'password', [
|
|
|
|
'required' => true,
|
|
|
|
'autocomplete' => 'new-password',
|
|
|
|
'label' => $this->translate('Password'),
|
|
|
|
'description' => $this->translate('The password for the database user defined above.'),
|
|
|
|
'validators' => [
|
|
|
|
new CallbackValidator(function ($_, CallbackValidator $validator) use ($mm, $newDbSetup): bool {
|
|
|
|
/** @var array<string, string> $values */
|
|
|
|
$values = $this->getValue('database_setup');
|
|
|
|
/** @var CheckboxElement $checkBox */
|
|
|
|
$checkBox = $newDbSetup->getElement('grant_privileges');
|
|
|
|
$canIssueGrants = $checkBox->isChecked();
|
|
|
|
$elevationConfig = [
|
|
|
|
'username' => $values['username'],
|
|
|
|
'password' => $values['password']
|
|
|
|
];
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (! $mm->validateDatabasePrivileges($elevationConfig, $canIssueGrants)) {
|
|
|
|
$validator->addMessage(sprintf(
|
|
|
|
$this->translate(
|
|
|
|
'The provided credentials cannot be used to execute "%s" SQL commands'
|
|
|
|
. ' and/or grant the missing privileges to other users.'
|
|
|
|
),
|
|
|
|
implode(' ,', $mm->getRequiredDatabasePrivileges())
|
|
|
|
));
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} catch (PDOException $e) {
|
|
|
|
$validator->addMessage($e->getMessage());
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
})
|
|
|
|
]
|
|
|
|
])
|
|
|
|
->addElement('checkbox', 'grant_privileges', [
|
|
|
|
'required' => false,
|
|
|
|
'label' => $this->translate('Grant Missing Privileges'),
|
|
|
|
'description' => $this->translate(
|
|
|
|
'Allows to automatically grant the required privileges to the database user specified'
|
|
|
|
. ' in the respective resource config. If you do not want to provide additional credentials'
|
|
|
|
. ' each time, you can enable this and Icinga Web will grant the active database user the'
|
|
|
|
. ' missing privileges.'
|
|
|
|
)
|
|
|
|
]);
|
|
|
|
|
|
|
|
$this->addHtml(
|
|
|
|
new HtmlElement(
|
|
|
|
'div',
|
|
|
|
Attributes::create(['class' => 'change-database-user-description']),
|
|
|
|
new HtmlElement('span', null, Text::create(sprintf(
|
|
|
|
$this->translate(
|
|
|
|
'It seems that the currently used database user does not have the required privileges to'
|
|
|
|
. ' execute the %s SQL commands. Please provide an alternative user'
|
|
|
|
. ' that has the appropriate credentials to resolve this issue.'
|
|
|
|
),
|
|
|
|
implode(', ', $mm->getRequiredDatabasePrivileges())
|
|
|
|
)))
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->addElement($newDbSetup);
|
|
|
|
}
|
2023-07-24 13:14:00 +02:00
|
|
|
}
|
|
|
|
}
|