mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-27 07:44:04 +02:00
Fix stacktrace for missing database connection
- Add error handling for database connection failures - Suppress stacktrace and add error messages for user and admin - Improve user experience with clear error messages
This commit is contained in:
parent
cca7f2db1f
commit
15b0148542
@ -6,6 +6,7 @@ namespace Icinga\Controllers;
|
|||||||
use Icinga\Application\Hook\DbMigrationHook;
|
use Icinga\Application\Hook\DbMigrationHook;
|
||||||
use Icinga\Application\MigrationManager;
|
use Icinga\Application\MigrationManager;
|
||||||
use Icinga\Exception\IcingaException;
|
use Icinga\Exception\IcingaException;
|
||||||
|
use Throwable;
|
||||||
use Zend_Controller_Plugin_ErrorHandler;
|
use Zend_Controller_Plugin_ErrorHandler;
|
||||||
use Icinga\Application\Icinga;
|
use Icinga\Application\Icinga;
|
||||||
use Icinga\Application\Logger;
|
use Icinga\Application\Logger;
|
||||||
@ -96,6 +97,9 @@ class ErrorController extends ActionController
|
|||||||
$mm = MigrationManager::instance();
|
$mm = MigrationManager::instance();
|
||||||
$action = $this->getRequest()->getActionName();
|
$action = $this->getRequest()->getActionName();
|
||||||
$controller = $this->getRequest()->getControllerName();
|
$controller = $this->getRequest()->getControllerName();
|
||||||
|
$hasPending = false;
|
||||||
|
try {
|
||||||
|
$hasPending = $mm->hasPendingMigrations();
|
||||||
if ($action !== 'hint' && $controller !== 'migrations' && $mm->hasMigrations($moduleName)) {
|
if ($action !== 'hint' && $controller !== 'migrations' && $mm->hasMigrations($moduleName)) {
|
||||||
// The view renderer from IPL web doesn't render the HTML content set in the respective
|
// The view renderer from IPL web doesn't render the HTML content set in the respective
|
||||||
// controller if the error_handler request param is set, as it doesn't support error
|
// controller if the error_handler request param is set, as it doesn't support error
|
||||||
@ -108,6 +112,9 @@ class ErrorController extends ActionController
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
//suppress
|
||||||
|
}
|
||||||
|
|
||||||
$this->getResponse()->setHttpResponseCode(500);
|
$this->getResponse()->setHttpResponseCode(500);
|
||||||
$module = $modules->hasLoaded($moduleName) ? $modules->getModule($moduleName) : null;
|
$module = $modules->hasLoaded($moduleName) ? $modules->getModule($moduleName) : null;
|
||||||
|
@ -19,6 +19,9 @@ use ipl\Html\HtmlElement;
|
|||||||
use ipl\Html\Text;
|
use ipl\Html\Text;
|
||||||
use ipl\Web\Compat\CompatController;
|
use ipl\Web\Compat\CompatController;
|
||||||
use ipl\Web\Widget\ActionLink;
|
use ipl\Web\Widget\ActionLink;
|
||||||
|
use ipl\Web\Widget\Icon;
|
||||||
|
use ipl\Web\Widget\Link;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
class MigrationsController extends CompatController
|
class MigrationsController extends CompatController
|
||||||
{
|
{
|
||||||
@ -55,6 +58,7 @@ class MigrationsController extends CompatController
|
|||||||
|
|
||||||
$migrateListForm = new MigrationForm();
|
$migrateListForm = new MigrationForm();
|
||||||
$migrateListForm->setAttribute('id', $this->getRequest()->protectId('migration-form'));
|
$migrateListForm->setAttribute('id', $this->getRequest()->protectId('migration-form'));
|
||||||
|
try {
|
||||||
$migrateListForm->setRenderDatabaseUserChange(! $mm->validateDatabasePrivileges());
|
$migrateListForm->setRenderDatabaseUserChange(! $mm->validateDatabasePrivileges());
|
||||||
|
|
||||||
if ($canApply && $mm->hasPendingMigrations()) {
|
if ($canApply && $mm->hasPendingMigrations()) {
|
||||||
@ -69,11 +73,34 @@ class MigrationsController extends CompatController
|
|||||||
$migrateListForm->registerElement($migrateAllButton);
|
$migrateListForm->registerElement($migrateAllButton);
|
||||||
|
|
||||||
// Make sure it looks familiar, even if not inside a form
|
// Make sure it looks familiar, even if not inside a form
|
||||||
$migrateAllButton->setWrapper(new HtmlElement('div', Attributes::create(['class' => 'icinga-controls'])));
|
$migrateAllButton->setWrapper(
|
||||||
|
new HtmlElement('div', Attributes::create(['class' => 'icinga-controls']))
|
||||||
|
);
|
||||||
|
|
||||||
$this->controls->getAttributes()->add('class', 'default-layout');
|
$this->controls->getAttributes()->add('class', 'default-layout');
|
||||||
$this->addControl($migrateAllButton);
|
$this->addControl($migrateAllButton);
|
||||||
}
|
}
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$this->addContent(
|
||||||
|
new HtmlElement(
|
||||||
|
'div',
|
||||||
|
new Attributes(['class' => 'db-connection-warning']),
|
||||||
|
new Icon('warning'),
|
||||||
|
new HtmlElement('ul', null),
|
||||||
|
new HtmlElement(
|
||||||
|
'p',
|
||||||
|
null,
|
||||||
|
new Text(
|
||||||
|
$this->translate(' No Configuration Database selected.
|
||||||
|
To establish a valid database connection set the Configuration Database field. ')
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new HtmlElement('ul', null),
|
||||||
|
new Link($this->translate('Configuration Database'), 'config/general/')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$this->handleFormatRequest($mm->toArray());
|
$this->handleFormatRequest($mm->toArray());
|
||||||
|
|
||||||
|
@ -4,10 +4,15 @@
|
|||||||
namespace Icinga\Controllers;
|
namespace Icinga\Controllers;
|
||||||
|
|
||||||
use Icinga\Common\Database;
|
use Icinga\Common\Database;
|
||||||
use Icinga\Web\Notification;
|
|
||||||
use Icinga\Web\RememberMe;
|
use Icinga\Web\RememberMe;
|
||||||
use Icinga\Web\RememberMeUserDevicesList;
|
use Icinga\Web\RememberMeUserDevicesList;
|
||||||
|
use ipl\Html\Attributes;
|
||||||
|
use ipl\Html\HtmlElement;
|
||||||
|
use ipl\Html\Text;
|
||||||
use ipl\Web\Compat\CompatController;
|
use ipl\Web\Compat\CompatController;
|
||||||
|
use ipl\Web\Widget\Icon;
|
||||||
|
use ipl\Web\Widget\Link;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MyDevicesController
|
* MyDevicesController
|
||||||
@ -49,6 +54,46 @@ class MyDevicesController extends CompatController
|
|||||||
|
|
||||||
public function indexAction()
|
public function indexAction()
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
$this->getDb();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$hasConfigPermission = $this->hasPermission('config/*');
|
||||||
|
if ($hasConfigPermission) {
|
||||||
|
$this->addContent(
|
||||||
|
new HtmlElement(
|
||||||
|
'div',
|
||||||
|
new Attributes(['class' => 'db-connection-warning']),
|
||||||
|
new Icon('warning'),
|
||||||
|
new HtmlElement(
|
||||||
|
'p',
|
||||||
|
null,
|
||||||
|
new Text($this->translate(
|
||||||
|
'No Configuration Database selected.'
|
||||||
|
. 'To establish a valid database connection set the Configuration Database field.'
|
||||||
|
))
|
||||||
|
),
|
||||||
|
new Link($this->translate('Configuration Database'), 'config/general/')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->addContent(
|
||||||
|
new HtmlElement(
|
||||||
|
'div',
|
||||||
|
new Attributes(['class' => 'db-connection-warning']),
|
||||||
|
new Icon('warning'),
|
||||||
|
new HtmlElement(
|
||||||
|
'p',
|
||||||
|
null,
|
||||||
|
new Text($this->translate(
|
||||||
|
'No Configuration Database selected.'
|
||||||
|
. 'You don`t have permission to change this setting. Please contact an administrator.'
|
||||||
|
))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
$name = $this->auth->getUser()->getUsername();
|
$name = $this->auth->getUser()->getUsername();
|
||||||
|
|
||||||
$data = (new RememberMeUserDevicesList())
|
$data = (new RememberMeUserDevicesList())
|
||||||
@ -57,12 +102,6 @@ class MyDevicesController extends CompatController
|
|||||||
->setUrl('my-devices/delete');
|
->setUrl('my-devices/delete');
|
||||||
|
|
||||||
$this->addContent($data);
|
$this->addContent($data);
|
||||||
|
|
||||||
if (! $this->hasDb()) {
|
|
||||||
Notification::warning(
|
|
||||||
$this->translate("Users can't stay logged in without a database configuration backend")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteAction()
|
public function deleteAction()
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
|
|
||||||
namespace Icinga\Forms\Config\General;
|
namespace Icinga\Forms\Config\General;
|
||||||
|
|
||||||
|
use Icinga\Application\Config;
|
||||||
use Icinga\Application\Icinga;
|
use Icinga\Application\Icinga;
|
||||||
use Icinga\Data\ResourceFactory;
|
use Icinga\Data\ResourceFactory;
|
||||||
use Icinga\Web\Form;
|
use Icinga\Web\Form;
|
||||||
|
use ipl\Html\Text;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration form for general application options
|
* Configuration form for general application options
|
||||||
@ -100,6 +102,16 @@ class ApplicationConfigForm extends Form
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$config = Config::app()->getSection('global');
|
||||||
|
if (!isset($config->config_resource)) {
|
||||||
|
$missingConfigResource =
|
||||||
|
Text::create(
|
||||||
|
$this->translate("No Configuration Database selected.
|
||||||
|
Please set the field to establish a valid database connection.")
|
||||||
|
);
|
||||||
|
$this->warning($missingConfigResource, false);
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ use Icinga\Web\Notification;
|
|||||||
use Icinga\Web\Session;
|
use Icinga\Web\Session;
|
||||||
use Icinga\Web\StyleSheet;
|
use Icinga\Web\StyleSheet;
|
||||||
use ipl\Html\HtmlElement;
|
use ipl\Html\HtmlElement;
|
||||||
|
use ipl\Html\Text;
|
||||||
use ipl\I18n\GettextTranslator;
|
use ipl\I18n\GettextTranslator;
|
||||||
use ipl\I18n\Locale;
|
use ipl\I18n\Locale;
|
||||||
use ipl\I18n\StaticTranslator;
|
use ipl\I18n\StaticTranslator;
|
||||||
@ -185,7 +186,15 @@ class PreferenceForm extends Form
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
$config = Config::app()->getSection('global');
|
||||||
|
if (!isset($config->config_resource)) {
|
||||||
|
$missingConfigResource =
|
||||||
|
Text::create($this->translate(
|
||||||
|
'No Configuration Database selected.'
|
||||||
|
. 'To establish a valid database connection set the Configuration Database field.'
|
||||||
|
));
|
||||||
|
$this->warning($missingConfigResource, false);
|
||||||
|
}
|
||||||
$themeFile = StyleSheet::getThemeFile(Config::app()->get('themes', 'default'));
|
$themeFile = StyleSheet::getThemeFile(Config::app()->get('themes', 'default'));
|
||||||
if (! (bool) Config::app()->get('themes', 'disabled', false)) {
|
if (! (bool) Config::app()->get('themes', 'disabled', false)) {
|
||||||
$themes = Icinga::app()->getThemes();
|
$themes = Icinga::app()->getThemes();
|
||||||
@ -439,7 +448,7 @@ class PreferenceForm extends Form
|
|||||||
|
|
||||||
public function isSubmitted()
|
public function isSubmitted()
|
||||||
{
|
{
|
||||||
if (parent::isSubmitted()) {
|
if (($this->getElement('btn_submit') !== null ) && parent::isSubmitted()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Icinga\Application\Config;
|
||||||
use Icinga\Application\MigrationManager;
|
use Icinga\Application\MigrationManager;
|
||||||
use Icinga\Web\Navigation\Renderer\BadgeNavigationItemRenderer;
|
use Icinga\Web\Navigation\Renderer\BadgeNavigationItemRenderer;
|
||||||
use ipl\Html\HtmlElement;
|
use ipl\Html\HtmlElement;
|
||||||
|
use ipl\Web\Widget\EmptyState;
|
||||||
use ipl\Web\Widget\Icon;
|
use ipl\Web\Widget\Icon;
|
||||||
use ipl\Web\Widget\StateBadge;
|
use ipl\Web\Widget\StateBadge;
|
||||||
|
|
||||||
@ -93,8 +95,6 @@ use ipl\Web\Widget\StateBadge;
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
?>
|
?>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
$mm = MigrationManager::instance();
|
$mm = MigrationManager::instance();
|
||||||
@ -102,11 +102,36 @@ use ipl\Web\Widget\StateBadge;
|
|||||||
try {
|
try {
|
||||||
$hasPending = $mm->hasPendingMigrations();
|
$hasPending = $mm->hasPendingMigrations();
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
throw new LogicException('Please check the database connection in Configuration -> Application -> Resources');
|
// suppress
|
||||||
}
|
}
|
||||||
if ($hasPending): ?>
|
?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php $config = Config::app()->getSection('global') ?>
|
||||||
<div class="pending-migrations clearfix">
|
<div class="pending-migrations clearfix">
|
||||||
|
<?php if($mm->getPendingMigrations() || (!isset($config->config_resource))) : ?>
|
||||||
<h2><?= $this->translate('Pending Migrations') ?></h2>
|
<h2><?= $this->translate('Pending Migrations') ?></h2>
|
||||||
|
<?php endif ?>
|
||||||
|
<table >
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<?php if (!isset($config->config_resource)) : ?>
|
||||||
|
<?= new EmptyState(
|
||||||
|
$this->translate('No Configuration Database selected. To establish a valid database connection set: '))
|
||||||
|
?><td>
|
||||||
|
<?= $this->qlink(
|
||||||
|
$this->translate('Configuration Database'),
|
||||||
|
'config/general/',
|
||||||
|
array('name' => ('Configuration Database')),
|
||||||
|
array('title' => sprintf($this->translate('Go to Application/General')), 'Configuration Database')
|
||||||
|
) ?>
|
||||||
|
</td>
|
||||||
|
<?php endif ?>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<?php if ($hasPending): ?>
|
||||||
<table class="name-value-table migrations">
|
<table class="name-value-table migrations">
|
||||||
<?php foreach ($mm->getPendingMigrations() as $migration): ?>
|
<?php foreach ($mm->getPendingMigrations() as $migration): ?>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -82,6 +82,7 @@ class StyleSheet
|
|||||||
'css/icinga/health.less',
|
'css/icinga/health.less',
|
||||||
'css/icinga/php-diff.less',
|
'css/icinga/php-diff.less',
|
||||||
'css/icinga/pending-migration.less',
|
'css/icinga/pending-migration.less',
|
||||||
|
'css/icinga/db-connection-warning.less',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
32
public/css/icinga/db-connection-warning.less
Normal file
32
public/css/icinga/db-connection-warning.less
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
.db-connection-warning {
|
||||||
|
border-radius: .25em;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0 0 1em 0;
|
||||||
|
padding: 1em 1em;
|
||||||
|
background-color: fade(#ffaa44, 40%);
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
margin: 0;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: .5em;
|
||||||
|
color: #00c3ed;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 2em;
|
||||||
|
|
||||||
|
opacity: .4;
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user