Merge branch 'master' into feature/restrict-custom-variables-10965

This commit is contained in:
Eric Lippmann 2016-03-21 14:50:13 +01:00
commit 5bc52a2801
103 changed files with 2364 additions and 1680 deletions

View File

@ -35,6 +35,11 @@ class apache {
require => Package['apache'],
}
package { 'mod_ssl':
ensure => latest,
notify => Service[$apache],
}
@user { $user:
alias => 'apache',
}

View File

@ -17,6 +17,7 @@
class php {
include apache
include epel
package { 'php':
ensure => latest,
@ -24,5 +25,11 @@ class php {
require => Package['apache'],
}
package { 'php-pecl-xdebug':
ensure => latest,
notify => Service['apache'],
require => Class['epel'],
}
php::phpd { ['error_reporting', 'timezone', 'xdebug_settings' ]: }
}

View File

@ -14,10 +14,12 @@ Daniel Shirley <aditaa@ig2ad.com>
Davide Demuru <davide.demuru@buongiorno.com>
Emil Vikström <emil@pixelstore.se>
Eric Lippmann <eric.lippmann@netways.de>
Florian Strohmaier <hello@florianstrohmaier.com>
Goran Rakic <grakic@devbase.net>
Gunnar Beutner <gunnar.beutner@netways.de>
Jannis Moßhammer <jannis.mosshammer@netways.de>
Jo Rhett <jo@chegg.com>
Joe Doherty <git@pjuu.com>
Johannes Meyer <johannes.meyer@netways.de>
Louis Sautier <sautier.louis@gmail.com>
Marcus Cobden <marcus@marcuscobden.co.uk>

View File

@ -1,5 +1,66 @@
# Icinga Web 2 Changelog
## What's New in Version 2.2.0
#### Features
* Feature 8487: Number headings in the documentation module
* Feature 8963: Feature commands in the multi select views
* Feature 10654: Render links in acknowledgements, comments and downtimes
* Feature 11062: Allow style classes in plugin output
* Feature 11238: Puppet/Vagrant: Install mod_ssl and forward port 443
#### Bugfixes
* Bug 7350: Tabs are missing if JS is disabled
* Bug 9800: Debian packaging: Ship translation module w/ the icingaweb2 package and install its config.ini
* Bug 10173: Failed commands give no useful error any more
* Bug 10251: Icinga Web 2 fails to run with PHP7
* Bug 10277: Special characters are incorrectly escaped for tooltips in the service grid
* Bug 10289: Doc module: Headers are cut off when clicking on TOC links
* Bug 10309: Move auth backend configuration to app config
* Bug 10310: Monitoring details: information/action ordering
* Bug 10362: Debian packaging: Separate package for CLI missing
* Bug 10366: Text plugin output treated as HTML in too many occasions
* Bug 10369: Accessibility: Focus not visible and lost after refresh
* Bug 10397: Users with no permissions can check multiple services
* Bug 10442: Edit user control should be more prominent
* Bug 10469: "Remove Acknowledgement" text missing in multi-select views
* Bug 10506: HTTP basic auth request is sent when using Kerberos authentication with Apache2 and mod_php
* Bug 10625: Return local date and time when lost connection to the web server
* Bug 10640: Respect protected_variables in nested custom variables too
* Bug 10778: Filters in the host group and service group overview not applied to state links
* Bug 10786: Whitespace characters are ignored in the plugin output in list views
* Bug 10805: Setup Wizard: Obsolete PHP sockets requirement
* Bug 10856: Benchmark is not rendered on many pages
* Bug 10871: Get rid of padding in controls
* Bug 10878: Dashboards different depending on username casing
* Bug 10881: Move iframe from modules to framework
* Bug 10917: Event grid tiles: The filter column "from" is not allowed here
* Bug 10918: Error on logout when using external authentication
* Bug 10921: icingacli monitoring list --format=csv throws error
* Bug 11000: Change license header to only reflect a file's year of creation/initial commit
* Bug 11008: Wobbling spinners
* Bug 11021: Global default theme is not applied while not authenticated
* Bug 11032: Fix icon_image size and provide a CSS class for theming
* Bug 11039: Misleading tooltip in Tactical Overview
* Bug 11051: Preferences and navigation items stored in INI files rely on case sensitive usernames
* Bug 11073: Active row is flickering on refresh
* Bug 11091: Custom navigation items: URL is not escaped/encoded
* Bug 11100: Comments are always persistent
* Bug 11114: Validate that a proper root DN is set for LDAP resources
* Bug 11117: Vendor: Update dompdf to version 0.6.2
* Bug 11119: icingacli shows ugly exception when unable to access the config directory
* Bug 11120: icingacli: command and action shortcuts have been broken
* Bug 11126: Invalid cookie value in cookie icingaweb2-tzo
* Bug 11142: LDAP User Groups backend group_filter
* Bug 11143: Layout: Tabs should be left-aligned
* Bug 11151: Having basic authentication on the webserver but not in Icinga Web 2 causes Web 2 to require basic auth
* Bug 11168: Debian packaging: Don't patch HTMLPurifier loading and install HTMLPurifier*.php files from the library/vendor root
* Bug 11187: Session cookie: Path too broad and unset secure flag on HTTPS
* Bug 11197: Menu items without url should ignore the target configuration
* Bug 11260: Scheduling downtimes through the API not working
## What's New in Version 2.1.1
#### Features

View File

@ -10,7 +10,7 @@
**Icinga Web 2** is the next generation open source monitoring web interface, framework
and command-line interface developed by the [Icinga Project](https://www.icinga.org/), supporting Icinga 2,
Icinga Core and any other monitoring backend compatible with the Livestatus Protocol.
Icinga Core and any other monitoring backend compatible with the IDO database.
![Icinga Web 2](https://www.icinga.org/wp-content/uploads/2015/10/Screen-Shot-2015-10-02-at-00.12.26.png "Icinga Web 2")

View File

@ -1 +1 @@
v2.1.2
v2.2.0

2
Vagrantfile vendored
View File

@ -18,6 +18,8 @@ end
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.network "forwarded_port", guest: 80, host: 8080,
auto_correct: true
config.vm.network "forwarded_port", guest: 443, host: 8443,
auto_correct: true
config.vm.provision :shell, :path => ".puppet/manifests/puppet.sh"

View File

@ -45,27 +45,12 @@ class ConfigController extends Controller
'url' => 'config/resource',
'baseTarget' => '_main'
));
return $tabs;
}
/**
* Create and return the tabs to display when showing authentication configuration
*/
public function createAuthenticationTabs()
{
$tabs = $this->getTabs();
$tabs->add('userbackend', array(
'title' => $this->translate('Configure how users authenticate with and log into Icinga Web 2'),
'label' => $this->translate('Users'),
$tabs->add('authentication', array(
'title' => $this->translate('Configure the user and group backends'),
'label' => $this->translate('Authentication'),
'url' => 'config/userbackend',
'baseTarget' => '_main'
));
$tabs->add('usergroupbackend', array(
'title' => $this->translate('Configure how users are associated with groups by Icinga Web 2'),
'label' => $this->translate('User Groups'),
'url' => 'usergroupbackend/list',
'baseTarget' => '_main'
));
return $tabs;
}
@ -184,17 +169,19 @@ class ConfigController extends Controller
}
/**
* Action for listing and reordering user backends
* Action for listing user and group backends
*/
public function userbackendAction()
{
$this->assertPermission('config/application/userbackend');
$this->assertPermission('config/application/usergroupbackend');
$form = new UserBackendReorderForm();
$form->setIniConfig(Config::app('authentication'));
$form->handleRequest();
$this->view->form = $form;
$this->createAuthenticationTabs()->activate('userbackend');
$this->view->backendNames = Config::app('groups');
$this->createApplicationTabs()->activate('authentication');
$this->render('userbackend/reorder');
}

View File

@ -39,6 +39,8 @@ class ListController extends Controller
*/
public function applicationlogAction()
{
$this->assertPermission('application/log');
if (! Logger::writesToFile()) {
$this->httpNotFound('Page not found');
}

View File

@ -29,16 +29,7 @@ class UsergroupbackendController extends Controller
*/
public function indexAction()
{
$this->redirectNow('usergroupbackend/list');
}
/**
* Show a list of all user group backends
*/
public function listAction()
{
$this->view->backendNames = Config::app('groups');
$this->createListTabs()->activate('usergroupbackend');
$this->redirectNow('config/userbackend');
}
/**
@ -47,7 +38,7 @@ class UsergroupbackendController extends Controller
public function createAction()
{
$form = new UserGroupBackendForm();
$form->setRedirectUrl('usergroupbackend/list');
$form->setRedirectUrl('config/userbackend');
$form->addDescription($this->translate('Create a new backend to associate users and groups with.'));
$form->setIniConfig(Config::app('groups'));
$form->setOnSuccess(function (UserGroupBackendForm $form) {
@ -78,7 +69,7 @@ class UsergroupbackendController extends Controller
$backendName = $this->params->getRequired('backend');
$form = new UserGroupBackendForm();
$form->setRedirectUrl('usergroupbackend/list');
$form->setRedirectUrl('config/userbackend');
$form->setIniConfig(Config::app('groups'));
$form->setOnSuccess(function (UserGroupBackendForm $form) use ($backendName) {
try {
@ -121,7 +112,7 @@ class UsergroupbackendController extends Controller
$backendForm = new UserGroupBackendForm();
$backendForm->setIniConfig(Config::app('groups'));
$form = new ConfirmRemovalForm();
$form->setRedirectUrl('usergroupbackend/list');
$form->setRedirectUrl('config/userbackend');
$form->setOnSuccess(function (ConfirmRemovalForm $form) use ($backendName, $backendForm) {
try {
$backendForm->delete($backendName);
@ -141,23 +132,4 @@ class UsergroupbackendController extends Controller
$this->renderForm($form, $this->translate('Remove User Group Backend'));
}
/**
* Create the tabs for the application configuration
*/
protected function createListTabs()
{
$tabs = $this->getTabs();
$tabs->add('userbackend', array(
'title' => $this->translate('Configure how users authenticate with and log into Icinga Web 2'),
'label' => $this->translate('Users'),
'url' => 'config/userbackend'
));
$tabs->add('usergroupbackend', array(
'title' => $this->translate('Configure how users are associated with groups by Icinga Web 2'),
'label' => $this->translate('User Groups'),
'url' => 'usergroupbackend/list'
));
return $tabs;
}
}

View File

@ -5,6 +5,7 @@ namespace Icinga\Forms\Dashboard;
use Icinga\Web\Widget\Dashboard;
use Icinga\Web\Form;
use Icinga\Web\Form\Validator\UrlValidator;
use Icinga\Web\Url;
use Icinga\Web\Widget\Dashboard\Dashlet;
@ -27,7 +28,7 @@ class DashletForm extends Form
if (! $this->getSubmitLabel()) {
$this->setSubmitLabel($this->translate('Add To Dashboard'));
}
$this->setAction(URL::fromRequest());
$this->setAction(Url::fromRequest());
}
/**
@ -68,7 +69,8 @@ class DashletForm extends Form
'label' => $this->translate('Url'),
'description' => $this->translate(
'Enter url being loaded in the dashlet. You can paste the full URL, including filters.'
)
),
'validators' => array(new UrlValidator())
)
);
$this->addElement(

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
<?= $tabs ?>
</div>
<div class="content">
<h1><?= $this->translate('User Backends') ?></h1>
<?= $this->qlink(
$this->translate('Create a New User Backend') ,
'config/createuserbackend',
@ -14,4 +15,57 @@
)
) ?>
<?= $form ?>
<h1><?= $this->translate('User Group Backends') ?></h1>
<?= $this->qlink(
$this->translate('Create a New User Group Backend') ,
'usergroupbackend/create',
null,
array(
'class' => 'button-link',
'data-base-target' => '_next',
'icon' => 'plus',
'title' => $this->translate('Create a new user group backend')
)
) ?>
<?php if (! count($backendNames)) { return; } ?>
<table class="table-row-selectable common-table" data-base-target="_next">
<thead>
<tr>
<th><?= $this->translate('Backend') ?></th>
<th></th>
</tr>
</thead>
<tbody>
<?php foreach ($backendNames as $backendName => $config):
$type = $config->get('backend');
?>
<tr>
<td>
<?= $this->qlink(
$backendName,
'usergroupbackend/edit',
array('backend' => $backendName),
array(
'icon' => $type === 'external' ? 'magic' : ($type === 'ldap' || $type === 'msldap' ? 'sitemap' : 'database'),
'title' => sprintf($this->translate('Edit user group backend %s'), $backendName)
)
); ?>
</td>
<td class="icon-col text-right">
<?= $this->qlink(
null,
'usergroupbackend/remove',
array('backend' => $backendName),
array(
'class' => 'action-link',
'icon' => 'cancel',
'title' => sprintf($this->translate('Remove user group backend %s'), $backendName)
)
) ?>
</td>
</tr>
<?php endforeach ?>
</tbody>
</table>
</div>

View File

@ -20,7 +20,7 @@
<?php foreach ($this->dashboard->getPanes() as $pane): ?>
<tr style="background-color: #f1f1f1;">
<th colspan="2" style="text-align: left; padding: 0.5em;">
<?= $pane->getName(); ?>
<?= $this->escape($pane->getName()) ?>
</th>
<th>
<?= $this->qlink(

View File

@ -40,30 +40,26 @@
</td>
<td class="icon-col text-right" data-base-target="_self">
<?php if ($i > 0): ?>
<button type="submit" name="backend_newpos" class="link-button icon-only animated move-up" value="<?= sprintf(
'%s|%s',
$backendNames[$i],
$i - 1
<button type="submit" name="backend_newpos" class="link-button icon-only animated move-up" value="<?= $this->escape(
$backendNames[$i] . '|' . ($i - 1)
) ?>" title="<?= $this->translate(
'Move up in authentication order'
) ?>" aria-label="<?= sprintf(
) ?>" aria-label="<?= $this->escape(sprintf(
$this->translate('Move user backend %s upwards'),
$backendNames[$i]
) ?>">
)) ?>">
<?= $this->icon('up-small') ?>
</button>
<?php endif ?>
<?php if ($i + 1 < count($backendNames)): ?>
<button type="submit" name="backend_newpos" class="link-button icon-only animated move-down" value="<?= sprintf(
'%s|%s',
$backendNames[$i],
$i + 1
<button type="submit" name="backend_newpos" class="link-button icon-only animated move-down" value="<?= $this->escape(
$backendNames[$i] . '|' . ($i + 1)
) ?>" title="<?= $this->translate(
'Move down in authentication order'
) ?>" aria-label="<?= sprintf(
) ?>" aria-label="<?= $this->escape(sprintf(
$this->translate('Move user backend %s downwards'),
$backendNames[$i]
) ?>">
)) ?>">
<?= $this->icon('down-small') ?>
</button>
<?php endif ?>

View File

@ -4,29 +4,29 @@ use Icinga\Data\Updatable;
use Icinga\Data\Reducible;
use Icinga\Data\Selectable;
$editLink = null;
if ($this->hasPermission('config/authentication/users/edit') && $backend instanceof Updatable) {
$editLink = $this->qlink(
null,
'user/edit',
array(
'backend' => $backend->getName(),
'user' => $user->user_name
),
array(
'title' => sprintf($this->translate('Edit user %s'), $user->user_name),
'class' => 'user-edit',
'icon' => 'edit'
)
);
}
?>
<div class="controls separated">
<?php if (! $this->compact): ?>
<?= $tabs; ?>
<?php endif ?>
<h2 class="clearfix"><?= $this->escape($user->user_name) ?><span class="pull-right"><?= $editLink ?></span></h2>
<h2><?= $this->escape($user->user_name) ?></h2>
<?php
if ($this->hasPermission('config/authentication/users/edit') && $backend instanceof Updatable) {
echo $this->qlink(
$this->translate('Edit User'),
'user/edit',
array(
'backend' => $backend->getName(),
'user' => $user->user_name
),
array(
'class' => 'button-link',
'icon' => 'edit',
'title' => sprintf($this->translate('Edit user %s'), $user->user_name)
)
);
}
?>
<table class="name-value-table">
<tr>
<th><?= $this->translate('State'); ?></th>

View File

@ -1,56 +0,0 @@
<div class="controls">
<?= $tabs ?>
</div>
<div class="content">
<?= $this->qlink(
$this->translate('Create a New User Group Backend') ,
'usergroupbackend/create',
null,
array(
'class' => 'button-link',
'data-base-target' => '_next',
'icon' => 'plus',
'title' => $this->translate('Create a new user group backend')
)
) ?>
<?php if (! count($backendNames)) { return; } ?>
<table class="table-row-selectable common-table" data-base-target="_next">
<thead>
<tr>
<th><?= $this->translate('Backend') ?></th>
<th></th>
</tr>
</thead>
<tbody>
<?php foreach ($backendNames as $backendName => $config):
$type = $config->get('backend');
?>
<tr>
<td>
<?= $this->qlink(
$backendName,
'usergroupbackend/edit',
array('backend' => $backendName),
array(
'icon' => $type === 'external' ? 'magic' : ($type === 'ldap' || $type === 'msldap' ? 'sitemap' : 'database'),
'title' => sprintf($this->translate('Edit user group backend %s'), $backendName)
)
); ?>
</td>
<td class="icon-col text-right">
<?= $this->qlink(
null,
'usergroupbackend/remove',
array('backend' => $backendName),
array(
'class' => 'action-link',
'icon' => 'cancel',
'title' => sprintf($this->translate('Remove user group backend %s'), $backendName)
)
) ?>
</td>
</tr>
<?php endforeach ?>
</tbody>
</table>
</div>

View File

@ -11,10 +11,10 @@ thoroughly.
* A web server, e.g. Apache or nginx
* PHP >= 5.3.0 w/ gettext, intl and OpenSSL support
* MySQL or PostgreSQL PHP libraries when using a database for authentication or for storing preferences into a database
* LDAP PHP library when using Active Directory or LDAP for authentication
* Icinga 1.x w/ Livestatus or IDO; Icinga 2.x w/ Livestatus or IDO feature enabled
* MySQL or PostgreSQL PHP libraries when using IDO
* Icinga 1.x w/ IDO; Icinga 2.x w/ IDO feature enabled
* The IDO table prefix must be icinga_ which is the default
* MySQL or PostgreSQL PHP libraries
### <a id="pagespeed-incompatibility"></a> PageSpeed Module Incompatibility
@ -22,14 +22,14 @@ It seems that Web 2 is not compatible with the PageSpeed module. Please disable
following methods.
**Apache**:
````
```
ModPagespeedDisallow "*/icingaweb2/*"
````
```
**Nginx**:
````
```
pagespeed Disallow "*/icingaweb2/*";
````
```
## <a id="installing-from-package"></a> Installing Icinga Web 2 from Package
@ -55,52 +55,52 @@ You need to add the Icinga repository to your package management configuration f
Below is a list with examples for various distributions.
**Debian (debmon)**:
````
```
wget -O - http://debmon.org/debmon/repo.key 2>/dev/null | apt-key add -
echo 'deb http://debmon.org/debmon debmon-wheezy main' >/etc/apt/sources.list.d/debmon.list
apt-get update
````
```
**Ubuntu Trusty**:
````
```
wget -O - http://packages.icinga.org/icinga.key | apt-key add -
add-apt-repository 'deb http://packages.icinga.org/ubuntu icinga-trusty main'
apt-get update
````
```
For other Ubuntu versions just replace trusty with your distribution\'s code name.
**RHEL and CentOS**:
````
```
rpm --import http://packages.icinga.org/icinga.key
curl -o /etc/yum.repos.d/ICINGA-release.repo http://packages.icinga.org/epel/ICINGA-release.repo
yum makecache
````
```
**Fedora**:
````
```
rpm --import http://packages.icinga.org/icinga.key
curl -o /etc/yum.repos.d/ICINGA-release.repo http://packages.icinga.org/fedora/ICINGA-release.repo
yum makecache
````
```
**SLES 11**:
````
```
zypper ar http://packages.icinga.org/SUSE/ICINGA-release-11.repo
zypper ref
````
```
**SLES 12**:
````
```
zypper ar http://packages.icinga.org/SUSE/ICINGA-release.repo
zypper ref
````
```
**openSUSE**:
````
```
zypper ar http://packages.icinga.org/openSUSE/ICINGA-release.repo
zypper ref
````
```
#### <a id="package-repositories-rhel-notes"></a> RHEL/CentOS Notes
@ -114,7 +114,7 @@ The packages for RHEL/CentOS depend on other packages which are distributed as p
#### <a id="package-repositories-wheezy-notes"></a> Debian wheezy Notes
The packages for Debian wheezy depend on other packages which are distributed as part of the
[wheezy-packports](http://backports.debian.org/) repository. Please make sure to enable this repository by following
[wheezy-backports](http://backports.debian.org/) repository. Please make sure to enable this repository by following
[these instructions](http://backports.debian.org/Instructions/).
### <a id="installing-from-package-example"></a> Installing Icinga Web 2
@ -123,35 +123,35 @@ You can install Icinga Web 2 by using your distribution's package manager to ins
Below is a list with examples for various distributions. The additional package `icingacli` is necessary on RPM based systems for being able to follow further steps in this guide. In DEB based systems, the icingacli binary is included in the icingaweb2 package.
**Debian and Ubuntu**:
````
```
apt-get install icingaweb2
````
```
For Debian wheezy please read the [package repositories notes](#package-repositories-wheezy-notes).
**RHEL, CentOS and Fedora**:
````
```
yum install icingaweb2 icingacli
````
```
For RHEL/CentOS please read the [package repositories notes](#package-repositories-rhel-notes).
**SLES and openSUSE**:
````
```
zypper install icingaweb2 icingacli
````
```
### <a id="preparing-web-setup-from-package"></a> Preparing Web Setup
You can set up Icinga Web 2 quickly and easily with the Icinga Web 2 setup wizard which is available the first time
you visit Icinga Web 2 in your browser. When using the web setup you are required to authenticate using a token.
In order to generate a token use the `icingacli`:
````
```
icingacli setup token create
````
```
In case you do not remember the token you can show it using the `icingacli`:
````
```
icingacli setup token show
````
```
Finally visit Icinga Web 2 in your browser to access the setup wizard and complete the installation:
`/icingaweb2/setup`.
@ -173,9 +173,9 @@ There is also a browsable version available at
[git.icinga.org](https://git.icinga.org/?p=icingaweb2.git;a=summary "Icinga Web 2 Git Repository").
This version also offers snapshots for easy download which you can use if you do not have git present on your system.
````
```
git clone git://git.icinga.org/icingaweb2.git
````
```
### <a id="installing-from-source-requirements"></a> Installing Requirements from Source
@ -198,41 +198,41 @@ The setup wizard will check the pre-requisites later on.
Choose a target directory and move Icinga Web 2 there.
````
```
mv icingaweb2 /usr/share/icingaweb2
````
```
### <a id="configuring-web-server"></a> Configuring the Web Server
Use `icingacli` to generate web server configuration for either Apache or nginx.
**Apache**:
````
```
./bin/icingacli setup config webserver apache --document-root /usr/share/icingaweb2/public
````
```
**nginx**:
````
```
./bin/icingacli setup config webserver nginx --document-root /usr/share/icingaweb2/public
````
```
Save the output as new file in your webserver's configuration directory.
Example for Apache on RHEL or CentOS:
````
```
./bin/icingacli setup config webserver apache --document-root /usr/share/icingaweb2/public > /etc/httpd/conf.d/icingaweb2.conf
````
```
Example for Apache on SUSE:
````
```
./bin/icingacli setup config webserver apache --document-root /usr/share/icingaweb2/public > /etc/apache2/conf.d/icingaweb2.conf
````
```
Example for Apache on Debian Jessie:
````
```
./bin/icingacli setup config webserver apache --document-root /usr/share/icingaweb2/public > /etc/apache2/conf-available/icingaweb2.conf
a2enconf icingaweb2
````
```
### <a id="preparing-web-setup-from-source"></a> Preparing Icinga Web 2 Setup
@ -245,53 +245,53 @@ system group. The web server user and CLI user have to be added to this system g
Add the system group `icingaweb2` in the first place.
**Fedora, RHEL, CentOS, SLES and OpenSUSE**:
````
```
groupadd -r icingaweb2
````
```
**Debian and Ubuntu**:
````
```
addgroup --system icingaweb2
````
```
Add your web server's user to the system group `icingaweb2`
and restart the web server:
**Fedora, RHEL and CentOS**:
````
```
usermod -a -G icingaweb2 apache
service httpd restart
````
```
**SLES and OpenSUSE**:
````
```
usermod -A icingaweb2 wwwrun
service apache2 restart
````
```
**Debian and Ubuntu**:
````
```
usermod -a -G icingaweb2 www-data
service apache2 restart
````
```
Use `icingacli` to create the configuration directory which defaults to **/etc/icingaweb2**:
````
```
./bin/icingacli setup config directory
````
```
When using the web setup you are required to authenticate using a token. In order to generate a token use the
`icingacli`:
````
```
./bin/icingacli setup token create
````
```
In case you do not remember the token you can show it using the `icingacli`:
````
```
./bin/icingacli setup token show
````
```
### <a id="web-setup-from-source-wizard"></a> Icinga Web 2 Setup Wizard
@ -325,7 +325,7 @@ Puppet, Ansible, Chef, etc. modules.
Create the database and add a new user as shown below for MySQL:
````
```
sudo mysql -p
CREATE DATABASE icingaweb2;
@ -333,18 +333,18 @@ GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON icing
quit
mysql -p icingaweb2 < /usr/share/icingaweb2/etc/schema/mysql.schema.sql
````
```
Then generate a new password hash as described in the [authentication docs](authentication.md#authentication-configuration-db-setup)
and use it to insert a new user called `icingaadmin` into the database.
````
```
mysql -p icingaweb2
INSERT INTO icingaweb_user (name, active, password_hash) VALUES ('icingaadmin', 1, '$1$EzxLOFDr$giVx3bGhVm4lDUAw6srGX1');
quit
````
```
#### <a id="web-setup-manual-from-source-config"></a> Icinga Web 2 Manual Configuration
@ -352,7 +352,7 @@ quit
[resources.ini](resources.md#resources) providing the details for the Icinga Web 2 and
Icinga 2 IDO database configuration. Example for MySQL:
````
```
vim /etc/icingaweb2/resources.ini
[icingaweb2]
@ -373,11 +373,11 @@ port = "3306"
dbname = "icinga"
username = "icinga"
password = "icinga"
````
```
[config.ini](configuration.md#configuration) defining general application settings.
````
```
vim /etc/icingaweb2/config.ini
[logging]
@ -389,60 +389,60 @@ application = "icingaweb2"
[preferences]
type = "db"
resource = "icingaweb2"
````
```
[authentication.ini](authentication.md#authentication) for e.g. using the previously created database.
````
```
vim /etc/icingaweb2/authentication.ini
[icingaweb2]
backend = "db"
resource = "icingaweb2"
````
```
[roles.ini](security.md#security) granting the previously added `icingaadmin` user all permissions.
````
```
vim /etc/icingaweb2/roles.ini
[admins]
users = "icingaadmin"
permissions = "*"
````
```
#### <a id="web-setup-manual-from-source-config-monitoring-module"></a> Icinga Web 2 Manual Configuration Monitoring Module
[config.ini](../modules/monitoring/doc/configuration.md#configuration) defining additional security settings.
````
```
vim /etc/icingaweb2/modules/monitoring/config.ini
[security]
protected_customvars = "*pw*,*pass*,community"
````
```
[backends.ini](../modules/monitoring/doc/configuration.md#configuration) referencing the Icinga 2 DB IDO resource.
````
```
vim /etc/icingaweb2/modules/monitoring/backends.ini
[icinga2]
type = "ido"
resource = "icinga2"
````
```
[commandtransports.ini](../modules/monitoring/doc/commandtransports.md#commandtransports) defining the Icinga 2 command pipe.
````
```
vim /etc/icingaweb2/modules/monitoring/commandtransports.ini
[icinga2]
transport = "local"
path = "/var/run/icinga2/cmd/icinga2.cmd"
````
```
#### <a id="web-setup-manual-from-source-login"></a> Icinga Web 2 Manual Setup Login
@ -456,11 +456,11 @@ Finally visit Icinga Web 2 in your browser to login as `icingaadmin` user: `/ici
Icinga Web 2 Beta 2 introduces access control based on roles for secured actions. If you've already set up Icinga Web 2,
you are required to create the file **roles.ini** beneath Icinga Web 2's configuration directory with the following
content:
````
```
[administrators]
users = "your_user_name, another_user_name"
permissions = "*"
````
```
After please log out from Icinga Web 2 and log in again for having all permissions granted.
@ -519,3 +519,8 @@ The first release candidate of Icinga Web 2 introduces the following non-backwar
* Since Icinga Web 2 version 2.1.3 LDAP user group backends respect the configuration option `group_filter`.
Users who changed the configuration manually and used the option `filter` instead
have to change it back to `group_filter`.
## <a id="upgrading-to-2.2.0"></a> Upgrading to Icinga Web 2 2.2.0
* The menu entry `Authorization` beneath `Config` has been renamed to `Authentication`. The role, user backend and user
group backend configuration which was previously found beneath `Authentication` has been moved to `Application`.

View File

@ -1,9 +1,9 @@
# Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+
# Icinga Web 2 | (c) 2013-2016 Icinga Development Team | GPLv2+
%define revision 1
Name: icingaweb2
Version: 2.1.2
Version: 2.2.0
Release: %{revision}%{?dist}
Summary: Icinga Web 2
Group: Applications/System
@ -165,6 +165,18 @@ Requires: %{php} >= 5.3.0
Icinga Web 2 vendor library Parsedown
%package vendor-Zend
Version: 1.12.15
Release: 1%{?dist}
Summary: Icinga Web 2 vendor library Zend Framework
Group: Development/Libraries
License: BSD
Requires: %{php} >= 5.3.0
%description vendor-Zend
Icinga Web 2 vendor library Zend
%prep
%setup -q
@ -177,7 +189,7 @@ cp -prv application doc %{buildroot}/%{basedir}
cp -pv etc/bash_completion.d/icingacli %{buildroot}/%{_sysconfdir}/bash_completion.d/icingacli
cp -prv modules/{monitoring,setup,doc,translation} %{buildroot}/%{basedir}/modules
cp -prv library/Icinga %{buildroot}/%{phpdir}
cp -prv library/vendor/{dompdf,HTMLPurifier*,JShrink,lessphp,Parsedown} %{buildroot}/%{basedir}/library/vendor
cp -prv library/vendor/{dompdf,HTMLPurifier*,JShrink,lessphp,Parsedown,Zend} %{buildroot}/%{basedir}/library/vendor
cp -prv public/{css,img,js,error_norewrite.html} %{buildroot}/%{basedir}/public
cp -pv packages/files/apache/icingaweb2.conf %{buildroot}/%{wwwconfigdir}/icingaweb2.conf
cp -pv packages/files/bin/icingacli %{buildroot}/%{bindir}
@ -267,3 +279,8 @@ exit 0
%files vendor-Parsedown
%defattr(-,root,root)
%{basedir}/library/vendor/Parsedown
%files vendor-Zend
%defattr(-,root,root)
%{basedir}/library/vendor/Zend

View File

@ -520,25 +520,6 @@ abstract class ApplicationBootstrap
return $this;
}
/**
* Set up the resource factory
*
* @return $this
*/
protected function setupResourceFactory()
{
try {
$config = Config::app('resources');
ResourceFactory::setConfig($config);
} catch (NotReadableError $e) {
Logger::error(
new IcingaException('Cannot load resource configuration. An exception was thrown:', $e)
);
}
return $this;
}
/**
* Set up the user backend factory
*

View File

@ -41,7 +41,6 @@ class Cli extends ApplicationBootstrap
->setupInternationalization()
->parseBasicParams()
->setupLogger()
->setupResourceFactory()
->setupModuleManager()
->setupUserBackendFactory()
->loadSetupModuleIfNecessary();

View File

@ -120,7 +120,7 @@ class Manager
}
if (! is_readable($parent)) {
throw new NotReadableError(
'Cannot read enabled modules. Module directory\'s parent directory "%s" is not readable',
'Cannot read enabled modules. Config directory "%s" is not readable',
$parent
);
}

View File

@ -1289,7 +1289,7 @@ class Module
$class = $implementation;
}
Hook::register($name, $implementation, $class);
Hook::register($name, $class, $class);
return $this;
}

View File

@ -8,7 +8,7 @@ namespace Icinga\Application;
*/
class Version
{
const VERSION = '2.1.2';
const VERSION = '2.2.0';
/**
* Get the version of this instance of Icinga Web 2

View File

@ -82,22 +82,21 @@ class Web extends EmbeddedWeb
->setupLogging()
->setupErrorHandling()
->loadConfig()
->setupResourceFactory()
->setupRequest()
->setupSession()
->setupNotifications()
->setupRequest()
->setupResponse()
->setupUserBackendFactory()
->setupUser()
->setupTimezone()
->setupLogger()
->setupInternationalization()
->setupZendMvc()
->setupModuleManager()
->loadSetupModuleIfNecessary()
->loadEnabledModules()
->setupRoute()
->setupPagination();
->setupPagination()
->setupUserBackendFactory()
->setupUser()
->setupTimezone()
->setupLogger()
->setupInternationalization();
}
/**
@ -322,13 +321,7 @@ class Web extends EmbeddedWeb
'priority' => 810
),
'authentication' => array(
'label' => t('Authentication'),
'url' => 'config/userbackend',
'permission' => 'config/application/*',
'priority' => 820
),
'authorization' => array(
'label' => t('Authorization'),
'label' => t('Authentication'),
'permission' => 'config/authentication/*',
'priority' => 830,
'url' => 'role/list'
@ -370,9 +363,10 @@ class Web extends EmbeddedWeb
if (Logger::writesToFile()) {
$menu['system']['children']['application_log'] = array(
'label' => t('Application Log'),
'url' => 'list/applicationlog',
'priority' => 710
'label' => t('Application Log'),
'url' => 'list/applicationlog',
'permission' => 'application/log',
'priority' => 710
);
}
} else {

View File

@ -3,7 +3,6 @@
use Icinga\Util\Translator;
/**
* No-op translate
*
@ -19,6 +18,11 @@ function N_($messageId)
return $messageId;
}
// Workaround for test issues, this is required unless our tests are able to
// accomplish "real" bootstrapping
if (function_exists('t')) {
return;
}
if (extension_loaded('gettext')) {

View File

@ -244,7 +244,8 @@ class Auth
$this->user = Session::getSession()->get('user');
if ($this->user !== null && $this->user->isExternalUser() === true) {
list($originUsername, $field) = $this->user->getExternalUserInformation();
if (! array_key_exists($field, $_SERVER) || $_SERVER[$field] !== $originUsername) {
$username = getenv($field); // usually REMOTE_USER here
if ( !$username || $username !== $originUsername) {
$this->removeAuthorization();
}
}

View File

@ -1,143 +0,0 @@
<?php
/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
namespace Icinga\Authentication\UserGroup;
use Icinga\Exception\StatementException;
use Icinga\Data\Filter\Filter;
use Icinga\Repository\IniRepository;
use Icinga\User;
use Icinga\Util\StringHelper;
class IniUserGroupBackend extends IniRepository implements UserGroupBackendInterface
{
/**
* The query columns being provided
*
* @var array
*/
protected $queryColumns = array(
'groups' => array(
'group' => 'name',
'group_name' => 'name',
'parent' => 'parent',
'created_at' => 'ctime',
'last_modified' => 'mtime',
'users'
)
);
/**
* The columns which are not permitted to be queried
*
* @var array
*/
protected $blacklistedQueryColumns = array('group');
/**
* The search columns being provided
*
* @var array
*/
protected $searchColumns = array('group');
/**
* The value conversion rules to apply on a query or statement
*
* @var array
*/
protected $conversionRules = array(
'groups' => array(
'created_at' => 'date_time',
'last_modified' => 'date_time',
'users' => 'comma_separated_string'
)
);
/**
* Initialize this ini user group backend
*/
protected function init()
{
$this->ds->getConfigObject()->setKeyColumn('name');
}
/**
* Initialize this repository's filter columns
*
* @return array
*/
protected function initializeFilterColumns()
{
return array(
t('User Group') => 'group',
t('Parent') => 'parent',
t('Created At') => 'created_at',
t('Last Modified') => 'last_modified'
);
}
/**
* Add a new group to this backend
*
* @param string $target
* @param array $data
*
* @throws StatementException In case the operation has failed
*/
public function insert($target, array $data)
{
$data['created_at'] = time();
parent::insert($target, $data);
}
/**
* Update groups of this backend, optionally limited using a filter
*
* @param string $target
* @param array $data
* @param Filter $filter
*
* @throws StatementException In case the operation has failed
*/
public function update($target, array $data, Filter $filter = null)
{
$data['last_modified'] = time();
parent::update($target, $data, $filter);
}
/**
* Return the groups the given user is a member of
*
* @param User $user
*
* @return array
*/
public function getMemberships(User $user)
{
$result = $this->select()->fetchAll();
$groups = array();
foreach ($result as $group) {
$groups[$group->group_name] = $group->parent;
}
$username = strtolower($user->getUsername());
$memberships = array();
foreach ($result as $group) {
if ($group->users && !in_array($group->group_name, $memberships)) {
$users = array_map('strtolower', StringHelper::trimSplit($group->users));
if (in_array($username, $users)) {
$memberships[] = $group->group_name;
$parent = $groups[$group->group_name];
while ($parent !== null) {
$memberships[] = $parent;
$parent = isset($groups[$parent]) ? $groups[$parent] : null;
}
}
}
}
return $memberships;
}
}

View File

@ -22,8 +22,7 @@ class UserGroupBackend
protected static $defaultBackends = array(
'db',
'ldap',
'msldap',
//'ini'
'msldap'
);
/**
@ -155,9 +154,6 @@ class UserGroupBackend
case 'db':
$backend = new DbUserGroupBackend($resource);
break;
case 'ini':
$backend = new IniUserGroupBackend($resource);
break;
case 'ldap':
case 'msldap':
$backend = new LdapUserGroupBackend($resource);

View File

@ -5,6 +5,7 @@ namespace Icinga\Cli;
use Icinga\Application\ApplicationBootstrap as App;
use Icinga\Exception\IcingaException;
use Icinga\Exception\NotReadableError;
use Icinga\Exception\ProgrammingError;
use Icinga\Cli\Params;
use Icinga\Cli\Screen;
@ -421,10 +422,14 @@ class Loader
{
if ($this->modules === null) {
$this->modules = array();
$this->modules = array_unique(array_merge(
$this->app->getModuleManager()->listEnabledModules(),
$this->app->getModuleManager()->listLoadedModules()
));
try {
$this->modules = array_unique(array_merge(
$this->app->getModuleManager()->listEnabledModules(),
$this->app->getModuleManager()->listLoadedModules()
));
} catch (NotReadableError $e) {
$this->fail($e->getMessage());
}
}
return $this->modules;
}

View File

@ -153,6 +153,11 @@ class DbConnection implements Selectable, Extensible, Updatable, Reducible, Insp
$driverOptions[PDO::MYSQL_ATTR_INIT_COMMAND] =
'SET SESSION SQL_MODE=\'STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,'
. 'NO_AUTO_CREATE_USER,ANSI_QUOTES,PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION\';';
if (array_key_exists('charset', $adapterParamaters) && $adapterParamaters['charset']) {
$driverOptions[PDO::MYSQL_ATTR_INIT_COMMAND] .= 'SET NAMES ' . $adapterParamaters['charset']. ';';
unset($adapterParamaters['charset']);
}
$adapterParamaters['port'] = $this->config->get('port', 3306);
break;
case 'oci':

View File

@ -67,16 +67,14 @@ class ResourceFactory implements ConfigAwareFactory
}
/**
* Check if the existing resources are set. If not, throw an error.
* Check if the existing resources are set. If not, load them from resources.ini
*
* @throws ConfigurationError
*/
private static function assertResourcesExist()
{
if (self::$resources === null) {
throw new ConfigurationError(
'Resources not set up. Please contact your Icinga Web administrator'
);
self::$resources = Config::app('resources');
}
}

View File

@ -53,7 +53,11 @@ class TimezoneDetect
}
if (Platform::isCli() === false && array_key_exists(self::$cookieName, $_COOKIE)) {
list($offset, $dst) = explode(',', $_COOKIE[self::$cookieName]);
$cookieValue = $_COOKIE[self::$cookieName];
list($offset, $dst) = explode(
strpos($cookieValue, ',') === false ? '-' : ',',
$cookieValue
);
$timezoneName = timezone_name_from_abbr('', (int)$offset, (int)$dst);
self::$success = (bool)$timezoneName;

View File

@ -209,6 +209,7 @@ class Controller extends ModuleActionController
);
$editor = Widget::create('filterEditor');
/** @var \Icinga\Web\Widget\FilterEditor $editor */
call_user_func_array(
array($editor, 'preserveParams'),
array_merge($defaultPreservedParams, $preserveParams ?: array())
@ -221,10 +222,12 @@ class Controller extends ModuleActionController
->setSearchColumns($searchColumns)
->handleRequest($this->getRequest());
if (! $this->view->compact) {
$this->view->filterEditor = $editor;
if ($this->view->compact) {
$editor->setVisible(false);
}
$this->view->filterEditor = $editor;
return $this;
}
}

View File

@ -459,15 +459,13 @@ class ActionController extends Zend_Controller_Action
$layout->innerLayout = $this->innerLayout;
if ($user = $req->getUser()) {
// Cast preference app.show_benchmark to bool because preferences loaded from a preferences storage are
// always strings
if ((bool) $user->getPreferences()->getValue('icingaweb', 'show_benchmark', false) === true) {
if (!$this->_helper->viewRenderer->getNoRender()) {
if ((bool) $user->getPreferences()->getValue('icingaweb', 'show_benchmark', false)) {
if ($this->_helper->layout()->isEnabled()) {
$layout->benchmark = $this->renderBenchmark();
}
}
if ((bool) $user->getPreferences()->getValue('icingaweb', 'auto_refresh', true) === false) {
if (! (bool) $user->getPreferences()->getValue('icingaweb', 'auto_refresh', true)) {
$this->disableAutoRefresh();
}
}

View File

@ -96,6 +96,9 @@ class Cookie
*/
public function getDomain()
{
if ($this->domain === null) {
$this->domain = Config::app()->get('cookie', 'domain');
}
return $this->domain;
}
@ -182,9 +185,9 @@ class Cookie
if ($path === null) {
// The following call could be used as default for ConfigObject::get(), but we prevent unnecessary
// function calls here, if the path is set in the config
$path = Icinga::app()->getRequest()->getBaseUrl();
$path = Icinga::app()->getRequest()->getBaseUrl() . '/'; // Zend has rtrim($baseUrl, '/')
}
return $path;
$this->path = $path;
}
return $this->path;
}
@ -219,7 +222,7 @@ class Cookie
// function calls here, if the secure flag is set in the config
$secure = Icinga::app()->getRequest()->isSecure();
}
return $secure;
$this->secure = $secure;
}
return $this->secure;
}

View File

@ -0,0 +1,41 @@
<?php
/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
namespace Icinga\Web\Form\Validator;
use Zend_Validate_Abstract;
/**
* Validator that checks whether a textfield doesn't contain raw double quotes
*/
class UrlValidator extends Zend_Validate_Abstract
{
/**
* Error templates
*
* @var array
*
* @see Zend_Validate_Abstract::$_messageTemplates
*/
protected $_messageTemplates = array(
'HAS_QUOTES' => 'The url must not contain raw double quotes. If you really need double quotes, use %22 instead.'
);
/**
* Validate the input value
*
* @param string $value The string to validate
*
* @return bool true if and only if the input is valid, otherwise false
*
* @see Zend_Validate_Abstract::isValid()
*/
public function isValid($value)
{
$hasQuotes = false === strpos($value, '"');
if (! $hasQuotes) {
$this->_error('HAS_QUOTES');
}
return $hasQuotes;
}
}

View File

@ -155,18 +155,16 @@ class LessCompiler
$moduleCss .= '}';
}
$moduleCss = preg_replace(
'/(\.icinga-module\.module-[^\s]+) (#layout\.[^\s]+)/m',
'\2 \1',
$moduleCss
);
$this->source .= $moduleCss;
if ($this->theme !== null) {
$this->source .= file_get_contents($this->theme);
}
return $this->lessc->compile($this->source);
return preg_replace(
'/(\.icinga-module\.module-[^\s]+) (#layout\.[^\s]+)/m',
'\2 \1',
$this->lessc->compile($this->source)
);
}
}

View File

@ -260,8 +260,9 @@ class Menu implements RecursiveIterator
));
if (Logger::writesToFile()) {
$section->add(t('Application Log'), array(
'url' => 'list/applicationlog',
'priority' => 710
'url' => 'list/applicationlog',
'permission' => 'application/log',
'priority' => 710
));
}

View File

@ -192,7 +192,7 @@ class NavigationItemRenderer
$content = sprintf(
'<a%s href="%s"%s>%s</a>',
$this->view()->propertiesToString($item->getAttributes()),
$url,
$this->view()->escape($url->getAbsoluteUrl('&')),
$this->renderTargetAttribute(),
$label
);
@ -218,7 +218,7 @@ class NavigationItemRenderer
protected function renderTargetAttribute()
{
$target = $this->getItem()->getTarget();
if ($target === null) {
if ($target === null || $this->getItem()->getUrl()->getAbsoluteUrl() == '#') {
return '';
}

View File

@ -5,6 +5,7 @@ namespace Icinga\Web\Session;
use Icinga\Application\Logger;
use Icinga\Exception\ConfigurationError;
use Icinga\Web\Cookie;
/**
* Session implementation in PHP
@ -102,11 +103,21 @@ class PhpSession extends Session
ini_set('session.cache_limiter', null);
}
$cookie = new Cookie('bogus');
session_set_cookie_params(
0,
$cookie->getPath(),
$cookie->getDomain(),
$cookie->isSecure(),
true
);
session_start();
if ($this->hasBeenTouched) {
ini_set('session.use_cookies', true);
ini_set('session.use_only_cookies', true);
/** @noinspection PhpUndefinedVariableInspection */
ini_set('session.cache_limiter', $cacheLimiter);
}
}

View File

@ -212,17 +212,18 @@ class Url
}
/**
* Set the new Filter of the url to be the current filter and the given filter
* Add the given filter to the current filter of the URL
*
* @param Filter $and
* @param Filter $and
*
* @return $this
*/
public function addFilter($and)
{
$this->setQueryString(
Filter::matchAll(
$and,
Filter::fromQueryString($this->getQueryString())
)->toQueryString()
Filter::fromQueryString($this->getQueryString())
->andFilter($and)
->toQueryString()
);
return $this;
}

View File

@ -55,6 +55,13 @@ class FilterEditor extends AbstractWidget
*/
private $selectedIdx;
/**
* Whether the filter control is visible
*
* @var bool
*/
protected $visible = true;
/**
* Create a new FilterWidget
*
@ -144,6 +151,30 @@ class FilterEditor extends AbstractWidget
return $this;
}
/**
* Get whether the filter control is visible
*
* @return bool
*/
public function isVisible()
{
return $this->visible;
}
/**
* Set whether the filter control is visible
*
* @param bool $visible
*
* @return $this
*/
public function setVisible($visible)
{
$this->visible = (bool) $visible;
return $this;
}
protected function redirectNow($url)
{
$response = Icinga::app()->getFrontController()->getResponse();
@ -714,7 +745,7 @@ class FilterEditor extends AbstractWidget
} else {
$title = t('Modify this filter');
if (! $this->filter->isEmpty()) {
$title .= ': ' . $this->filter;
$title .= ': ' . $this->view()->escape($this->filter);
}
}
return $html
@ -731,8 +762,11 @@ class FilterEditor extends AbstractWidget
public function render()
{
if (! $this->visible) {
return '';
}
if (! $this->preservedUrl()->getParam('modifyFilter')) {
return '<div class="filter">' . $this->renderSearch() . $this->shorten($this->filter, 50) . '</div>';
return '<div class="filter">' . $this->renderSearch() . $this->view()->escape($this->shorten($this->filter, 50)) . '</div>';
}
return '<div class="filter">'
. $this->renderSearch()

View File

@ -1,4 +1,4 @@
Module: doc
Version: 2.1.2
Version: 2.2.0
Description: Documentation module
Extracts, shows and exports documentation for Icinga Web 2 and its modules.

View File

@ -48,6 +48,7 @@ class Monitoring_ActionsController extends Controller
$form = new ScheduleHostDowntimeCommandForm();
$form
->setIsApiTarget(true)
->setBackend($this->backend)
->setObjects($hostList->fetch())
->handleRequest($this->getRequest());
}
@ -96,6 +97,7 @@ class Monitoring_ActionsController extends Controller
$form = new ScheduleServiceDowntimeCommandForm();
$form
->setIsApiTarget(true)
->setBackend($this->backend)
->setObjects($serviceList->fetch())
->handleRequest($this->getRequest());
}

View File

@ -93,6 +93,7 @@ class HealthController extends Controller
$this->view->programStatus = $programStatus;
$toggleFeaturesForm = new ToggleInstanceFeaturesCommandForm();
$toggleFeaturesForm
->setBackend($this->backend)
->setStatus($programStatus)
->load($programStatus)
->handleRequest();

View File

@ -151,7 +151,6 @@ class HostController extends MonitoredObjectController
$this->assertPermission('monitoring/command/downtime/schedule');
$form = new ScheduleHostDowntimeCommandForm();
$form->setBackend($this->backend);
$form->setTitle($this->translate('Schedule Host Downtime'));
$this->handleCommandForm($form);
}
@ -164,7 +163,6 @@ class HostController extends MonitoredObjectController
$this->assertPermission('monitoring/command/process-check-result');
$form = new ProcessCheckResultCommandForm();
$form->setBackend($this->backend);
$form->setTitle($this->translate('Submit Passive Host Check Result'));
$this->handleCommandForm($form);
}

View File

@ -69,6 +69,7 @@ class HostsController extends Controller
protected function handleCommandForm(ObjectsCommandForm $form)
{
$form
->setBackend($this->backend)
->setObjects($this->hostList)
->setRedirectUrl(Url::fromPath('monitoring/hosts/show')->setParams($this->params))
->handleRequest();
@ -83,11 +84,13 @@ class HostsController extends Controller
public function showAction()
{
$this->setAutorefreshInterval(15);
$checkNowForm = new CheckNowCommandForm();
$checkNowForm
->setObjects($this->hostList)
->handleRequest();
$this->view->checkNowForm = $checkNowForm;
if ($this->Auth()->hasPermission('monitoring/command/schedule-check')) {
$checkNowForm = new CheckNowCommandForm();
$checkNowForm
->setObjects($this->hostList)
->handleRequest();
$this->view->checkNowForm = $checkNowForm;
}
$acknowledgedObjects = $this->hostList->getAcknowledgedObjects();
if (! empty($acknowledgedObjects)) {
@ -192,7 +195,6 @@ class HostsController extends Controller
$this->assertPermission('monitoring/command/downtime/schedule');
$form = new ScheduleHostDowntimeCommandForm();
$form->setBackend($this->backend);
$form->setTitle($this->translate('Schedule Host Downtimes'));
$this->handleCommandForm($form);
}
@ -205,7 +207,6 @@ class HostsController extends Controller
$this->assertPermission('monitoring/command/process-check-result');
$form = new ProcessCheckResultCommandForm();
$form->setBackend($this->backend);
$form->setTitle($this->translate('Submit Passive Host Check Results'));
$this->handleCommandForm($form);
}

View File

@ -121,7 +121,6 @@ class ServiceController extends MonitoredObjectController
$this->assertPermission('monitoring/command/process-check-result');
$form = new ProcessCheckResultCommandForm();
$form->setBackend($this->backend);
$form->setTitle($this->translate('Submit Passive Service Check Result'));
$this->handleCommandForm($form);
}

View File

@ -75,6 +75,7 @@ class ServicesController extends Controller
protected function handleCommandForm(ObjectsCommandForm $form)
{
$form
->setBackend($this->backend)
->setObjects($this->serviceList)
->setRedirectUrl(Url::fromPath('monitoring/services/show')->setParams($this->params))
->handleRequest();
@ -90,11 +91,13 @@ class ServicesController extends Controller
public function showAction()
{
$this->setAutorefreshInterval(15);
$checkNowForm = new CheckNowCommandForm();
$checkNowForm
->setObjects($this->serviceList)
->handleRequest();
$this->view->checkNowForm = $checkNowForm;
if ($this->Auth()->hasPermission('monitoring/command/schedule-check')) {
$checkNowForm = new CheckNowCommandForm();
$checkNowForm
->setObjects($this->serviceList)
->handleRequest();
$this->view->checkNowForm = $checkNowForm;
}
$acknowledgedObjects = $this->serviceList->getAcknowledgedObjects();
if (! empty($acknowledgedObjects)) {
@ -207,7 +210,6 @@ class ServicesController extends Controller
$this->assertPermission('monitoring/command/process-check-result');
$form = new ProcessCheckResultCommandForm();
$form->setBackend($this->backend);
$form->setTitle($this->translate('Submit Passive Service Check Results'));
$this->handleCommandForm($form);
}

View File

@ -138,7 +138,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm
)
);
if (! preg_match('~^v2\.\d+\.\d+.*$~', $this->status->program_version)) {
if (! $this->getBackend()->isIcinga2($this->status->program_version)) {
$this->addElement(
'checkbox',
ToggleInstanceFeatureCommand::FEATURE_HOST_OBSESSING,

View File

@ -34,21 +34,21 @@ class AddCommentCommandForm extends ObjectsCommandForm
*/
public function createElements(array $formData = array())
{
$this->addElements(array(
$this->addElement(
'textarea',
'comment',
array(
'textarea',
'comment',
array(
'required' => true,
'label' => $this->translate('Comment'),
'description' => $this->translate(
'If you work with other administrators, you may find it useful to share information about the'
. ' the host or service that is having problems. Make sure you enter a brief description of'
. ' what you are doing.'
)
'required' => true,
'label' => $this->translate('Comment'),
'description' => $this->translate(
'If you work with other administrators, you may find it useful to share information about the'
. ' the host or service that is having problems. Make sure you enter a brief description of'
. ' what you are doing.'
)
),
array(
)
);
if (! $this->getBackend()->isIcinga2()) {
$this->addElement(
'checkbox',
'persistent',
array(
@ -59,8 +59,8 @@ class AddCommentCommandForm extends ObjectsCommandForm
. ' restarted.'
)
)
)
));
);
}
return $this;
}
@ -76,7 +76,9 @@ class AddCommentCommandForm extends ObjectsCommandForm
$comment->setObject($object);
$comment->setComment($this->getElement('comment')->getValue());
$comment->setAuthor($this->request->getUser()->getUsername());
$comment->setPersistent($this->getElement('persistent')->isChecked());
if (($persistent = $this->getElement('persistent')) !== null) {
$comment->setPersistent($persistent->isChecked());
}
$this->getTransport($this->request)->send($comment);
}
Notification::success($this->translatePlural(

View File

@ -124,7 +124,7 @@ class ProcessCheckResultCommandForm extends ObjectsCommandForm
ProcessCheckResultCommand::HOST_DOWN => $this->translate('DOWN', 'icinga.state')
);
if (substr($this->getBackend()->getProgramVersion(), 0, 2) !== 'v2') {
if (! $this->getBackend()->isIcinga2()) {
$options[ProcessCheckResultCommand::HOST_UNREACHABLE] = $this->translate('UNREACHABLE', 'icinga.state');
}

View File

@ -12,8 +12,40 @@ use Icinga\Web\Notification;
class RemoveAcknowledgementCommandForm extends ObjectsCommandForm
{
/**
* (non-PHPDoc)
* @see \Zend_Form::init() For the method documentation.
* Whether to show the submit label next to the remove icon
*
* The submit label is disabled in detail views but should be enabled in multi-select views.
*
* @var bool
*/
protected $labelEnabled = false;
/**
* Whether to show the submit label next to the remove icon
*
* @return bool
*/
public function isLabelEnabled()
{
return $this->labelEnabled;
}
/**
* Set whether to show the submit label next to the remove icon
*
* @param bool $labelEnabled
*
* @return $this
*/
public function setLabelEnabled($labelEnabled)
{
$this->labelEnabled = (bool) $labelEnabled;
return $this;
}
/**
* {@inheritdoc}
*/
public function init()
{
@ -36,7 +68,7 @@ class RemoveAcknowledgementCommandForm extends ObjectsCommandForm
),
'escape' => false,
'ignore' => true,
'label' => $this->getView()->icon('cancel'),
'label' => $this->getSubmitLabel(),
'title' => $this->translatePlural(
'Remove problem acknowledgement',
'Remove problem acknowledgements',
@ -45,12 +77,29 @@ class RemoveAcknowledgementCommandForm extends ObjectsCommandForm
'type' => 'submit'
)
);
return $this;
}
/**
* (non-PHPDoc)
* @see \Icinga\Web\Form::onSuccess() For the method documentation.
* {@inheritdoc}
*/
public function getSubmitLabel()
{
$label = $this->getView()->icon('cancel');
if ($this->isLabelEnabled()) {
$label .= $this->translatePlural(
'Remove problem acknowledgement',
'Remove problem acknowledgements',
count($this->objects)
);
}
return $label;
}
/**
* {@inheritdoc}
*/
public function onSuccess()
{
@ -66,6 +115,7 @@ class RemoveAcknowledgementCommandForm extends ObjectsCommandForm
'Removing problem acknowledgements..',
count($this->objects)
));
return true;
}
}

View File

@ -33,7 +33,7 @@ class ScheduleHostDowntimeCommandForm extends ScheduleServiceDowntimeCommandForm
)
);
if (substr($this->getBackend()->getProgramVersion(), 0, 2) !== 'v2') {
if (! $this->getBackend()->isIcinga2()) {
$this->addElement(
'select',
'child_hosts',

View File

@ -59,7 +59,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm
'permission' => 'monitoring/command/feature/object/flap-detection'
)
);
if (preg_match('~^[vr]2\.\d+\.\d+.*$~', $this->getIcingaVersion())) {
if ($this->getBackend()->isIcinga2()) {
unset($features[ToggleObjectFeatureCommand::FEATURE_OBSESSING]);
}
$this->features = $features;
@ -176,14 +176,4 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm
return true;
}
/**
* Fetch and return the program version of the current instance
*
* @return string
*/
protected function getIcingaVersion()
{
return $this->getBackend()->select()->from('programstatus', array('program_version'))->fetchOne();
}
}

View File

@ -0,0 +1,38 @@
<?php
/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
/**
* Helper for escaping comments, but preserving links
*/
class Zend_View_Helper_EscapeComment extends Zend_View_Helper_Abstract
{
/**
* The purifier to use for escaping
*
* @var HTMLPurifier
*/
protected static $purifier;
/**
* Escape any comment for being placed inside HTML, but preserve simple links (<a href="...">).
*
* @param string $comment
*
* @return string
*/
public function escapeComment($comment)
{
if (self::$purifier === null) {
require_once 'HTMLPurifier/Bootstrap.php';
require_once 'HTMLPurifier.php';
require_once 'HTMLPurifier.autoload.php';
$config = HTMLPurifier_Config::createDefault();
$config->set('Core.EscapeNonASCIICharacters', true);
$config->set('HTML.Allowed', 'a[href]');
$config->set('Cache.DefinitionImpl', null);
self::$purifier = new HTMLPurifier($config);
}
return self::$purifier->purify($comment);
}
}

View File

@ -27,13 +27,14 @@ class Zend_View_Helper_IconImage extends Zend_View_Helper_Abstract
public function host($object)
{
if ($object->host_icon_image && ! preg_match('/[\'"]/', $object->host_icon_image)) {
return $this->view->icon(
return $this->view->img(
Macro::resolveMacros($object->host_icon_image, $object),
null,
array(
'alt' => $object->host_icon_image_alt,
'title' => $object->host_icon_image_alt,
'data-tooltip-delay' => 0
'alt' => $object->host_icon_image_alt,
'data-tooltip-delay' => 0,
'class' => 'host-icon-image',
'title' => $object->host_icon_image_alt
)
);
}
@ -49,13 +50,14 @@ class Zend_View_Helper_IconImage extends Zend_View_Helper_Abstract
public function service($object)
{
if ($object->service_icon_image && ! preg_match('/[\'"]/', $object->service_icon_image)) {
return $this->view->icon(
return $this->view->img(
Macro::resolveMacros($object->service_icon_image, $object),
null,
array(
'alt' => $object->service_icon_image_alt,
'title' => $object->service_icon_image_alt,
'data-tooltip-delay' => 0
'alt' => $object->service_icon_image_alt,
'class' => 'service-icon-image',
'data-tooltip-delay' => 0,
'title' => $object->service_icon_image_alt
)
);
}

View File

@ -33,7 +33,7 @@ class Zend_View_Helper_PluginOutput extends Zend_View_Helper_Abstract
return '';
}
$output = preg_replace('~<br[^>]*>~', "\n", $output);
if (strlen($output) > strlen(strip_tags($output))) {
if (preg_match('~<[^>]*["/\'][^>]*>~', $output)) {
// HTML
$output = preg_replace(
'~<table~',
@ -97,7 +97,7 @@ class Zend_View_Helper_PluginOutput extends Zend_View_Helper_Abstract
$config = HTMLPurifier_Config::createDefault();
$config->set('Core.EscapeNonASCIICharacters', true);
$config->set('HTML.Allowed', 'p,br,b,a[href],i,table,tr,td[colspan],div[class]');
$config->set('HTML.Allowed', 'p,br,b,a[href],i,table,tr,td[colspan],div,*[class]');
// This avoids permission problems:
// $config->set('Core.DefinitionCache', null);
$config->set('Cache.DefinitionImpl', null);

View File

@ -45,7 +45,7 @@
</tr>
<tr title="<?= $this->translate('A comment, as entered by the author, associated with the scheduled downtime'); ?>">
<th><?= $this->translate('Comment') ?></th>
<td class="comment-text"><?= $this->nl2br($this->escape($this->downtime->comment)) ?></td>
<td class="comment-text"><?= $this->nl2br($this->escapeComment($this->downtime->comment)) ?></td>
</tr>
</tbody>
</table>

View File

@ -50,7 +50,7 @@
'<b>' . $acknowledgedCount . '</b>'
); ?> </th>
<td>
<?= $removeAckForm ?>
<?= $removeAckForm->setLabelEnabled(true) ?>
</td>
</tr>
<?php endif ?>
@ -174,10 +174,12 @@
</td>
</tr>
<tr>
<th> <?= $this->translate('Schedule Check') ?> </th>
<td> <?= $checkNowForm ?> </td>
</tr>
<?php if (isset($checkNowForm)): // Form is unset if the current user lacks the respective permission ?>
<tr>
<th> <?= $this->translate('Schedule Check') ?> </th>
<td> <?= $checkNowForm ?> </td>
</tr>
<?php endif ?>
<tr>
<th></th>

View File

@ -50,6 +50,7 @@ if (! $this->compact): ?>
$stateBadges = new StateBadges();
$stateBadges
->setUrl('monitoring/list/hosts')
->setBaseFilter($this->filterEditor->getFilter())
->add(
StateBadges::STATE_UP,
$hostgroup->hosts_up,

View File

@ -86,9 +86,7 @@ if (! $this->compact): ?>
<?php endif ?>
<span class="state-icons"><?= implode(' ', $this->hostFlags($host)) ?></span>
</div>
<p class="overview-plugin-output">
<?= $this->pluginOutput($this->ellipsis($host->host_output, 10000), true) ?>
</p>
<p class="overview-plugin-output"><?= $this->pluginOutput($this->ellipsis($host->host_output, 10000), true) ?></p>
</td>
<?php foreach($this->addColumns as $col): ?>
<td><?= $this->escape($host->$col) ?></td>

View File

@ -65,14 +65,12 @@ if (! $this->compact): ?>
)
) ?>
<?php else: ?>
<?= $this->translate('Sent out to any contact') ?>
<?= $this->translate('Not sent out to any contact') ?>
<?php endif ?>
</div>
<?php endif ?>
</div>
<p class="overview-plugin-output">
<?= $this->pluginOutput($this->ellipsis($notification->notification_output, 10000), true) ?>
</p>
<p class="overview-plugin-output"><?= $this->pluginOutput($this->ellipsis($notification->notification_output, 10000), true) ?></p>
</td>
</tr>
<?php endforeach ?>

View File

@ -82,7 +82,7 @@ $hostFilter = '(host_name=' . implode('|host_name=', array_keys($pivotData)) . '
$service->host_display_name
),
'class' => 'bg-color-' . Service::getStateText($service->service_state) . ($service->service_handled ? ' handled' : ''),
'title' => $this->escape($service->service_output)
'title' => $service->service_output
)
) ?>
</td>

View File

@ -43,6 +43,7 @@ if (! $this->compact): ?>
$stateBadges = new StateBadges();
$stateBadges
->setUrl('monitoring/list/services')
->setBaseFilter($this->filterEditor->getFilter())
->add(
StateBadges::STATE_OK,
$serviceGroup->services_ok,

View File

@ -90,9 +90,7 @@ if (! $this->compact): ?>
<div class="overview-performance-data">
<?= $this->perfdata($service->service_perfdata, true, 5) ?>
</div>
<p class="overview-plugin-output">
<?= $this->pluginOutput($this->ellipsis($service->service_output, 10000), true) ?>
</p>
<p class="overview-plugin-output"><?= $this->pluginOutput($this->ellipsis($service->service_output, 10000), true) ?></p>
</div>
</td>
<?php foreach($this->addColumns as $col): ?>

View File

@ -36,10 +36,11 @@
<?= $this->timeAgo($comment->timestamp) ?>
</span>
<span class="comment-icons" data-base-target="_self">
<?= $comment->persistent ? $this->icon('attach', 'This comment is persistent.') : '' ?>
<?= $comment->persistent ? $this->icon('attach', 'This comment is persistent') : '' ?>
<?= $comment->expiration ? $this->icon('clock', sprintf(
$this->translate('This comment expires %s.'),
$this->timeUntil($comment->expiration)
$this->translate('This comment expires on %s at %s'),
$this->formatDate($comment->expiration),
$this->formatTime($comment->expiration)
)) : '' ?>
<?php if (isset($delCommentForm)) {
$deleteButton = clone $delCommentForm;
@ -56,5 +57,5 @@
</span>
</div>
<p class="comment-text">
<?= $this->nl2br($this->escape($comment->comment)) ?>
<?= $this->nl2br($this->escapeComment($comment->comment)) ?>
</p>

View File

@ -67,6 +67,6 @@
</span>
</div>
<p class="comment-text">
<?= $this->nl2br($this->escape($downtime->comment)) ?>
<?= $this->nl2br($this->escapeComment($downtime->comment)) ?>
</p>
</td>

View File

@ -143,12 +143,11 @@ $history->limit($limit * $page);
) ?>
<?php endif ?>
<?php endif ?>
<p class="overview-plugin-output">
<?php if ($icon) {
echo $this->icon($icon, null, $iconCssClass ? array('class' => $iconCssClass) : array());
} ?>
<?= nl2br($this->createTicketLinks($this->escape($msg)), false) ?>
</p>
<p class="overview-plugin-output"><?php if ($icon) {
echo $this->icon($icon, null, $iconCssClass ? array('class' => $iconCssClass) : array());
} ?><?= $this->nl2br($this->createTicketLinks($this->escapeComment($msg)))
// TODO(ak): this allows only a[href] in messages, but plugin output allows more
?></p>
</td>
</tr>
<?php endforeach ?>

View File

@ -49,7 +49,7 @@
) ?>
</th>
<td>
<?= $removeAckForm ?>
<?= $removeAckForm->setLabelEnabled(true) ?>
</td>
</tr>
<?php endif ?>
@ -176,10 +176,12 @@
</td>
</tr>
<tr>
<th> <?= $this->translate('Schedule Check') ?> </th>
<td> <?= $checkNowForm ?> </td>
</tr>
<?php if (isset($checkNowForm)): // Form is unset if the current user lacks the respective permission ?>
<tr>
<th> <?= $this->translate('Schedule Check') ?> </th>
<td> <?= $checkNowForm ?> </td>
</tr>
<?php endif ?>
<tr>
<th></th>

View File

@ -44,7 +44,7 @@ $acknowledgement = $object->acknowledgement;
} ?>
</dt>
<dd>
<?= $this->nl2br($this->createTicketLinks($this->escape($acknowledgement->getComment()))) ?>
<?= $this->nl2br($this->createTicketLinks($this->escapeComment($acknowledgement->getComment()))) ?>
</dd>
</dl>
<?php elseif (isset($removeAckForm)): ?>

View File

@ -4,16 +4,14 @@
<?= $this->translate('Check Source') ?>
</th>
<td>
<?php if ($object->is_reachable !== null) {
if ((bool) $object->is_reachable) {
echo $this->icon('circle', $this->translate('Is reachable'), array('class' => 'fg-color-ok'));
} else {
echo $this->icon('circle', $this->translate('Not reachable'), array('class' => 'fg-color-critical'));
}
} ?>
<?= $this->escape($object->check_source) ?>
<?php if ($object->is_reachable !== null): ?>
<span class="check-source-meta"><?= (bool) $object->is_reachable ? $this->translate('is reachable') : $this->translate('is not reachable') ?></span>
<?php if ((bool) $object->is_reachable) {
echo $this->icon('circle', $this->translate('Is reachable'), array('class' => 'check-source-reachable'));
} else {
echo $this->icon('circle', $this->translate('Not reachable'), array('class' => 'check-source-not-reachable'));
} ?>
<?php endif ?>
</td>
</tr>

View File

@ -6,18 +6,28 @@ $activeChecksEnabled = (bool) $object->active_checks_enabled;
<tr>
<th><?= $activeChecksEnabled ? $this->translate('Last check') : $this->translate('Last update') ?></th>
<td data-base-target="_self">
<?php if ((int) $object->state !== 99): ?>
<?= $this->timeAgo($object->last_check) ?>
<?php if ($object->next_update < time()): ?>
<?= $this->icon('circle', $this->translate('Check result is late'), array('class' => 'check-result-late')) ?>
<?php endif ?>
<?php endif ?>
<?php if (isset($checkNowForm)) { // Form is unset if the current user lacks the respective permission
echo $checkNowForm;
} ?>
<?php if ((int) $object->state !== 99) {
echo $this->timeAgo($object->last_check);
} ?>
</td>
</tr>
<tr>
<th><?= $activeChecksEnabled ? $this->translate('Next check') : $this->translate('Next update') ?></th>
<td>
<?php if ((int) $object->state !== 99) {
if ($activeChecksEnabled) {
echo $this->timeUntil($object->next_check);
} else {
echo sprintf($this->translate('expected %s'), $this->timeUntil($object->next_update));
}
} ?>
<?php if ($activeChecksEnabled && $this->hasPermission('monitoring/command/schedule-check')) {
if ($object->getType() === $object::TYPE_SERVICE) {
echo $this->qlink(
@ -49,16 +59,6 @@ $activeChecksEnabled = (bool) $object->active_checks_enabled;
);
}
} ?>
<?php if ((int) $object->state !== 99) {
if ($activeChecksEnabled) {
echo $this->timeUntil($object->next_check);
} else {
echo sprintf($this->translate('expected %s'), $this->timeUntil($object->next_update));
}
} ?>
<?php if ($object->next_update < time()) {
echo $this->icon('circle', $this->translate('Check result is late'), array('class' => 'fg-color-critical'));
} ?>
</td>
</tr>

View File

@ -67,7 +67,7 @@ if (empty($object->comments) && ! $addLink) {
} ?>
</dt>
<dd>
<?= $this->nl2br($this->createTicketLinks($this->escape($comment->comment))) ?>
<?= $this->nl2br($this->createTicketLinks($this->escapeComment($comment->comment))) ?>
</dd>
<?php endforeach ?>
</dl>

View File

@ -96,7 +96,7 @@ if (empty($object->comments) && ! $addLink) {
} ?>
</dt>
<dd>
<?= $this->nl2br($this->createTicketLinks($this->escape($downtime->comment))) ?>
<?= $this->nl2br($this->createTicketLinks($this->escapeComment($downtime->comment))) ?>
</dd>
<?php endforeach ?>
</dl>

View File

@ -28,7 +28,7 @@ use Icinga\Module\Monitoring\Object\Service;
<?php if ($services_critical_handled): ?>
<?= $this->qlink(
$services_critical_handled . ' ' . (
$services_critical_unhandled ? $this->translate('Acknowledged') : Service::getStateText(2, true)
$services_critical_unhandled ? $this->translate('Handled') : Service::getStateText(2, true)
),
'monitoring/list/services',
array(
@ -38,8 +38,8 @@ use Icinga\Module\Monitoring\Object\Service;
),
array('title' => sprintf(
$this->translatePlural(
'List %u service that is currently in state CRITICAL (Acknowledged)',
'List %u services which are currently in state CRITICAL (Acknowledged)',
'List %u service that is currently in state CRITICAL (Handled)',
'List %u services which are currently in state CRITICAL (Handled)',
$services_critical_handled
),
$services_critical_handled
@ -127,7 +127,7 @@ use Icinga\Module\Monitoring\Object\Service;
<?php if ($services_warning_handled): ?>
<?= $this->qlink(
$services_warning_handled . ' ' . (
$services_warning_unhandled ? $this->translate('Acknowledged') : Service::getStateText(1, true)
$services_warning_unhandled ? $this->translate('Handled') : Service::getStateText(1, true)
),
'monitoring/list/services',
array(
@ -137,8 +137,8 @@ use Icinga\Module\Monitoring\Object\Service;
),
array('title' => sprintf(
$this->translatePlural(
'List %u service that is currently in state WARNING (Acknowledged)',
'List %u services which are currently in state WARNING (Acknowledged)',
'List %u service that is currently in state WARNING (Handled)',
'List %u services which are currently in state WARNING (Handled)',
$services_warning_handled
),
$services_warning_handled
@ -226,7 +226,7 @@ use Icinga\Module\Monitoring\Object\Service;
<?php if ($services_unknown_handled): ?>
<?= $this->qlink(
$services_unknown_handled . ' ' . (
$services_unknown_unhandled ? $this->translate('Acknowledged') : Service::getStateText(3, true)
$services_unknown_unhandled ? $this->translate('Handled') : Service::getStateText(3, true)
),
'monitoring/list/services',
array(
@ -236,8 +236,8 @@ use Icinga\Module\Monitoring\Object\Service;
),
array('title' => sprintf(
$this->translatePlural(
'List %u service that is currently in state UNKNOWN (Acknowledged)',
'List %u services which are currently in state UNKNOWN (Acknowledged)',
'List %u service that is currently in state UNKNOWN (Handled)',
'List %u services which are currently in state UNKNOWN (Handled)',
$services_unknown_handled
),
$services_unknown_handled

View File

@ -341,4 +341,22 @@ class MonitoringBackend implements Selectable, Queryable, ConnectionInterface
{
return $this->select()->from('programstatus', array('program_version'))->fetchOne();
}
/**
* Get whether the backend is Icinga 2
*
* @param string $programVersion
*
* @return bool
*/
public function isIcinga2($programVersion = null)
{
if ($programVersion === null) {
$programVersion = $this->select()->from('programstatus', array('program_version'))->fetchOne();
}
return (bool) preg_match(
'/^[vr]2\.\d+\.\d+.*$/',
$programVersion
);
}
}

View File

@ -111,16 +111,16 @@ class CommandTransport implements CommandTransportInterface
*/
public function send(IcingaCommand $command, $now = null)
{
$tries = 0;
foreach (static::getConfig() as $transportConfig) {
$transport = static::createTransport($transportConfig);
$errors = array();
foreach (static::getConfig() as $name => $transportConfig) {
$transport = static::createTransport($transportConfig);
if ($this->transferPossible($command, $transport)) {
try {
$transport->send($command, $now);
} catch (CommandTransportException $e) {
Logger::error($e);
$tries += 1;
$errors[] = sprintf('%s: %s.', $name, rtrim($e->getMessage(), '.'));
continue; // Try the next transport
}
@ -128,14 +128,8 @@ class CommandTransport implements CommandTransportInterface
}
}
if ($tries > 0) {
throw new CommandTransportException(
mt(
'monitoring',
'Failed to send external Icinga command. None of the configured transports'
. ' was able to transfer the command. Please see the log for more details.'
)
);
if (! empty($errors)) {
throw new CommandTransportException(implode("\n", $errors));
}
throw new CommandTransportException(

View File

@ -95,7 +95,9 @@ abstract class DataView implements QueryInterface, SortRules, FilterColumns, Ite
public function dump()
{
$this->order();
if (! $this->isSorted) {
$this->order();
}
return $this->query->dump();
}

View File

@ -89,7 +89,11 @@ class HostStatus extends DataView
) {
return array('host', 'host_address', 'host_address6');
} else {
return array('host', 'host_display_name');
if ($this->connection->isIcinga2()) {
return array('host', 'host_display_name');
} else {
return array('host', 'host_display_name', 'host_alias');
}
}
}

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Object;
use stdClass;
use InvalidArgumentException;
use Icinga\Application\Config;
use Icinga\Data\Filter\Filter;
@ -456,18 +457,34 @@ abstract class MonitoredObject implements Filterable
$customvars = $this->hostVariables;
}
$this->customvars = array();
foreach ($customvars as $name => $value) {
if ($blacklistPattern && preg_match($blacklistPattern, $name)) {
$this->customvars[$name] = '***';
} else {
$this->customvars[$name] = $value;
}
}
$this->customvars = $this->obfuscateCustomVars($customvars, $blacklistPattern);
return $this;
}
/**
* Obfuscate custom variables recursively
*
* @param stdClass|array $customvars The custom variables to obfuscate
* @param string $blacklistPattern Which custom variables to obfuscate
*
* @return stdClass|array The obfuscated custom variables
*/
protected function obfuscateCustomVars($customvars, $blacklistPattern)
{
$obfuscatedCustomVars = array();
foreach ($customvars as $name => $value) {
if ($blacklistPattern && preg_match($blacklistPattern, $name)) {
$obfuscatedCustomVars[$name] = '***';
} else {
$obfuscatedCustomVars[$name] = $value instanceof stdClass || is_array($value)
? $this->obfuscateCustomVars($value, $blacklistPattern)
: $value;
}
}
return $customvars instanceof stdClass ? (object) $obfuscatedCustomVars : $obfuscatedCustomVars;
}
/**
* Fetch the host custom variables related to this object
*

View File

@ -122,6 +122,7 @@ abstract class MonitoredObjectController extends Controller
protected function handleCommandForm(ObjectsCommandForm $form)
{
$form
->setBackend($this->backend)
->setObjects($this->object)
->setRedirectUrl(Url::fromPath($this->commandRedirectUrl)->setParams($this->params))
->handleRequest();

View File

@ -1,5 +1,5 @@
Module: monitoring
Version: 2.1.2
Version: 2.2.0
Description: Icinga monitoring module
This is the core module for most Icingaweb users. It provides an
abstraction layer for various Icinga data backends.

View File

@ -1,5 +1,26 @@
/*! Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
// Styles for the icon displayed if a check source is reachable
.check-source-reachable {
color: @color-ok;
}
// Styles for the icon displayed if a check source is not reachable
.check-source-not-reachable {
color: @color-critical;
}
// Styles for the icon displayed if a check result is late
.check-result-late {
color: @color-critical;
&:before {
// Remove right margin because the check now form may be displayed right next to the icon and we already have a gap
// because of inline-blocks
margin-right: 0;
}
}
// Show more and load more links in overviews
.action-links {
text-align: right;

View File

@ -2,6 +2,13 @@
@border-left-width: 6px;
// Icon images in list and detail views
.host-icon-image,
.service-icon-image {
max-width: 2em;
vertical-align: middle;
}
// Check source reachable information in the host and service detail views
.check-source-meta {
font-size: @font-size-small;
@ -77,6 +84,7 @@
font-family: @font-family-fixed;
font-size: @font-size-small;
margin: 0;
white-space: pre-wrap;
}
// Table for performance data in detail views
@ -201,16 +209,12 @@
border-spacing: 0 1px;
width: 100%;
tr[href] {
.transition(background 0.2s ease);
tr[href].active {
background-color: @tr-active-color;
}
&.active {
background-color: @tr-active-color;
}
&:hover {
background-color: @tr-hover-color;
cursor: pointer;
}
tr[href]:hover {
background-color: @tr-hover-color;
cursor: pointer;
}
}

View File

@ -1,5 +1,5 @@
Module: setup
Version: 2.1.2
Version: 2.2.0
Description: Setup module
Web based wizard for setting up Icinga Web 2 and its modules.
This includes the data backends (e.g. relational database, LDAP),

View File

@ -1,5 +1,5 @@
Module: test
Version: 2.1.2
Version: 2.2.0
Description: Translation module
This module allows developers to run (unit) tests against Icinga Web 2 and
any of its modules. Usually you do not need to enable this.

View File

@ -1,5 +1,5 @@
Module: translation
Version: 2.1.2
Version: 2.2.0
Description: Translation module
This module allows developers and translators to translate Icinga Web 2 and
its modules for multiple languages. You do not need this module to run an

View File

@ -163,10 +163,11 @@ td, th {
// Styles for when containers are loading. JS will remove this once the containers are ready
.impact {
.active > a, // Remove > a once .tabs layout has been fixed
.controls,
.content {
.transition(background-color 2s 1s linear !important);
background-color: @gray-lighter !important;
}
}
.impact > .controls, .impact li.active a {
.transition(background-color 2s 1s linear !important);
background-color: @gray-lighter !important;
}

View File

@ -127,6 +127,8 @@ label {
border: none;
padding: 0;
text-align: left;
&:hover {
text-decoration: underline;
}

View File

@ -97,15 +97,15 @@
& > .controls {
z-index: 3;
> * {
margin-left: @gutter !important;
margin-right: @gutter !important;
padding-left: @gutter;
padding-right: @gutter;
> .tabs {
// Remove gutter for tabs
margin-left: -1 * @gutter;
margin-right: -1 * @gutter;
}
}
// 1em gutter of containers is maintained by padding of content and margin of every element in controls. We're not
// setting padding to .container because else horizontally scrolled .content may overflow .controls when scrolled
// vertically
}
}

View File

@ -68,23 +68,6 @@ a:hover > .icon-cancel {
.button-link {
.action-link();
.button();
display: inline-block;
height: 35px;
line-height: 20px;
min-width: 175px;
&:hover {
text-decoration: none;
}
* {
line-height: inherit;
}
i {
font-size: 16px;
}
}
// List styles
@ -162,26 +145,21 @@ a:hover > .icon-cancel {
}
}
tr[href] {
.transition(background 0.2s ease);
tr[href].active {
background-color: @tr-active-color;
border-left-color: @icinga-blue;
}
&.active {
background-color: @tr-active-color;
border-left-color: @icinga-blue;
transition: none;
}
&:hover {
background-color: @tr-hover-color;
cursor: pointer;
}
tr[href]:hover {
background-color: @tr-hover-color;
cursor: pointer;
}
caption {
border-top: 1px solid @gray-light;
caption-side: bottom;
text-align: right;
font-style: italic;
text-align: right;
}
}

View File

@ -100,3 +100,11 @@
.dropdown-nav-item > ul > li:hover > a > .display-on-hover {
position: static;
}
.tabs > li > .close-container-control {
display: none;
}
#layout.twocols .tabs > li > .close-container-control {
display: block;
}

View File

@ -217,7 +217,7 @@
$ = undefined;
oldjQuery.getScript(
oldConfig.baseUrl + 'js/icinga.min.js'
oldConfig.baseUrl.replace(/\/$/, '') + '/js/icinga.min.js'
).done(function () {
var jQuery = window.jQuery;
window.icinga = new window.Icinga(oldConfig);

View File

@ -243,7 +243,6 @@
*/
Navigation.prototype.onPopState = function (url, data) {
// 1. get selection data and set active menu
console.log('popstate:', data);
if (data) {
var active = this.icinga.utils.getElementByDomPath(data);
if (!active) {

View File

@ -36,6 +36,12 @@
var self = event.data.self;
var icinga = self.icinga;
if (! icinga) {
// Attempt to catch a rare error, race condition, whatever
console.log('Got no icinga in applyHandlers');
return;
}
if (self.initializeModules) {
var loaded = false;
var moduleName = $target.data('icingaModule');
@ -89,12 +95,6 @@
if ($searchField.length && $searchField.val().length) {
self.searchValue = $searchField.val();
}
if (icinga.ui.isOneColLayout()) {
icinga.ui.disableCloseButtons();
} else {
icinga.ui.enableCloseButtons();
}
},
/**

View File

@ -681,11 +681,17 @@
req.addToHistory = false;
} else {
if (this.failureNotice === null) {
var now = new Date();
var padString = this.icinga.utils.padString;
this.failureNotice = this.createNotice(
'error',
'The connection to the Icinga web server was lost at ' +
this.icinga.utils.timeShort() +
'.',
'The connection to the Icinga web server was lost at '
+ now.getFullYear()
+ '-' + padString(now.getMonth() + 1, 0, 2)
+ '-' + padString(now.getDate(), 0, 2)
+ ' ' + padString(now.getHours(), 0, 2)
+ ':' + padString(now.getMinutes(), 0, 2)
+ '.',
true
);
@ -711,7 +717,7 @@
c += ' persist';
}
var $notice = $(
'<li class="' + c + '">' + message + '</li>'
'<li class="' + c + '">' + this.icinga.utils.escape(message) + '</li>'
).appendTo($('#notifications'));
this.icinga.ui.fixControls();
@ -737,7 +743,7 @@
if (forceFocus && forceFocus.length) {
activeElementPath = this.icinga.utils.getCSSPath($(forceFocus));
} else if (document.activeElement.id === 'search') {
} else if (document.activeElement && document.activeElement.id === 'search') {
activeElementPath = '#search';
} else if (document.activeElement
&& document.activeElement !== document.body

Some files were not shown because too many files have changed in this diff Show More