diff options
Diffstat (limited to 'application/forms/MigrationForm.php')
-rw-r--r-- | application/forms/MigrationForm.php | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/application/forms/MigrationForm.php b/application/forms/MigrationForm.php new file mode 100644 index 0000000..c5d517f --- /dev/null +++ b/application/forms/MigrationForm.php @@ -0,0 +1,143 @@ +<?php + +/* Icinga Web 2 | (c) 2023 Icinga GmbH | GPLv2+ */ + +namespace Icinga\Forms; + +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; +use ipl\Web\Common\CsrfCounterMeasure; +use ipl\Web\Common\FormUid; +use ipl\Web\Compat\CompatForm; +use ipl\Web\FormDecorator\IcingaFormDecorator; +use PDOException; + +class MigrationForm extends CompatForm +{ + use CsrfCounterMeasure; + use FormUid; + use Translation; + + protected $defaultAttributes = [ + 'class' => ['icinga-form', 'migration-form', 'icinga-controls'], + 'name' => 'migration-form' + ]; + + /** @var bool Whether to allow changing the current database user and password */ + protected $renderDatabaseUserChange = false; + + public function hasBeenSubmitted(): bool + { + if (! $this->hasBeenSent()) { + return false; + } + + $pressedButton = $this->getPressedSubmitElement(); + + return $pressedButton && strpos($pressedButton->getName(), 'migrate-') !== false; + } + + public function setRenderDatabaseUserChange(bool $value = true): self + { + $this->renderDatabaseUserChange = $value; + + return $this; + } + + public function hasDefaultElementDecorator() + { + // The base implementation registers a decorator we don't want here + return false; + } + + protected function assemble(): void + { + $this->addHtml($this->createUidElement()); + + 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); + } + } +} |