mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-31 01:34:09 +02:00
Merge branch 'master' into bugfix/Improve-tooltip-descriptions-8110
Conflicts: modules/monitoring/application/views/scripts/hosts/show.phtml
This commit is contained in:
commit
868295110a
@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
icingaweb2::config: /etc/icingaweb
|
icingaweb2::config: /etc/icingaweb2
|
||||||
icingaweb2::log: /var/log/icingaweb/icingaweb.log
|
icingaweb2::log: /var/log/icingaweb2/icingaweb2.log
|
||||||
icingaweb2::web_path: icingaweb
|
icingaweb2::web_path: icingaweb2
|
||||||
icingaweb2::db_user: icingaweb
|
icingaweb2::db_user: icingaweb2
|
||||||
icingaweb2::db_pass: icingaweb
|
icingaweb2::db_pass: icingaweb2
|
||||||
icingaweb2::db_name: icingaweb
|
icingaweb2::db_name: icingaweb2
|
||||||
|
icingaweb2::group: icingaweb2
|
||||||
|
@ -13,5 +13,5 @@ node default {
|
|||||||
source => 'puppet:////vagrant/.puppet/files/etc/profile.d/env.sh'
|
source => 'puppet:////vagrant/.puppet/files/etc/profile.d/env.sh'
|
||||||
}
|
}
|
||||||
@user { vagrant: ensure => present }
|
@user { vagrant: ensure => present }
|
||||||
User <| title == vagrant |> { groups +> icingaweb }
|
User <| title == vagrant |> { groups +> hiera('icingaweb2::group') }
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,8 @@ class icinga2_pgsql {
|
|||||||
password => 'icinga2',
|
password => 'icinga2',
|
||||||
schemafile => '/usr/share/icinga2-ido-pgsql/schema/pgsql.sql',
|
schemafile => '/usr/share/icinga2-ido-pgsql/schema/pgsql.sql',
|
||||||
}
|
}
|
||||||
-> icinga2::feature { 'ido-pgsql':
|
# Because Icinga 2 does not handle more than one IDO connection properly, The ido-pgsql will not be enabled by default.
|
||||||
source => 'puppet:///modules/icinga2_pgsql',
|
# -> icinga2::feature { 'ido-pgsql':
|
||||||
}
|
# source => 'puppet:///modules/icinga2_pgsql',
|
||||||
|
# }
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
class icingaweb2::config (
|
class icingaweb2::config (
|
||||||
$config = hiera('icingaweb2::config')
|
$config = hiera('icingaweb2::config'),
|
||||||
|
$web_group = hiera('icingaweb2::group')
|
||||||
) {
|
) {
|
||||||
group { 'icingaweb':
|
group { $web_group:
|
||||||
ensure => present,
|
ensure => present,
|
||||||
}
|
}
|
||||||
|
|
||||||
file { [ "${config}", "${config}/enabledModules", "${config}/modules", "${config}/preferences" ]:
|
file { [ "${config}", "${config}/enabledModules", "${config}/modules", "${config}/preferences" ]:
|
||||||
ensure => directory,
|
ensure => directory,
|
||||||
owner => 'root',
|
owner => 'root',
|
||||||
group => 'icingaweb',
|
group => $web_group,
|
||||||
mode => '2770',
|
mode => '2770',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
define icingaweb2::config::general (
|
define icingaweb2::config::general (
|
||||||
$source,
|
$source,
|
||||||
$config = hiera('icingaweb2::config'),
|
$config = hiera('icingaweb2::config'),
|
||||||
$replace = true
|
$web_group = hiera('icingaweb2::group'),
|
||||||
|
$replace = true
|
||||||
) {
|
) {
|
||||||
include icingaweb2::config
|
include icingaweb2::config
|
||||||
|
|
||||||
file { "${config}/${name}.ini":
|
file { "${config}/${name}.ini":
|
||||||
content => template("${source}/${name}.ini.erb"),
|
content => template("${source}/${name}.ini.erb"),
|
||||||
owner => 'root',
|
owner => 'root',
|
||||||
group => 'icingaweb',
|
group => $web_group,
|
||||||
mode => 0660,
|
mode => 0660,
|
||||||
replace => $replace,
|
replace => $replace,
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
define icingaweb2::config::module (
|
define icingaweb2::config::module (
|
||||||
$module,
|
$module,
|
||||||
$source,
|
$source,
|
||||||
$config = hiera('icingaweb2::config'),
|
$config = hiera('icingaweb2::config'),
|
||||||
$replace = true
|
$web_group = hiera('icingaweb2::group'),
|
||||||
|
$replace = true
|
||||||
) {
|
) {
|
||||||
include icingaweb2::config
|
include icingaweb2::config
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ define icingaweb2::config::module (
|
|||||||
file { "${config}/modules/${module}":
|
file { "${config}/modules/${module}":
|
||||||
ensure => directory,
|
ensure => directory,
|
||||||
owner => 'root',
|
owner => 'root',
|
||||||
group => 'icingaweb',
|
group => $web_group,
|
||||||
mode => '2770',
|
mode => '2770',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -18,7 +19,7 @@ define icingaweb2::config::module (
|
|||||||
file { "${config}/modules/${module}/${name}.ini":
|
file { "${config}/modules/${module}/${name}.ini":
|
||||||
source => "${source}/modules/${module}/${name}.ini",
|
source => "${source}/modules/${module}/${name}.ini",
|
||||||
owner => 'root',
|
owner => 'root',
|
||||||
group => 'icingaweb',
|
group => $web_group,
|
||||||
mode => 0660,
|
mode => 0660,
|
||||||
replace => $replace,
|
replace => $replace,
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,11 @@ local icinga icinga trust
|
|||||||
host icinga icinga 127.0.0.1/32 trust
|
host icinga icinga 127.0.0.1/32 trust
|
||||||
host icinga icinga ::1/128 trust
|
host icinga icinga ::1/128 trust
|
||||||
|
|
||||||
|
# icinga2
|
||||||
|
local icinga2 icinga2 trust
|
||||||
|
host icinga2 icinga2 127.0.0.1/32 trust
|
||||||
|
host icinga2 icinga2 ::1/128 trust
|
||||||
|
|
||||||
# icinga_unittest
|
# icinga_unittest
|
||||||
local icinga_unittest icinga_unittest trust
|
local icinga_unittest icinga_unittest trust
|
||||||
host icinga_unittest icinga_unittest 127.0.0.1/32 trust
|
host icinga_unittest icinga_unittest 127.0.0.1/32 trust
|
||||||
@ -81,6 +86,11 @@ local icingaweb icingaweb trust
|
|||||||
host icingaweb icingaweb 127.0.0.1/32 trust
|
host icingaweb icingaweb 127.0.0.1/32 trust
|
||||||
host icingaweb icingaweb ::1/128 trust
|
host icingaweb icingaweb ::1/128 trust
|
||||||
|
|
||||||
|
# icingaweb2
|
||||||
|
local <%= scope.function_hiera(['icingaweb2::db_user']) %> <%= scope.function_hiera(['icingaweb2::db_user']) %> trust
|
||||||
|
host <%= scope.function_hiera(['icingaweb2::db_user']) %> <%= scope.function_hiera(['icingaweb2::db_user']) %> 127.0.0.1/32 trust
|
||||||
|
host <%= scope.function_hiera(['icingaweb2::db_user']) %> <%= scope.function_hiera(['icingaweb2::db_user']) %> ::1/128 trust
|
||||||
|
|
||||||
# "local" is for Unix domain socket connections only
|
# "local" is for Unix domain socket connections only
|
||||||
local all all ident
|
local all all ident
|
||||||
# IPv4 local connections:
|
# IPv4 local connections:
|
||||||
|
29
.puppet/modules/php_imagick/manifests/init.pp
Normal file
29
.puppet/modules/php_imagick/manifests/init.pp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Class: php_imagick
|
||||||
|
#
|
||||||
|
# This class installs the ImageMagick PHP module.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
#
|
||||||
|
# Actions:
|
||||||
|
#
|
||||||
|
# Requires:
|
||||||
|
#
|
||||||
|
# php
|
||||||
|
#
|
||||||
|
# Sample Usage:
|
||||||
|
#
|
||||||
|
# include php_imagick
|
||||||
|
#
|
||||||
|
class php_imagick {
|
||||||
|
include php
|
||||||
|
|
||||||
|
$php_imagick = $::operatingsystem ? {
|
||||||
|
/(Debian|Ubuntu)/ => 'php5-imagick',
|
||||||
|
/(RedHat|CentOS|Fedora)/ => 'php-pecl-imagick',
|
||||||
|
/(SLES|OpenSuSE)/ => 'php5-imagick',
|
||||||
|
}
|
||||||
|
|
||||||
|
package { $php_imagick:
|
||||||
|
ensure => latest,
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,15 @@
|
|||||||
class icingaweb2_dev (
|
class icingaweb2_dev (
|
||||||
$config = hiera('icingaweb2::config'),
|
$config = hiera('icingaweb2::config'),
|
||||||
$log = hiera('icingaweb2::log'),
|
$log = hiera('icingaweb2::log'),
|
||||||
$web_path = hiera('icingaweb2::web_path'),
|
$web_path = hiera('icingaweb2::web_path'),
|
||||||
$db_user = hiera('icingaweb2::db_user'),
|
$db_user = hiera('icingaweb2::db_user'),
|
||||||
$db_pass = hiera('icingaweb2::db_pass'),
|
$db_pass = hiera('icingaweb2::db_pass'),
|
||||||
$db_name = hiera('icingaweb2::db_name'),
|
$db_name = hiera('icingaweb2::db_name'),
|
||||||
|
$web_group = hiera('icingaweb2::group'),
|
||||||
) {
|
) {
|
||||||
include apache
|
include apache
|
||||||
include php
|
include php
|
||||||
|
include php_imagick
|
||||||
include icingaweb2::config
|
include icingaweb2::config
|
||||||
include icingacli
|
include icingacli
|
||||||
include icinga_packages
|
include icinga_packages
|
||||||
@ -19,7 +21,7 @@ class icingaweb2_dev (
|
|||||||
}
|
}
|
||||||
|
|
||||||
# TODO(el): icinga-gui is not a icingaweb2_dev package
|
# TODO(el): icinga-gui is not a icingaweb2_dev package
|
||||||
package { [ 'php-pdo', 'php-ldap', 'php-phpunit-PHPUnit', 'icinga-gui' ]:
|
package { [ 'php-gd', 'php-intl', 'php-pdo', 'php-ldap', 'php-phpunit-PHPUnit', 'icinga-gui' ]:
|
||||||
ensure => latest,
|
ensure => latest,
|
||||||
notify => Service['apache'],
|
notify => Service['apache'],
|
||||||
require => Class['icinga_packages'],
|
require => Class['icinga_packages'],
|
||||||
@ -28,7 +30,7 @@ class icingaweb2_dev (
|
|||||||
Exec { path => '/usr/local/bin:/usr/bin:/bin' }
|
Exec { path => '/usr/local/bin:/usr/bin:/bin' }
|
||||||
|
|
||||||
# TODO(el): Enabling/disabling modules should be a resource
|
# TODO(el): Enabling/disabling modules should be a resource
|
||||||
User <| alias == apache |> { groups +> 'icingaweb' }
|
User <| alias == apache |> { groups +> $web_group }
|
||||||
-> exec { 'enable-monitoring-module':
|
-> exec { 'enable-monitoring-module':
|
||||||
command => 'icingacli module enable monitoring',
|
command => 'icingacli module enable monitoring',
|
||||||
user => 'apache',
|
user => 'apache',
|
||||||
@ -50,7 +52,7 @@ class icingaweb2_dev (
|
|||||||
file { $log_dir:
|
file { $log_dir:
|
||||||
ensure => directory,
|
ensure => directory,
|
||||||
owner => 'root',
|
owner => 'root',
|
||||||
group => 'icingaweb',
|
group => $web_group,
|
||||||
mode => '2775'
|
mode => '2775'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[autologin]
|
[autologin]
|
||||||
backend = autologin
|
backend = external
|
||||||
|
|
||||||
[icingaweb-mysql]
|
[icingaweb-mysql]
|
||||||
backend = db
|
backend = db
|
||||||
|
263
README.md
263
README.md
@ -2,267 +2,26 @@
|
|||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
0. [General Information](#general information)
|
0. [About](#about)
|
||||||
1. [Installation](#installation)
|
1. [Installation](#installation)
|
||||||
2. [Support](#support)
|
2. [Support](#support)
|
||||||
3. [Vagrant - Virtual development environment](#vagrant)
|
|
||||||
|
|
||||||
## General Information
|
## About
|
||||||
|
|
||||||
`Icinga Web 2` is the next generation monitoring web interface, framework
|
**Icinga Web 2** is the next generation open source monitoring web interface, framework
|
||||||
and CLI tool developed by the [Icinga Project](https://www.icinga.org/community/team/).
|
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.
|
||||||
|
|
||||||
Responsive and fast, rewritten from scratch supporting multiple backends and
|

|
||||||
providing a CLI tool. Compatible with Icinga Core 2.x and 1.x.
|
|
||||||
|
|
||||||
Check the Icinga website for some [insights](https://www.icinga.org/icinga/screenshots/icinga-web-2/).
|
|
||||||
|
|
||||||
> **Note**
|
|
||||||
>
|
|
||||||
> `Icinga Web 2` is still in development and not meant for production deployment.
|
|
||||||
> Watch the [development roadmap](https://dev.icinga.org/projects/icingaweb2/roadmap)
|
|
||||||
> and [Icinga website](https://www.icinga.org/) for release schedule updates!
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Please navigate to [doc/installation.md](doc/installation.md) for updated details.
|
For installing Icinga Web 2 please read [doc/installation.md](doc/installation.md).
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
Please head over to the [community support channels](https://www.icinga.org/icinga/faq/get-help/)
|
If you come across problems at some time, the [community support channels](https://support.icinga.org/)
|
||||||
in case of questions, bugs, etc.
|
are good places to ask for advice from other users and give some in return.
|
||||||
|
|
||||||
Please make sure to provide the following details:
|
|
||||||
|
|
||||||
* OS, distribution, version
|
|
||||||
* PHP and/or MySQL/PostgreSQL version
|
|
||||||
* Which browser and its version
|
|
||||||
* Screenshot and problem description
|
|
||||||
|
|
||||||
|
|
||||||
## Vagrant
|
|
||||||
|
|
||||||
### Requirements
|
|
||||||
|
|
||||||
* Vagrant 1.2+
|
|
||||||
* Virtualbox 4.2.16+
|
|
||||||
* a fairly powerful hardware (quad core, 4gb ram, fast hdd)
|
|
||||||
|
|
||||||
> **Note**
|
|
||||||
>
|
|
||||||
> The deployment of the virtual machine is tested against Vagrant starting with version 1.2.
|
|
||||||
> Unfortunately older versions will not work.
|
|
||||||
|
|
||||||
### General
|
|
||||||
|
|
||||||
The Icinga Web 2 project ships with a Vagrant virtual machine that integrates
|
|
||||||
the source code with various services and example data in a controlled
|
|
||||||
environment. This enables developers and users to test Livestatus, status.dat,
|
|
||||||
MySQL and PostgreSQL backends as well as the LDAP authentication. All you
|
|
||||||
have to do is install Vagrant and run:
|
|
||||||
|
|
||||||
vagrant up
|
|
||||||
|
|
||||||
> **Note**
|
|
||||||
>
|
|
||||||
> The first boot of the vm takes a fairly long time because
|
|
||||||
> you'll download a plain CentOS base box and Vagrant will automatically
|
|
||||||
> provision the environment on the first go.
|
|
||||||
|
|
||||||
After you should be able to browse [localhost:8080/icingaweb](http://localhost:8080/icingaweb).
|
|
||||||
|
|
||||||
### Environment
|
|
||||||
|
|
||||||
**Forwarded ports**:
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Proctocol</th>
|
|
||||||
<th>Local port (virtual machine host)</th>
|
|
||||||
<th>Remote port (the virtual machine)</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>SSH</td>
|
|
||||||
<td>2222</td>
|
|
||||||
<td>22</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>HTTP</td>
|
|
||||||
<td>8080</td>
|
|
||||||
<td>80</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
**Installed packages**:
|
|
||||||
|
|
||||||
* Apache2 with PHP enabled
|
|
||||||
* PHP with MySQL and PostgreSQL libraries
|
|
||||||
* MySQL server and client software
|
|
||||||
* PostgreSQL server and client software
|
|
||||||
* [Icinga prerequisites](http://docs.icinga.org/latest/en/quickstart-idoutils.html#installpackages)
|
|
||||||
* OpenLDAP servers and clients
|
|
||||||
|
|
||||||
**Installed users and groups**:
|
|
||||||
|
|
||||||
* User icinga with group icinga and icinga-cmd
|
|
||||||
* Webserver user added to group icinga-cmd
|
|
||||||
|
|
||||||
**Installed software**:
|
|
||||||
|
|
||||||
* Icinga with IDOUtils using a MySQL database
|
|
||||||
* Icinga with IDOUtils using a PostgreSQL database
|
|
||||||
* Icinga 2
|
|
||||||
|
|
||||||
**Installed files**:
|
|
||||||
|
|
||||||
* `/usr/share/icinga/htpasswd.users` account information for logging into the Icinga classic web interface for both icinga instances
|
|
||||||
* `/usr/lib64/nagios/plugins` Monitoring Plugins for all Icinga instances
|
|
||||||
|
|
||||||
#### Icinga with IDOUtils using a MySQL database
|
|
||||||
|
|
||||||
**Installation path**: `/usr/local/icinga-mysql`
|
|
||||||
|
|
||||||
**Services**:
|
|
||||||
|
|
||||||
* `icinga-mysql`
|
|
||||||
* `ido2db-mysql`
|
|
||||||
|
|
||||||
Connect to the **icinga mysql database** using the following command:
|
|
||||||
|
|
||||||
mysql -u icinga -p icinga icinga
|
|
||||||
|
|
||||||
Access the **Classic UI** (CGIs) via [localhost:8080/icinga-mysql](http://localhost:8080/icinga-mysql).
|
|
||||||
For **logging into** the Icinga classic web interface use user *icingaadmin* with password *icinga*.
|
|
||||||
|
|
||||||
#### Icinga with IDOUtils using a PostgreSQL database
|
|
||||||
|
|
||||||
**Installation path**: `/usr/local/icinga-pgsql`
|
|
||||||
|
|
||||||
**Services**:
|
|
||||||
|
|
||||||
* `icinga-pgsql`
|
|
||||||
* `ido2db-pgsql`
|
|
||||||
|
|
||||||
Connect to the **icinga mysql database** using the following command:
|
|
||||||
|
|
||||||
sudo -u postgres psql -U icinga -d icinga
|
|
||||||
|
|
||||||
Access the **Classic UI** (CGIs) via [localhost:8080/icinga-pgsql](http://localhost:8080/icinga-pgsql).
|
|
||||||
For **logging into** the Icinga classic web interface use user *icingaadmin* with password *icinga*.
|
|
||||||
|
|
||||||
#### Monitoring Test Config
|
|
||||||
|
|
||||||
Test config is added to both the MySQL and PostgreSQL Icinga instance utilizing the Perl module
|
|
||||||
**Monitoring::Generator::TestConfig** to generate test config to **/usr/local/share/misc/monitoring_test_config**
|
|
||||||
which is then copied to **<instance>/etc/conf.d/test_config/**.
|
|
||||||
Configuration can be adjusted and recreated with **/usr/local/share/misc/monitoring_test_config/recreate.pl**.
|
|
||||||
**Note** that you have to run
|
|
||||||
|
|
||||||
vagrant provision
|
|
||||||
|
|
||||||
in the host after any modification to the script just mentioned.
|
|
||||||
|
|
||||||
#### MK Livestatus
|
|
||||||
|
|
||||||
MK Livestatus is added to the Icinga installation using a MySQL database.
|
|
||||||
|
|
||||||
**Installation path**:
|
|
||||||
|
|
||||||
* `/usr/local/icinga-mysql/bin/unixcat`
|
|
||||||
* `/usr/local/icinga-mysql/lib/mk-livestatus/livecheck`
|
|
||||||
* `/usr/local/icinga-mysql/lib/mk-livestatus/livestatus.o`
|
|
||||||
* `/usr/local/icinga-mysql/etc/modules/mk-livestatus.cfg`
|
|
||||||
* `/usr/local/icinga-mysql/var/rw/live`
|
|
||||||
|
|
||||||
**Example usage**:
|
|
||||||
|
|
||||||
echo "GET hosts" | /usr/local/icinga-mysql/bin/unixcat /usr/local/icinga-mysql/var/rw/live
|
|
||||||
|
|
||||||
#### LDAP example data
|
|
||||||
|
|
||||||
The environment includes a openldap server with example data. *Domain* suffix is **dc=icinga,dc=org**.
|
|
||||||
Administrator (*rootDN*) of the slapd configuration database is **cn=admin,cn=config** and the
|
|
||||||
administrator (*rootDN*) of our database instance is **cn=admin,dc=icinga,dc=org**. Both share
|
|
||||||
the *password* `admin`.
|
|
||||||
|
|
||||||
Examples to query the slapd configuration database:
|
|
||||||
|
|
||||||
ldapsearch -x -W -LLL -D cn=admin,cn=config -b cn=config dn
|
|
||||||
ldapsearch -Y EXTERNAL -H ldapi:/// -LLL -b cn=config dn
|
|
||||||
|
|
||||||
Examples to query our database instance:
|
|
||||||
|
|
||||||
ldapsearch -x -W -LLL -D cn=admin,dc=icinga,dc=org -b dc=icinga,dc=org dn
|
|
||||||
ldapsearch -Y EXTERNAL -H ldapi:/// -LLL -b dc=icinga,dc=org dn
|
|
||||||
|
|
||||||
This is what the **dc=icinga,dc=org** *DIT* looks like:
|
|
||||||
|
|
||||||
> dn: dc=icinga,dc=org
|
|
||||||
>
|
|
||||||
> dn: ou=people,dc=icinga,dc=org
|
|
||||||
>
|
|
||||||
> dn: ou=groups,dc=icinga,dc=org
|
|
||||||
>
|
|
||||||
> dn: cn=Users,ou=groups,dc=icinga,dc=org
|
|
||||||
> cn: Users
|
|
||||||
> uniqueMember: cn=Jon Doe,ou=people,dc=icinga,dc=org
|
|
||||||
> uniqueMember: cn=Jane Smith,ou=people,dc=icinga,dc=org
|
|
||||||
> uniqueMember: cn=John Q. Public,ou=people,dc=icinga,dc=org
|
|
||||||
> uniqueMember: cn=Richard Roe,ou=people,dc=icinga,dc=org
|
|
||||||
>
|
|
||||||
> dn: cn=John Doe,ou=people,dc=icinga,dc=org
|
|
||||||
> cn: John Doe
|
|
||||||
> uid: jdoe
|
|
||||||
>
|
|
||||||
> dn: cn=Jane Smith,ou=people,dc=icinga,dc=org
|
|
||||||
> cn: Jane Smith
|
|
||||||
> uid: jsmith
|
|
||||||
>
|
|
||||||
> dn: cn=John Q. Public,ou=people,dc=icinga,dc=org
|
|
||||||
> cn: John Q. Public
|
|
||||||
> uid: jqpublic
|
|
||||||
>
|
|
||||||
> dn: cn=Richard Roe,ou=people,dc=icinga,dc=org
|
|
||||||
> cn: Richard Roe
|
|
||||||
> uid: rroe
|
|
||||||
|
|
||||||
All users share the password `password`.
|
|
||||||
|
|
||||||
#### Testing the code
|
|
||||||
|
|
||||||
All software required to run tests is installed in the virtual machine.
|
|
||||||
In order to run all tests you have to execute the following commands:
|
|
||||||
|
|
||||||
vagrant ssh -c /vagrant/test/php/runtests
|
|
||||||
vagrant ssh -c /vagrant/test/php/checkswag
|
|
||||||
vagrant ssh -c /vagrant/test/js/runtests
|
|
||||||
vagrant ssh -c /vagrant/test/js/checkswag
|
|
||||||
vagrant ssh -c /vagrant/test/frontend/runtests
|
|
||||||
|
|
||||||
`runtests` will execute unit and regression tests and `checkswag` will report
|
|
||||||
code style issues.
|
|
||||||
|
|
||||||
#### Icinga 2
|
|
||||||
|
|
||||||
Installed from the Icinga [snapshot package repository](http://packages.icinga.org/epel/).
|
|
||||||
The configuration is located in `/etc/icinga2`.
|
|
||||||
|
|
||||||
**Example usage**:
|
|
||||||
|
|
||||||
/etc/init.d/icinga2 (start|stop|restart|reload)
|
|
||||||
|
|
||||||
|
|
||||||
## Log into Icinga Web 2
|
|
||||||
|
|
||||||
If you've configure LDAP as authentication backend (which is the default) use the following login credentials:
|
|
||||||
|
|
||||||
> **Username**: jdoe
|
|
||||||
> **Password**: password
|
|
||||||
|
|
||||||
Have a look at [LDAP example data](#ldap example data) for more accounts.
|
|
||||||
|
|
||||||
Using MySQL as backend:
|
|
||||||
|
|
||||||
> **Username**: icingaadmin
|
|
||||||
> **Password**: icinga
|
|
||||||
|
|
||||||
|
For status updates check the [Icinga website](https://www.icinga.org/) and the
|
||||||
|
[Icinga Web 2 development roadmap](https://dev.icinga.org/projects/icingaweb2/roadmap).
|
||||||
|
1
Vagrantfile
vendored
1
Vagrantfile
vendored
@ -4,7 +4,6 @@
|
|||||||
VAGRANTFILE_API_VERSION = "2"
|
VAGRANTFILE_API_VERSION = "2"
|
||||||
VAGRANT_REQUIRED_VERSION = "1.5.0"
|
VAGRANT_REQUIRED_VERSION = "1.5.0"
|
||||||
|
|
||||||
# Require 1.2.x at least
|
|
||||||
if ! defined? Vagrant.require_version
|
if ! defined? Vagrant.require_version
|
||||||
if Gem::Version.new(Vagrant::VERSION) < Gem::Version.new(VAGRANT_REQUIRED_VERSION)
|
if Gem::Version.new(Vagrant::VERSION) < Gem::Version.new(VAGRANT_REQUIRED_VERSION)
|
||||||
puts "Vagrant >= " + VAGRANT_REQUIRED_VERSION + " required. Your version is " + Vagrant::VERSION
|
puts "Vagrant >= " + VAGRANT_REQUIRED_VERSION + " required. Your version is " + Vagrant::VERSION
|
||||||
|
@ -4,16 +4,17 @@
|
|||||||
|
|
||||||
# namespace Icinga\Application\Controllers;
|
# namespace Icinga\Application\Controllers;
|
||||||
|
|
||||||
use Icinga\Authentication\Backend\AutoLoginBackend;
|
|
||||||
use Icinga\Web\Controller\ActionController;
|
|
||||||
use Icinga\Forms\Authentication\LoginForm;
|
|
||||||
use Icinga\Authentication\AuthChain;
|
|
||||||
use Icinga\Application\Config;
|
use Icinga\Application\Config;
|
||||||
|
use Icinga\Application\Icinga;
|
||||||
use Icinga\Application\Logger;
|
use Icinga\Application\Logger;
|
||||||
|
use Icinga\Authentication\AuthChain;
|
||||||
|
use Icinga\Authentication\Backend\ExternalBackend;
|
||||||
use Icinga\Exception\AuthenticationException;
|
use Icinga\Exception\AuthenticationException;
|
||||||
use Icinga\Exception\NotReadableError;
|
|
||||||
use Icinga\Exception\ConfigurationError;
|
use Icinga\Exception\ConfigurationError;
|
||||||
|
use Icinga\Exception\NotReadableError;
|
||||||
|
use Icinga\Forms\Authentication\LoginForm;
|
||||||
use Icinga\User;
|
use Icinga\User;
|
||||||
|
use Icinga\Web\Controller\ActionController;
|
||||||
use Icinga\Web\Url;
|
use Icinga\Web\Url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,10 +34,12 @@ class AuthenticationController extends ActionController
|
|||||||
*/
|
*/
|
||||||
public function loginAction()
|
public function loginAction()
|
||||||
{
|
{
|
||||||
if (@file_exists(Config::resolvePath('setup.token')) && !@file_exists(Config::resolvePath('config.ini'))) {
|
$icinga = Icinga::app();
|
||||||
|
if ($icinga->setupTokenExists() && $icinga->requiresSetup()) {
|
||||||
$this->redirectNow(Url::fromPath('setup'));
|
$this->redirectNow(Url::fromPath('setup'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$triedOnlyExternalAuth = null;
|
||||||
$auth = $this->Auth();
|
$auth = $this->Auth();
|
||||||
$this->view->form = $form = new LoginForm();
|
$this->view->form = $form = new LoginForm();
|
||||||
$this->view->title = $this->translate('Icingaweb Login');
|
$this->view->title = $this->translate('Icingaweb Login');
|
||||||
@ -80,7 +83,7 @@ class AuthenticationController extends ActionController
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach ($chain as $backend) {
|
foreach ($chain as $backend) {
|
||||||
if ($backend instanceof AutoLoginBackend) {
|
if ($backend instanceof ExternalBackend) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
++$backendsTried;
|
++$backendsTried;
|
||||||
@ -124,7 +127,8 @@ class AuthenticationController extends ActionController
|
|||||||
} elseif ($request->isGet()) {
|
} elseif ($request->isGet()) {
|
||||||
$user = new User('');
|
$user = new User('');
|
||||||
foreach ($chain as $backend) {
|
foreach ($chain as $backend) {
|
||||||
if ($backend instanceof AutoLoginBackend) {
|
$triedOnlyExternalAuth = $triedOnlyExternalAuth === null;
|
||||||
|
if ($backend instanceof ExternalBackend) {
|
||||||
$authenticated = $backend->authenticate($user);
|
$authenticated = $backend->authenticate($user);
|
||||||
if ($authenticated === true) {
|
if ($authenticated === true) {
|
||||||
$auth->setAuthenticated($user);
|
$auth->setAuthenticated($user);
|
||||||
@ -132,6 +136,8 @@ class AuthenticationController extends ActionController
|
|||||||
Url::fromPath(Url::fromRequest()->getParam('redirect', 'dashboard'))
|
Url::fromPath(Url::fromRequest()->getParam('redirect', 'dashboard'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$triedOnlyExternalAuth = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,7 +145,8 @@ class AuthenticationController extends ActionController
|
|||||||
$this->view->errorInfo = $e->getMessage();
|
$this->view->errorInfo = $e->getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->view->configMissing = is_dir(Config::$configDir) === false;
|
$this->view->requiresExternalAuth = $triedOnlyExternalAuth && !$auth->isAuthenticated();
|
||||||
|
$this->view->requiresSetup = Icinga::app()->requiresSetup();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7,7 +7,6 @@ use Icinga\Web\Url;
|
|||||||
use Icinga\Web\Widget\Tab;
|
use Icinga\Web\Widget\Tab;
|
||||||
use Icinga\Application\Config;
|
use Icinga\Application\Config;
|
||||||
use Icinga\Forms\PreferenceForm;
|
use Icinga\Forms\PreferenceForm;
|
||||||
use Icinga\Exception\ConfigurationError;
|
|
||||||
use Icinga\User\Preferences\PreferencesStore;
|
use Icinga\User\Preferences\PreferencesStore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,14 +39,13 @@ class PreferenceController extends BasePreferenceController
|
|||||||
public function indexAction()
|
public function indexAction()
|
||||||
{
|
{
|
||||||
$storeConfig = Config::app()->getSection('preferences');
|
$storeConfig = Config::app()->getSection('preferences');
|
||||||
if ($storeConfig->isEmpty()) {
|
|
||||||
throw new ConfigurationError(t('You need to configure how to store preferences first.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$user = $this->getRequest()->getUser();
|
$user = $this->getRequest()->getUser();
|
||||||
$form = new PreferenceForm();
|
$form = new PreferenceForm();
|
||||||
$form->setPreferences($user->getPreferences());
|
$form->setPreferences($user->getPreferences());
|
||||||
$form->setStore(PreferencesStore::create($storeConfig, $user));
|
if ($storeConfig->get('store', 'ini') !== 'none') {
|
||||||
|
$form->setStore(PreferencesStore::create($storeConfig, $user));
|
||||||
|
}
|
||||||
$form->handleRequest();
|
$form->handleRequest();
|
||||||
|
|
||||||
$this->view->form = $form;
|
$this->view->form = $form;
|
||||||
|
9
application/fonts/icingaweb.md
Normal file
9
application/fonts/icingaweb.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# fontello-ifont font files moved
|
||||||
|
|
||||||
|
New target is: public/font
|
||||||
|
|
||||||
|
The font directory has been moved to the public structure because of
|
||||||
|
Internet Explorer version 8 compatibility. The common way for browsers is to
|
||||||
|
include the binary embeded font type in the javascript. IE8 falls back and
|
||||||
|
include one of the provided font sources. Therefore it is important to have
|
||||||
|
the font files available public and exported by the HTTP server.
|
@ -18,7 +18,7 @@ class LoginForm extends Form
|
|||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
$this->setName('form_login');
|
$this->setName('form_login');
|
||||||
$this->setSubmitLabel(t('Login'));
|
$this->setSubmitLabel($this->translate('Login'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,8 +31,8 @@ class LoginForm extends Form
|
|||||||
'username',
|
'username',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Username'),
|
'label' => $this->translate('Username'),
|
||||||
'placeholder' => t('Please enter your username...'),
|
'placeholder' => $this->translate('Please enter your username...'),
|
||||||
'class' => false === isset($formData['username']) ? 'autofocus' : ''
|
'class' => false === isset($formData['username']) ? 'autofocus' : ''
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -41,8 +41,8 @@ class LoginForm extends Form
|
|||||||
'password',
|
'password',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Password'),
|
'label' => $this->translate('Password'),
|
||||||
'placeholder' => t('...and your password'),
|
'placeholder' => $this->translate('...and your password'),
|
||||||
'class' => isset($formData['username']) ? 'autofocus' : ''
|
'class' => isset($formData['username']) ? 'autofocus' : ''
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -53,8 +53,8 @@ class DbBackendForm extends Form
|
|||||||
'name',
|
'name',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Backend Name'),
|
'label' => $this->translate('Backend Name'),
|
||||||
'description' => t(
|
'description' => $this->translate(
|
||||||
'The name of this authentication provider that is used to differentiate it from others'
|
'The name of this authentication provider that is used to differentiate it from others'
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -64,8 +64,10 @@ class DbBackendForm extends Form
|
|||||||
'resource',
|
'resource',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Database Connection'),
|
'label' => $this->translate('Database Connection'),
|
||||||
'description' => t('The database connection to use for authenticating with this provider'),
|
'description' => $this->translate(
|
||||||
|
'The database connection to use for authenticating with this provider'
|
||||||
|
),
|
||||||
'multiOptions' => false === empty($this->resources)
|
'multiOptions' => false === empty($this->resources)
|
||||||
? array_combine($this->resources, $this->resources)
|
? array_combine($this->resources, $this->resources)
|
||||||
: array()
|
: array()
|
||||||
@ -107,11 +109,11 @@ class DbBackendForm extends Form
|
|||||||
try {
|
try {
|
||||||
$dbUserBackend = new DbUserBackend(ResourceFactory::createResource($form->getResourceConfig()));
|
$dbUserBackend = new DbUserBackend(ResourceFactory::createResource($form->getResourceConfig()));
|
||||||
if ($dbUserBackend->count() < 1) {
|
if ($dbUserBackend->count() < 1) {
|
||||||
$form->addError(t('No users found under the specified database backend'));
|
$form->addError($form->translate('No users found under the specified database backend'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$form->addError(sprintf(t('Using the specified backend failed: %s'), $e->getMessage()));
|
$form->addError(sprintf($form->translate('Using the specified backend failed: %s'), $e->getMessage()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,16 +8,16 @@ use Zend_Validate_Callback;
|
|||||||
use Icinga\Web\Form;
|
use Icinga\Web\Form;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Form class for adding/modifying autologin authentication backends
|
* Form class for adding/modifying authentication backends of type "external"
|
||||||
*/
|
*/
|
||||||
class AutologinBackendForm extends Form
|
class ExternalBackendForm extends Form
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Initialize this form
|
* Initialize this form
|
||||||
*/
|
*/
|
||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
$this->setName('form_config_authbackend_autologin');
|
$this->setName('form_config_authbackend_external');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,8 +30,8 @@ class AutologinBackendForm extends Form
|
|||||||
'name',
|
'name',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Backend Name'),
|
'label' => $this->translate('Backend Name'),
|
||||||
'description' => t(
|
'description' => $this->translate(
|
||||||
'The name of this authentication provider that is used to differentiate it from others'
|
'The name of this authentication provider that is used to differentiate it from others'
|
||||||
),
|
),
|
||||||
'validators' => array(
|
'validators' => array(
|
||||||
@ -52,9 +52,11 @@ class AutologinBackendForm extends Form
|
|||||||
'text',
|
'text',
|
||||||
'strip_username_regexp',
|
'strip_username_regexp',
|
||||||
array(
|
array(
|
||||||
'label' => t('Filter Pattern'),
|
'label' => $this->translate('Filter Pattern'),
|
||||||
'description' => t('The regular expression to use to strip specific parts off from usernames. Leave empty if you do not want to strip off anything'),
|
'description' => $this->translate(
|
||||||
'value' => '/\@[^$]+$/',
|
'The regular expression to use to strip specific parts off from usernames.'
|
||||||
|
. ' Leave empty if you do not want to strip off anything'
|
||||||
|
),
|
||||||
'validators' => array(
|
'validators' => array(
|
||||||
new Zend_Validate_Callback(function ($value) {
|
new Zend_Validate_Callback(function ($value) {
|
||||||
return @preg_match($value, '') !== false;
|
return @preg_match($value, '') !== false;
|
||||||
@ -67,7 +69,7 @@ class AutologinBackendForm extends Form
|
|||||||
'backend',
|
'backend',
|
||||||
array(
|
array(
|
||||||
'disabled' => true,
|
'disabled' => true,
|
||||||
'value' => 'autologin'
|
'value' => 'external'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -77,7 +79,7 @@ class AutologinBackendForm extends Form
|
|||||||
/**
|
/**
|
||||||
* Validate the configuration by creating a backend and requesting the user count
|
* Validate the configuration by creating a backend and requesting the user count
|
||||||
*
|
*
|
||||||
* Returns always true as autologin backends are just "passive" backends. (The webserver authenticates users.)
|
* Returns always true as backends of type "external" are just "passive" backends.
|
||||||
*
|
*
|
||||||
* @param Form $form The form to fetch the configuration values from
|
* @param Form $form The form to fetch the configuration values from
|
||||||
*
|
*
|
@ -54,8 +54,8 @@ class LdapBackendForm extends Form
|
|||||||
'name',
|
'name',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Backend Name'),
|
'label' => $this->translate('Backend Name'),
|
||||||
'description' => t(
|
'description' => $this->translate(
|
||||||
'The name of this authentication provider that is used to differentiate it from others'
|
'The name of this authentication provider that is used to differentiate it from others'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -65,8 +65,8 @@ class LdapBackendForm extends Form
|
|||||||
'resource',
|
'resource',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('LDAP Resource'),
|
'label' => $this->translate('LDAP Resource'),
|
||||||
'description' => t('The resource to use for authenticating with this provider'),
|
'description' => $this->translate('The resource to use for authenticating with this provider'),
|
||||||
'multiOptions' => false === empty($this->resources)
|
'multiOptions' => false === empty($this->resources)
|
||||||
? array_combine($this->resources, $this->resources)
|
? array_combine($this->resources, $this->resources)
|
||||||
: array()
|
: array()
|
||||||
@ -77,8 +77,8 @@ class LdapBackendForm extends Form
|
|||||||
'user_class',
|
'user_class',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('LDAP User Object Class'),
|
'label' => $this->translate('LDAP User Object Class'),
|
||||||
'description' => t('The object class used for storing users on the ldap server'),
|
'description' => $this->translate('The object class used for storing users on the ldap server'),
|
||||||
'value' => 'inetOrgPerson'
|
'value' => 'inetOrgPerson'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -87,8 +87,10 @@ class LdapBackendForm extends Form
|
|||||||
'user_name_attribute',
|
'user_name_attribute',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('LDAP User Name Attribute'),
|
'label' => $this->translate('LDAP User Name Attribute'),
|
||||||
'description' => t('The attribute name used for storing the user name on the ldap server'),
|
'description' => $this->translate(
|
||||||
|
'The attribute name used for storing the user name on the ldap server'
|
||||||
|
),
|
||||||
'value' => 'uid'
|
'value' => 'uid'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -105,9 +107,11 @@ class LdapBackendForm extends Form
|
|||||||
'base_dn',
|
'base_dn',
|
||||||
array(
|
array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'label' => t('Base DN'),
|
'label' => $this->translate('Base DN'),
|
||||||
'description' => t('The path where users can be found on the ldap server. ' .
|
'description' => $this->translate(
|
||||||
' Leave empty to select all users available on the specified resource.')
|
'The path where users can be found on the ldap server. Leave ' .
|
||||||
|
'empty to select all users available on the specified resource.'
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return $this;
|
return $this;
|
||||||
@ -146,7 +150,7 @@ class LdapBackendForm extends Form
|
|||||||
$form->addError($e->getMessage());
|
$form->addError($e->getMessage());
|
||||||
return false;
|
return false;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$form->addError(sprintf(t('Unable to validate authentication: %s'), $e->getMessage()));
|
$form->addError(sprintf($form->translate('Unable to validate authentication: %s'), $e->getMessage()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ use Icinga\Data\ResourceFactory;
|
|||||||
use Icinga\Exception\ConfigurationError;
|
use Icinga\Exception\ConfigurationError;
|
||||||
use Icinga\Forms\Config\Authentication\DbBackendForm;
|
use Icinga\Forms\Config\Authentication\DbBackendForm;
|
||||||
use Icinga\Forms\Config\Authentication\LdapBackendForm;
|
use Icinga\Forms\Config\Authentication\LdapBackendForm;
|
||||||
use Icinga\Forms\Config\Authentication\AutologinBackendForm;
|
use Icinga\Forms\Config\Authentication\ExternalBackendForm;
|
||||||
|
|
||||||
class AuthenticationBackendConfigForm extends ConfigForm
|
class AuthenticationBackendConfigForm extends ConfigForm
|
||||||
{
|
{
|
||||||
@ -31,7 +31,7 @@ class AuthenticationBackendConfigForm extends ConfigForm
|
|||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
$this->setName('form_config_authbackend');
|
$this->setName('form_config_authbackend');
|
||||||
$this->setSubmitLabel(t('Save Changes'));
|
$this->setSubmitLabel($this->translate('Save Changes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,10 +67,10 @@ class AuthenticationBackendConfigForm extends ConfigForm
|
|||||||
} elseif ($type === 'ldap') {
|
} elseif ($type === 'ldap') {
|
||||||
$form = new LdapBackendForm();
|
$form = new LdapBackendForm();
|
||||||
$form->setResources(isset($this->resources['ldap']) ? $this->resources['ldap'] : array());
|
$form->setResources(isset($this->resources['ldap']) ? $this->resources['ldap'] : array());
|
||||||
} elseif ($type === 'autologin') {
|
} elseif ($type === 'external') {
|
||||||
$form = new AutologinBackendForm();
|
$form = new ExternalBackendForm();
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidArgumentException(sprintf(t('Invalid backend type "%s" provided'), $type));
|
throw new InvalidArgumentException(sprintf($this->translate('Invalid backend type "%s" provided'), $type));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $form;
|
return $form;
|
||||||
@ -91,9 +91,9 @@ class AuthenticationBackendConfigForm extends ConfigForm
|
|||||||
{
|
{
|
||||||
$name = isset($values['name']) ? $values['name'] : '';
|
$name = isset($values['name']) ? $values['name'] : '';
|
||||||
if (! $name) {
|
if (! $name) {
|
||||||
throw new InvalidArgumentException(t('Authentication backend name missing'));
|
throw new InvalidArgumentException($this->translate('Authentication backend name missing'));
|
||||||
} elseif ($this->config->hasSection($name)) {
|
} elseif ($this->config->hasSection($name)) {
|
||||||
throw new InvalidArgumentException(t('Authentication backend already exists'));
|
throw new InvalidArgumentException($this->translate('Authentication backend already exists'));
|
||||||
}
|
}
|
||||||
|
|
||||||
unset($values['name']);
|
unset($values['name']);
|
||||||
@ -114,11 +114,11 @@ class AuthenticationBackendConfigForm extends ConfigForm
|
|||||||
public function edit($name, array $values)
|
public function edit($name, array $values)
|
||||||
{
|
{
|
||||||
if (! $name) {
|
if (! $name) {
|
||||||
throw new InvalidArgumentException(t('Old authentication backend name missing'));
|
throw new InvalidArgumentException($this->translate('Old authentication backend name missing'));
|
||||||
} elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) {
|
} elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) {
|
||||||
throw new InvalidArgumentException(t('New authentication backend name missing'));
|
throw new InvalidArgumentException($this->translate('New authentication backend name missing'));
|
||||||
} elseif (! $this->config->hasSection($name)) {
|
} elseif (! $this->config->hasSection($name)) {
|
||||||
throw new InvalidArgumentException(t('Unknown authentication backend provided'));
|
throw new InvalidArgumentException($this->translate('Unknown authentication backend provided'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$backendConfig = $this->config->getSection($name);
|
$backendConfig = $this->config->getSection($name);
|
||||||
@ -144,9 +144,9 @@ class AuthenticationBackendConfigForm extends ConfigForm
|
|||||||
public function remove($name)
|
public function remove($name)
|
||||||
{
|
{
|
||||||
if (! $name) {
|
if (! $name) {
|
||||||
throw new InvalidArgumentException(t('Authentication backend name missing'));
|
throw new InvalidArgumentException($this->translate('Authentication backend name missing'));
|
||||||
} elseif (! $this->config->hasSection($name)) {
|
} elseif (! $this->config->hasSection($name)) {
|
||||||
throw new InvalidArgumentException(t('Unknown authentication backend provided'));
|
throw new InvalidArgumentException($this->translate('Unknown authentication backend provided'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$backendConfig = $this->config->getSection($name);
|
$backendConfig = $this->config->getSection($name);
|
||||||
@ -167,9 +167,9 @@ class AuthenticationBackendConfigForm extends ConfigForm
|
|||||||
public function move($name, $position)
|
public function move($name, $position)
|
||||||
{
|
{
|
||||||
if (! $name) {
|
if (! $name) {
|
||||||
throw new InvalidArgumentException(t('Authentication backend name missing'));
|
throw new InvalidArgumentException($this->translate('Authentication backend name missing'));
|
||||||
} elseif (! $this->config->hasSection($name)) {
|
} elseif (! $this->config->hasSection($name)) {
|
||||||
throw new InvalidArgumentException(t('Unknown authentication backend provided'));
|
throw new InvalidArgumentException($this->translate('Unknown authentication backend provided'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$backendOrder = $this->config->keys();
|
$backendOrder = $this->config->keys();
|
||||||
@ -208,10 +208,10 @@ class AuthenticationBackendConfigForm extends ConfigForm
|
|||||||
try {
|
try {
|
||||||
if ($authBackend === null) { // create new backend
|
if ($authBackend === null) { // create new backend
|
||||||
$this->add($this->getValues());
|
$this->add($this->getValues());
|
||||||
$message = t('Authentication backend "%s" has been successfully created');
|
$message = $this->translate('Authentication backend "%s" has been successfully created');
|
||||||
} else { // edit existing backend
|
} else { // edit existing backend
|
||||||
$this->edit($authBackend, $this->getValues());
|
$this->edit($authBackend, $this->getValues());
|
||||||
$message = t('Authentication backend "%s" has been successfully changed');
|
$message = $this->translate('Authentication backend "%s" has been successfully changed');
|
||||||
}
|
}
|
||||||
} catch (InvalidArgumentException $e) {
|
} catch (InvalidArgumentException $e) {
|
||||||
Notification::error($e->getMessage());
|
Notification::error($e->getMessage());
|
||||||
@ -237,11 +237,13 @@ class AuthenticationBackendConfigForm extends ConfigForm
|
|||||||
$authBackend = $this->request->getQuery('auth_backend');
|
$authBackend = $this->request->getQuery('auth_backend');
|
||||||
if ($authBackend !== null) {
|
if ($authBackend !== null) {
|
||||||
if ($authBackend === '') {
|
if ($authBackend === '') {
|
||||||
throw new ConfigurationError(t('Authentication backend name missing'));
|
throw new ConfigurationError($this->translate('Authentication backend name missing'));
|
||||||
} elseif (! $this->config->hasSection($authBackend)) {
|
} elseif (! $this->config->hasSection($authBackend)) {
|
||||||
throw new ConfigurationError(t('Unknown authentication backend provided'));
|
throw new ConfigurationError($this->translate('Unknown authentication backend provided'));
|
||||||
} elseif ($this->config->getSection($authBackend)->backend === null) {
|
} elseif ($this->config->getSection($authBackend)->backend === null) {
|
||||||
throw new ConfigurationError(sprintf(t('Backend "%s" has no `backend\' setting'), $authBackend));
|
throw new ConfigurationError(
|
||||||
|
sprintf($this->translate('Backend "%s" has no `backend\' setting'), $authBackend)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$configValues = $this->config->getSection($authBackend)->toArray();
|
$configValues = $this->config->getSection($authBackend)->toArray();
|
||||||
@ -249,15 +251,15 @@ class AuthenticationBackendConfigForm extends ConfigForm
|
|||||||
$configValues['name'] = $authBackend;
|
$configValues['name'] = $authBackend;
|
||||||
$this->populate($configValues);
|
$this->populate($configValues);
|
||||||
} elseif (empty($this->resources)) {
|
} elseif (empty($this->resources)) {
|
||||||
$autologinBackends = array_filter(
|
$externalBackends = array_filter(
|
||||||
$this->config->toArray(),
|
$this->config->toArray(),
|
||||||
function ($authBackendCfg) {
|
function ($authBackendCfg) {
|
||||||
return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'autologin';
|
return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'external';
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (false === empty($autologinBackends)) {
|
if (false === empty($externalBackends)) {
|
||||||
throw new ConfigurationError(t('Could not find any resources for authentication'));
|
throw new ConfigurationError($this->translate('Could not find any resources for authentication'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,8 +278,8 @@ class AuthenticationBackendConfigForm extends ConfigForm
|
|||||||
array(
|
array(
|
||||||
'order' => 0,
|
'order' => 0,
|
||||||
'ignore' => true,
|
'ignore' => true,
|
||||||
'label' => t('Force Changes'),
|
'label' => $this->translate('Force Changes'),
|
||||||
'description' => t('Check this box to enforce changes without connectivity validation')
|
'description' => $this->translate('Check this box to enforce changes without connectivity validation')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -291,20 +293,20 @@ class AuthenticationBackendConfigForm extends ConfigForm
|
|||||||
$backendType = isset($formData['type']) ? $formData['type'] : null;
|
$backendType = isset($formData['type']) ? $formData['type'] : null;
|
||||||
|
|
||||||
if (isset($this->resources['db'])) {
|
if (isset($this->resources['db'])) {
|
||||||
$backendTypes['db'] = t('Database');
|
$backendTypes['db'] = $this->translate('Database');
|
||||||
}
|
}
|
||||||
if (isset($this->resources['ldap']) && ($backendType === 'ldap' || Platform::extensionLoaded('ldap'))) {
|
if (isset($this->resources['ldap']) && ($backendType === 'ldap' || Platform::extensionLoaded('ldap'))) {
|
||||||
$backendTypes['ldap'] = 'LDAP';
|
$backendTypes['ldap'] = 'LDAP';
|
||||||
}
|
}
|
||||||
|
|
||||||
$autologinBackends = array_filter(
|
$externalBackends = array_filter(
|
||||||
$this->config->toArray(),
|
$this->config->toArray(),
|
||||||
function ($authBackendCfg) {
|
function ($authBackendCfg) {
|
||||||
return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'autologin';
|
return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'external';
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
if ($backendType === 'autologin' || empty($autologinBackends)) {
|
if ($backendType === 'external' || empty($externalBackends)) {
|
||||||
$backendTypes['autologin'] = t('Autologin');
|
$backendTypes['external'] = $this->translate('External');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($backendType === null) {
|
if ($backendType === null) {
|
||||||
@ -318,8 +320,10 @@ class AuthenticationBackendConfigForm extends ConfigForm
|
|||||||
'ignore' => true,
|
'ignore' => true,
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'autosubmit' => true,
|
'autosubmit' => true,
|
||||||
'label' => t('Backend Type'),
|
'label' => $this->translate('Backend Type'),
|
||||||
'description' => t('The type of the resource to use for this authenticaton provider'),
|
'description' => $this->translate(
|
||||||
|
'The type of the resource to use for this authenticaton provider'
|
||||||
|
),
|
||||||
'multiOptions' => $backendTypes
|
'multiOptions' => $backendTypes
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -52,7 +52,7 @@ class AuthenticationBackendReorderForm extends ConfigForm
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if ($configForm->move($backendName, $position)->save()) {
|
if ($configForm->move($backendName, $position)->save()) {
|
||||||
Notification::success(t('Authentication order updated!'));
|
Notification::success($this->translate('Authentication order updated!'));
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,8 @@
|
|||||||
|
|
||||||
namespace Icinga\Forms\Config\General;
|
namespace Icinga\Forms\Config\General;
|
||||||
|
|
||||||
use DateTimeZone;
|
|
||||||
use Icinga\Application\Icinga;
|
use Icinga\Application\Icinga;
|
||||||
use Icinga\Data\ResourceFactory;
|
use Icinga\Data\ResourceFactory;
|
||||||
use Icinga\Util\Translator;
|
|
||||||
use Icinga\Web\Form;
|
use Icinga\Web\Form;
|
||||||
|
|
||||||
|
|
||||||
@ -33,10 +31,10 @@ class ApplicationConfigForm extends Form
|
|||||||
'text',
|
'text',
|
||||||
'global_module_path',
|
'global_module_path',
|
||||||
array(
|
array(
|
||||||
'label' => t('Module Path'),
|
'label' => $this->translate('Module Path'),
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'value' => implode(':', Icinga::app()->getModuleManager()->getModuleDirs()),
|
'value' => implode(':', Icinga::app()->getModuleManager()->getModuleDirs()),
|
||||||
'description' => t(
|
'description' => $this->translate(
|
||||||
'Contains the directories that will be searched for available modules, separated by '
|
'Contains the directories that will be searched for available modules, separated by '
|
||||||
. 'colons. Modules that don\'t exist in these directories can still be symlinked in '
|
. 'colons. Modules that don\'t exist in these directories can still be symlinked in '
|
||||||
. 'the module folder, but won\'t show up in the list of disabled modules.'
|
. 'the module folder, but won\'t show up in the list of disabled modules.'
|
||||||
@ -46,19 +44,19 @@ class ApplicationConfigForm extends Form
|
|||||||
|
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
'select',
|
'select',
|
||||||
'preferences_type',
|
'preferences_store',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'autosubmit' => true,
|
'autosubmit' => true,
|
||||||
'label' => t('User Preference Storage Type'),
|
'label' => $this->translate('User Preference Storage Type'),
|
||||||
'multiOptions' => array(
|
'multiOptions' => array(
|
||||||
'ini' => t('File System (INI Files)'),
|
'ini' => $this->translate('File System (INI Files)'),
|
||||||
'db' => t('Database'),
|
'db' => $this->translate('Database'),
|
||||||
'null' => t('Don\'t Store Preferences')
|
'none' => $this->translate('Don\'t Store Preferences')
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if (isset($formData['preferences_type']) && $formData['preferences_type'] === 'db') {
|
if (isset($formData['preferences_store']) && $formData['preferences_store'] === 'db') {
|
||||||
$backends = array();
|
$backends = array();
|
||||||
foreach (ResourceFactory::getResourceConfigs()->toArray() as $name => $resource) {
|
foreach (ResourceFactory::getResourceConfigs()->toArray() as $name => $resource) {
|
||||||
if ($resource['type'] === 'db') {
|
if ($resource['type'] === 'db') {
|
||||||
@ -72,7 +70,7 @@ class ApplicationConfigForm extends Form
|
|||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'multiOptions' => $backends,
|
'multiOptions' => $backends,
|
||||||
'label' => t('Database Connection')
|
'label' => $this->translate('Database Connection')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
namespace Icinga\Forms\Config\General;
|
namespace Icinga\Forms\Config\General;
|
||||||
|
|
||||||
use Icinga\Application\Icinga;
|
|
||||||
use Icinga\Application\Logger;
|
use Icinga\Application\Logger;
|
||||||
use Icinga\Web\Form;
|
use Icinga\Web\Form;
|
||||||
use Icinga\Web\Form\Validator\WritablePathValidator;
|
use Icinga\Web\Form\Validator\WritablePathValidator;
|
||||||
@ -31,12 +30,12 @@ class LoggingConfigForm extends Form
|
|||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'autosubmit' => true,
|
'autosubmit' => true,
|
||||||
'label' => t('Logging Type'),
|
'label' => $this->translate('Logging Type'),
|
||||||
'description' => t('The type of logging to utilize.'),
|
'description' => $this->translate('The type of logging to utilize.'),
|
||||||
'multiOptions' => array(
|
'multiOptions' => array(
|
||||||
'syslog' => 'Syslog',
|
'syslog' => 'Syslog',
|
||||||
'file' => t('File', 'app.config.logging.type'),
|
'file' => $this->translate('File', 'app.config.logging.type'),
|
||||||
'none' => t('None', 'app.config.logging.type')
|
'none' => $this->translate('None', 'app.config.logging.type')
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -47,13 +46,13 @@ class LoggingConfigForm extends Form
|
|||||||
'logging_level',
|
'logging_level',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Logging Level'),
|
'label' => $this->translate('Logging Level'),
|
||||||
'description' => t('The maximum logging level to emit.'),
|
'description' => $this->translate('The maximum logging level to emit.'),
|
||||||
'multiOptions' => array(
|
'multiOptions' => array(
|
||||||
Logger::$levels[Logger::ERROR] => t('Error', 'app.config.logging.level'),
|
Logger::$levels[Logger::ERROR] => $this->translate('Error', 'app.config.logging.level'),
|
||||||
Logger::$levels[Logger::WARNING] => t('Warning', 'app.config.logging.level'),
|
Logger::$levels[Logger::WARNING] => $this->translate('Warning', 'app.config.logging.level'),
|
||||||
Logger::$levels[Logger::INFO] => t('Information', 'app.config.logging.level'),
|
Logger::$levels[Logger::INFO] => $this->translate('Information', 'app.config.logging.level'),
|
||||||
Logger::$levels[Logger::DEBUG] => t('Debug', 'app.config.logging.level')
|
Logger::$levels[Logger::DEBUG] => $this->translate('Debug', 'app.config.logging.level')
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -65,9 +64,11 @@ class LoggingConfigForm extends Form
|
|||||||
'logging_application',
|
'logging_application',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Application Prefix'),
|
'label' => $this->translate('Application Prefix'),
|
||||||
'description' => t('The name of the application by which to prefix syslog messages.'),
|
'description' => $this->translate(
|
||||||
'value' => 'icingaweb',
|
'The name of the application by which to prefix syslog messages.'
|
||||||
|
),
|
||||||
|
'value' => 'icingaweb2',
|
||||||
'validators' => array(
|
'validators' => array(
|
||||||
array(
|
array(
|
||||||
'Regex',
|
'Regex',
|
||||||
@ -91,8 +92,8 @@ class LoggingConfigForm extends Form
|
|||||||
// 'logging_facility',
|
// 'logging_facility',
|
||||||
// array(
|
// array(
|
||||||
// 'required' => true,
|
// 'required' => true,
|
||||||
// 'label' => t('Facility'),
|
// 'label' => $this->translate('Facility'),
|
||||||
// 'description' => t('The syslog facility to utilize.'),
|
// 'description' => $this->translate('The syslog facility to utilize.'),
|
||||||
// 'multiOptions' => array(
|
// 'multiOptions' => array(
|
||||||
// 'user' => 'LOG_USER'
|
// 'user' => 'LOG_USER'
|
||||||
// )
|
// )
|
||||||
@ -104,9 +105,9 @@ class LoggingConfigForm extends Form
|
|||||||
'logging_file',
|
'logging_file',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('File path'),
|
'label' => $this->translate('File path'),
|
||||||
'description' => t('The full path to the log file to write messages to.'),
|
'description' => $this->translate('The full path to the log file to write messages to.'),
|
||||||
'value' => $this->getDefaultLogDir(),
|
'value' => '/var/log/icingaweb2/icingaweb2.log',
|
||||||
'validators' => array(new WritablePathValidator())
|
'validators' => array(new WritablePathValidator())
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -114,14 +115,4 @@ class LoggingConfigForm extends Form
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the default logging directory for type 'file'
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function getDefaultLogDir()
|
|
||||||
{
|
|
||||||
return realpath(Icinga::app()->getApplicationDir('../var/log/icingaweb.log'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ class GeneralConfigForm extends ConfigForm
|
|||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
$this->setName('form_config_general');
|
$this->setName('form_config_general');
|
||||||
$this->setSubmitLabel(t('Save Changes'));
|
$this->setSubmitLabel($this->translate('Save Changes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,7 +52,7 @@ class GeneralConfigForm extends ConfigForm
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->save()) {
|
if ($this->save()) {
|
||||||
Notification::success(t('New configuration has successfully been stored'));
|
Notification::success($this->translate('New configuration has successfully been stored'));
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,8 @@ class DbResourceForm extends Form
|
|||||||
'name',
|
'name',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Resource Name'),
|
'label' => $this->translate('Resource Name'),
|
||||||
'description' => t('The unique name of this resource')
|
'description' => $this->translate('The unique name of this resource')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
@ -50,8 +50,8 @@ class DbResourceForm extends Form
|
|||||||
'db',
|
'db',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Database Type'),
|
'label' => $this->translate('Database Type'),
|
||||||
'description' => t('The type of SQL database'),
|
'description' => $this->translate('The type of SQL database'),
|
||||||
'multiOptions' => $dbChoices
|
'multiOptions' => $dbChoices
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -60,8 +60,8 @@ class DbResourceForm extends Form
|
|||||||
'host',
|
'host',
|
||||||
array (
|
array (
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Host'),
|
'label' => $this->translate('Host'),
|
||||||
'description' => t('The hostname of the database'),
|
'description' => $this->translate('The hostname of the database'),
|
||||||
'value' => 'localhost'
|
'value' => 'localhost'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -70,8 +70,8 @@ class DbResourceForm extends Form
|
|||||||
'port',
|
'port',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Port'),
|
'label' => $this->translate('Port'),
|
||||||
'description' => t('The port to use'),
|
'description' => $this->translate('The port to use'),
|
||||||
'value' => 3306
|
'value' => 3306
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -80,8 +80,8 @@ class DbResourceForm extends Form
|
|||||||
'dbname',
|
'dbname',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Database Name'),
|
'label' => $this->translate('Database Name'),
|
||||||
'description' => t('The name of the database to use')
|
'description' => $this->translate('The name of the database to use')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
@ -89,8 +89,8 @@ class DbResourceForm extends Form
|
|||||||
'username',
|
'username',
|
||||||
array (
|
array (
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Username'),
|
'label' => $this->translate('Username'),
|
||||||
'description' => t('The user name to use for authentication')
|
'description' => $this->translate('The user name to use for authentication')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
@ -99,8 +99,8 @@ class DbResourceForm extends Form
|
|||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'renderPassword' => true,
|
'renderPassword' => true,
|
||||||
'label' => t('Password'),
|
'label' => $this->translate('Password'),
|
||||||
'description' => t('The password to use for authentication')
|
'description' => $this->translate('The password to use for authentication')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -132,7 +132,9 @@ class DbResourceForm extends Form
|
|||||||
$resource = ResourceFactory::createResource(new ConfigObject($form->getValues()));
|
$resource = ResourceFactory::createResource(new ConfigObject($form->getValues()));
|
||||||
$resource->getConnection()->getConnection();
|
$resource->getConnection()->getConnection();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$form->addError(t('Connectivity validation failed, connection to the given resource not possible.'));
|
$form->addError(
|
||||||
|
$form->translate('Connectivity validation failed, connection to the given resource not possible.')
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,8 +30,8 @@ class FileResourceForm extends Form
|
|||||||
'name',
|
'name',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Resource Name'),
|
'label' => $this->translate('Resource Name'),
|
||||||
'description' => t('The unique name of this resource')
|
'description' => $this->translate('The unique name of this resource')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
@ -39,8 +39,8 @@ class FileResourceForm extends Form
|
|||||||
'filename',
|
'filename',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Filepath'),
|
'label' => $this->translate('Filepath'),
|
||||||
'description' => t('The filename to fetch information from'),
|
'description' => $this->translate('The filename to fetch information from'),
|
||||||
'validators' => array(new ReadablePathValidator())
|
'validators' => array(new ReadablePathValidator())
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -49,8 +49,8 @@ class FileResourceForm extends Form
|
|||||||
'fields',
|
'fields',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Pattern'),
|
'label' => $this->translate('Pattern'),
|
||||||
'description' => t('The regular expression by which to identify columns')
|
'description' => $this->translate('The regular expression by which to identify columns')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -32,8 +32,8 @@ class LdapResourceForm extends Form
|
|||||||
'name',
|
'name',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Resource Name'),
|
'label' => $this->translate('Resource Name'),
|
||||||
'description' => t('The unique name of this resource')
|
'description' => $this->translate('The unique name of this resource')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
@ -41,8 +41,10 @@ class LdapResourceForm extends Form
|
|||||||
'hostname',
|
'hostname',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Host'),
|
'label' => $this->translate('Host'),
|
||||||
'description' => t('The hostname or address of the LDAP server to use for authentication'),
|
'description' => $this->translate(
|
||||||
|
'The hostname or address of the LDAP server to use for authentication'
|
||||||
|
),
|
||||||
'value' => 'localhost'
|
'value' => 'localhost'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -51,8 +53,8 @@ class LdapResourceForm extends Form
|
|||||||
'port',
|
'port',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Port'),
|
'label' => $this->translate('Port'),
|
||||||
'description' => t('The port of the LDAP server to use for authentication'),
|
'description' => $this->translate('The port of the LDAP server to use for authentication'),
|
||||||
'value' => 389
|
'value' => 389
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -61,8 +63,10 @@ class LdapResourceForm extends Form
|
|||||||
'root_dn',
|
'root_dn',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Root DN'),
|
'label' => $this->translate('Root DN'),
|
||||||
'description' => t('Only the root and its child nodes will be accessible on this resource.')
|
'description' => $this->translate(
|
||||||
|
'Only the root and its child nodes will be accessible on this resource.'
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
@ -70,8 +74,8 @@ class LdapResourceForm extends Form
|
|||||||
'bind_dn',
|
'bind_dn',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Bind DN'),
|
'label' => $this->translate('Bind DN'),
|
||||||
'description' => t('The user dn to use for querying the ldap server')
|
'description' => $this->translate('The user dn to use for querying the ldap server')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
@ -80,8 +84,8 @@ class LdapResourceForm extends Form
|
|||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'renderPassword' => true,
|
'renderPassword' => true,
|
||||||
'label' => t('Bind Password'),
|
'label' => $this->translate('Bind Password'),
|
||||||
'description' => t('The password to use for querying the ldap server')
|
'description' => $this->translate('The password to use for querying the ldap server')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -119,7 +123,9 @@ class LdapResourceForm extends Form
|
|||||||
throw new Exception();
|
throw new Exception();
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$form->addError(t('Connectivity validation failed, connection to the given resource not possible.'));
|
$form->addError(
|
||||||
|
$form->translate('Connectivity validation failed, connection to the given resource not possible.')
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,8 +33,8 @@ class LivestatusResourceForm extends Form
|
|||||||
'name',
|
'name',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Resource Name'),
|
'label' => $this->translate('Resource Name'),
|
||||||
'description' => t('The unique name of this resource')
|
'description' => $this->translate('The unique name of this resource')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
@ -42,9 +42,9 @@ class LivestatusResourceForm extends Form
|
|||||||
'socket',
|
'socket',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Socket'),
|
'label' => $this->translate('Socket'),
|
||||||
'description' => t('The path to your livestatus socket used for querying monitoring data'),
|
'description' => $this->translate('The path to your livestatus socket used for querying monitoring data'),
|
||||||
'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/rw/livestatus')
|
'value' => '/var/run/icinga2/cmd/livestatus'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -75,8 +75,10 @@ class LivestatusResourceForm extends Form
|
|||||||
try {
|
try {
|
||||||
$resource = ResourceFactory::createResource(new ConfigObject($form->getValues()));
|
$resource = ResourceFactory::createResource(new ConfigObject($form->getValues()));
|
||||||
$resource->connect()->disconnect();
|
$resource->connect()->disconnect();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $_) {
|
||||||
$form->addError(t('Connectivity validation failed, connection to the given resource not possible.'));
|
$form->addError(
|
||||||
|
$form->translate('Connectivity validation failed, connection to the given resource not possible.')
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
$this->setName('form_config_resource');
|
$this->setName('form_config_resource');
|
||||||
$this->setSubmitLabel(t('Save Changes'));
|
$this->setSubmitLabel($this->translate('Save Changes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,7 +43,7 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
} elseif ($type === 'file') {
|
} elseif ($type === 'file') {
|
||||||
return new FileResourceForm();
|
return new FileResourceForm();
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidArgumentException(sprintf(t('Invalid resource type "%s" provided'), $type));
|
throw new InvalidArgumentException(sprintf($this->translate('Invalid resource type "%s" provided'), $type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,9 +62,9 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
{
|
{
|
||||||
$name = isset($values['name']) ? $values['name'] : '';
|
$name = isset($values['name']) ? $values['name'] : '';
|
||||||
if (! $name) {
|
if (! $name) {
|
||||||
throw new InvalidArgumentException(t('Resource name missing'));
|
throw new InvalidArgumentException($this->translate('Resource name missing'));
|
||||||
} elseif ($this->config->hasSection($name)) {
|
} elseif ($this->config->hasSection($name)) {
|
||||||
throw new InvalidArgumentException(t('Resource already exists'));
|
throw new InvalidArgumentException($this->translate('Resource already exists'));
|
||||||
}
|
}
|
||||||
|
|
||||||
unset($values['name']);
|
unset($values['name']);
|
||||||
@ -85,11 +85,11 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
public function edit($name, array $values)
|
public function edit($name, array $values)
|
||||||
{
|
{
|
||||||
if (! $name) {
|
if (! $name) {
|
||||||
throw new InvalidArgumentException(t('Old resource name missing'));
|
throw new InvalidArgumentException($this->translate('Old resource name missing'));
|
||||||
} elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) {
|
} elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) {
|
||||||
throw new InvalidArgumentException(t('New resource name missing'));
|
throw new InvalidArgumentException($this->translate('New resource name missing'));
|
||||||
} elseif (! $this->config->hasSection($name)) {
|
} elseif (! $this->config->hasSection($name)) {
|
||||||
throw new InvalidArgumentException(t('Unknown resource provided'));
|
throw new InvalidArgumentException($this->translate('Unknown resource provided'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$resourceConfig = $this->config->getSection($name);
|
$resourceConfig = $this->config->getSection($name);
|
||||||
@ -111,9 +111,9 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
public function remove($name)
|
public function remove($name)
|
||||||
{
|
{
|
||||||
if (! $name) {
|
if (! $name) {
|
||||||
throw new InvalidArgumentException(t('Resource name missing'));
|
throw new InvalidArgumentException($this->translate('Resource name missing'));
|
||||||
} elseif (! $this->config->hasSection($name)) {
|
} elseif (! $this->config->hasSection($name)) {
|
||||||
throw new InvalidArgumentException(t('Unknown resource provided'));
|
throw new InvalidArgumentException($this->translate('Unknown resource provided'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$resourceConfig = $this->config->getSection($name);
|
$resourceConfig = $this->config->getSection($name);
|
||||||
@ -143,10 +143,10 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
try {
|
try {
|
||||||
if ($resource === null) { // create new resource
|
if ($resource === null) { // create new resource
|
||||||
$this->add($this->getValues());
|
$this->add($this->getValues());
|
||||||
$message = t('Resource "%s" has been successfully created');
|
$message = $this->translate('Resource "%s" has been successfully created');
|
||||||
} else { // edit existing resource
|
} else { // edit existing resource
|
||||||
$this->edit($resource, $this->getValues());
|
$this->edit($resource, $this->getValues());
|
||||||
$message = t('Resource "%s" has been successfully changed');
|
$message = $this->translate('Resource "%s" has been successfully changed');
|
||||||
}
|
}
|
||||||
} catch (InvalidArgumentException $e) {
|
} catch (InvalidArgumentException $e) {
|
||||||
Notification::error($e->getMessage());
|
Notification::error($e->getMessage());
|
||||||
@ -172,9 +172,9 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
$resource = $this->request->getQuery('resource');
|
$resource = $this->request->getQuery('resource');
|
||||||
if ($resource !== null) {
|
if ($resource !== null) {
|
||||||
if ($resource === '') {
|
if ($resource === '') {
|
||||||
throw new ConfigurationError(t('Resource name missing'));
|
throw new ConfigurationError($this->translate('Resource name missing'));
|
||||||
} elseif (! $this->config->hasSection($resource)) {
|
} elseif (! $this->config->hasSection($resource)) {
|
||||||
throw new ConfigurationError(t('Unknown resource provided'));
|
throw new ConfigurationError($this->translate('Unknown resource provided'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$configValues = $this->config->getSection($resource)->toArray();
|
$configValues = $this->config->getSection($resource)->toArray();
|
||||||
@ -197,8 +197,8 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
array(
|
array(
|
||||||
'order' => 0,
|
'order' => 0,
|
||||||
'ignore' => true,
|
'ignore' => true,
|
||||||
'label' => t('Force Changes'),
|
'label' => $this->translate('Force Changes'),
|
||||||
'description' => t('Check this box to enforce changes without connectivity validation')
|
'description' => $this->translate('Check this box to enforce changes without connectivity validation')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -211,14 +211,14 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
$resourceType = isset($formData['type']) ? $formData['type'] : 'db';
|
$resourceType = isset($formData['type']) ? $formData['type'] : 'db';
|
||||||
|
|
||||||
$resourceTypes = array(
|
$resourceTypes = array(
|
||||||
'file' => t('File'),
|
'file' => $this->translate('File'),
|
||||||
'livestatus' => 'Livestatus',
|
'livestatus' => 'Livestatus',
|
||||||
);
|
);
|
||||||
if ($resourceType === 'ldap' || Platform::extensionLoaded('ldap')) {
|
if ($resourceType === 'ldap' || Platform::extensionLoaded('ldap')) {
|
||||||
$resourceTypes['ldap'] = 'LDAP';
|
$resourceTypes['ldap'] = 'LDAP';
|
||||||
}
|
}
|
||||||
if ($resourceType === 'db' || Platform::hasMysqlSupport() || Platform::hasPostgresqlSupport()) {
|
if ($resourceType === 'db' || Platform::hasMysqlSupport() || Platform::hasPostgresqlSupport()) {
|
||||||
$resourceTypes['db'] = t('SQL Database');
|
$resourceTypes['db'] = $this->translate('SQL Database');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
@ -227,8 +227,8 @@ class ResourceConfigForm extends ConfigForm
|
|||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'autosubmit' => true,
|
'autosubmit' => true,
|
||||||
'label' => t('Resource Type'),
|
'label' => $this->translate('Resource Type'),
|
||||||
'description' => t('The type of resource'),
|
'description' => $this->translate('The type of resource'),
|
||||||
'multiOptions' => $resourceTypes,
|
'multiOptions' => $resourceTypes,
|
||||||
'value' => $resourceType
|
'value' => $resourceType
|
||||||
)
|
)
|
||||||
|
@ -17,6 +17,6 @@ class ConfirmRemovalForm extends Form
|
|||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
$this->setName('form_confirm_removal');
|
$this->setName('form_confirm_removal');
|
||||||
$this->setSubmitLabel(t('Confirm Removal'));
|
$this->setSubmitLabel($this->translate('Confirm Removal'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ class DashletForm extends Form
|
|||||||
{
|
{
|
||||||
$this->setName('form_dashboard_addurl');
|
$this->setName('form_dashboard_addurl');
|
||||||
if (! $this->getSubmitLabel()) {
|
if (! $this->getSubmitLabel()) {
|
||||||
$this->setSubmitLabel(t('Add To Dashboard'));
|
$this->setSubmitLabel($this->translate('Add To Dashboard'));
|
||||||
}
|
}
|
||||||
$this->setAction(URL::fromRequest());
|
$this->setAction(URL::fromRequest());
|
||||||
}
|
}
|
||||||
@ -66,9 +66,10 @@ class DashletForm extends Form
|
|||||||
'url',
|
'url',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Url'),
|
'label' => $this->translate('Url'),
|
||||||
'description' =>
|
'description' => $this->translate(
|
||||||
t('Enter url being loaded in the dashlet. You can paste the full URL, including filters.')
|
'Enter url being loaded in the dashlet. You can paste the full URL, including filters.'
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
@ -76,8 +77,8 @@ class DashletForm extends Form
|
|||||||
'dashlet',
|
'dashlet',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Dashlet Title'),
|
'label' => $this->translate('Dashlet Title'),
|
||||||
'description' => t('Enter a title for the dashlet.')
|
'description' => $this->translate('Enter a title for the dashlet.')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
@ -95,9 +96,8 @@ class DashletForm extends Form
|
|||||||
'pane',
|
'pane',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t("New Dashboard Title"),
|
'label' => $this->translate("New Dashboard Title"),
|
||||||
'description' =>
|
'description' => $this->translate('Enter a title for the new pane.')
|
||||||
t('Enter a title for the new pane.')
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -106,10 +106,9 @@ class DashletForm extends Form
|
|||||||
'pane',
|
'pane',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Dashboard'),
|
'label' => $this->translate('Dashboard'),
|
||||||
'multiOptions' => $panes,
|
'multiOptions' => $panes,
|
||||||
'description' =>
|
'description' => $this->translate('Select a pane you want to add the dashlet.')
|
||||||
t('Select a pane you want to add the dashlet.')
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -119,9 +118,9 @@ class DashletForm extends Form
|
|||||||
'create_new_pane',
|
'create_new_pane',
|
||||||
array(
|
array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'label' => t('New dashboard'),
|
'label' => $this->translate('New dashboard'),
|
||||||
'class' => 'autosubmit',
|
'class' => 'autosubmit',
|
||||||
'description' => t('Check this box if you want to add the dashlet to a new dashboard')
|
'description' => $this->translate('Check this box if you want to add the dashlet to a new dashboard')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,8 @@ class LdapDiscoveryForm extends Form
|
|||||||
'domain',
|
'domain',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Search Domain'),
|
'label' => $this->translate('Search Domain'),
|
||||||
'description' => t('Search this domain for records of available servers.'),
|
'description' => $this->translate('Search this domain for records of available servers.'),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ class LdapDiscoveryForm extends Form
|
|||||||
'note',
|
'note',
|
||||||
'additional_description',
|
'additional_description',
|
||||||
array(
|
array(
|
||||||
'value' => t('No Ldap servers found on this domain.'
|
'value' => $this->translate('No Ldap servers found on this domain.'
|
||||||
. ' You can try to specify host and port and try again, or just skip this step and '
|
. ' You can try to specify host and port and try again, or just skip this step and '
|
||||||
. 'configure the server manually.'
|
. 'configure the server manually.'
|
||||||
)
|
)
|
||||||
@ -47,8 +47,8 @@ class LdapDiscoveryForm extends Form
|
|||||||
'hostname',
|
'hostname',
|
||||||
array(
|
array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'label' => t('Host'),
|
'label' => $this->translate('Host'),
|
||||||
'description' => t('IP or host name to search.'),
|
'description' => $this->translate('IP or hostname to search.'),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -57,8 +57,8 @@ class LdapDiscoveryForm extends Form
|
|||||||
'port',
|
'port',
|
||||||
array(
|
array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'label' => t('Port'),
|
'label' => $this->translate('Port'),
|
||||||
'description' => t('Port', 389),
|
'description' => $this->translate('Port', 389),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ class PreferenceForm extends Form
|
|||||||
*/
|
*/
|
||||||
public function onSuccess()
|
public function onSuccess()
|
||||||
{
|
{
|
||||||
$this->preferences = new Preferences($this->store->load());
|
$this->preferences = new Preferences($this->store ? $this->store->load() : array());
|
||||||
|
|
||||||
$webPreferences = $this->preferences->get('icingaweb', array());
|
$webPreferences = $this->preferences->get('icingaweb', array());
|
||||||
foreach ($this->getValues() as $key => $value) {
|
foreach ($this->getValues() as $key => $value) {
|
||||||
@ -103,11 +103,11 @@ class PreferenceForm extends Form
|
|||||||
Session::getSession()->user->setPreferences($this->preferences);
|
Session::getSession()->user->setPreferences($this->preferences);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($this->getElement('btn_submit_preferences')->isChecked()) {
|
if ($this->store && $this->getElement('btn_submit_preferences')->isChecked()) {
|
||||||
$this->save();
|
$this->save();
|
||||||
Notification::success(t('Preferences successfully saved'));
|
Notification::success($this->translate('Preferences successfully saved'));
|
||||||
} else {
|
} else {
|
||||||
Notification::success(t('Preferences successfully saved for the current session'));
|
Notification::success($this->translate('Preferences successfully saved for the current session'));
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Logger::error($e);
|
Logger::error($e);
|
||||||
@ -142,13 +142,13 @@ class PreferenceForm extends Form
|
|||||||
public function createElements(array $formData)
|
public function createElements(array $formData)
|
||||||
{
|
{
|
||||||
$languages = array();
|
$languages = array();
|
||||||
$languages['autodetect'] = sprintf(t('Browser (%s)', 'preferences.form'), $this->getLocale());
|
$languages['autodetect'] = sprintf($this->translate('Browser (%s)', 'preferences.form'), $this->getLocale());
|
||||||
foreach (Translator::getAvailableLocaleCodes() as $language) {
|
foreach (Translator::getAvailableLocaleCodes() as $language) {
|
||||||
$languages[$language] = $language;
|
$languages[$language] = $language;
|
||||||
}
|
}
|
||||||
|
|
||||||
$tzList = array();
|
$tzList = array();
|
||||||
$tzList['autodetect'] = sprintf(t('Browser (%s)', 'preferences.form'), $this->getDefaultTimezone());
|
$tzList['autodetect'] = sprintf($this->translate('Browser (%s)', 'preferences.form'), $this->getDefaultTimezone());
|
||||||
foreach (DateTimeZone::listIdentifiers() as $tz) {
|
foreach (DateTimeZone::listIdentifiers() as $tz) {
|
||||||
$tzList[$tz] = $tz;
|
$tzList[$tz] = $tz;
|
||||||
}
|
}
|
||||||
@ -158,8 +158,8 @@ class PreferenceForm extends Form
|
|||||||
'language',
|
'language',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Your Current Language'),
|
'label' => $this->translate('Your Current Language'),
|
||||||
'description' => t('Use the following language to display texts and messages'),
|
'description' => $this->translate('Use the following language to display texts and messages'),
|
||||||
'multiOptions' => $languages,
|
'multiOptions' => $languages,
|
||||||
'value' => substr(setlocale(LC_ALL, 0), 0, 5)
|
'value' => substr(setlocale(LC_ALL, 0), 0, 5)
|
||||||
)
|
)
|
||||||
@ -170,8 +170,8 @@ class PreferenceForm extends Form
|
|||||||
'timezone',
|
'timezone',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Your Current Timezone'),
|
'label' => $this->translate('Your Current Timezone'),
|
||||||
'description' => t('Use the following timezone for dates and times'),
|
'description' => $this->translate('Use the following timezone for dates and times'),
|
||||||
'multiOptions' => $tzList,
|
'multiOptions' => $tzList,
|
||||||
'value' => $this->getDefaultTimezone()
|
'value' => $this->getDefaultTimezone()
|
||||||
)
|
)
|
||||||
@ -182,29 +182,31 @@ class PreferenceForm extends Form
|
|||||||
'show_benchmark',
|
'show_benchmark',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Use benchmark')
|
'label' => $this->translate('Use benchmark')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->addElement(
|
if ($this->store) {
|
||||||
'submit',
|
$this->addElement(
|
||||||
'btn_submit_preferences',
|
'submit',
|
||||||
array(
|
'btn_submit_preferences',
|
||||||
'ignore' => true,
|
array(
|
||||||
'label' => t('Save to the Preferences'),
|
'ignore' => true,
|
||||||
'decorators' => array(
|
'label' => $this->translate('Save to the Preferences'),
|
||||||
'ViewHelper',
|
'decorators' => array(
|
||||||
array('HtmlTag', array('tag' => 'div'))
|
'ViewHelper',
|
||||||
|
array('HtmlTag', array('tag' => 'div'))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
);
|
||||||
);
|
}
|
||||||
|
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
'submit',
|
'submit',
|
||||||
'btn_submit_session',
|
'btn_submit_session',
|
||||||
array(
|
array(
|
||||||
'ignore' => true,
|
'ignore' => true,
|
||||||
'label' => t('Save for the current Session'),
|
'label' => $this->translate('Save for the current Session'),
|
||||||
'decorators' => array(
|
'decorators' => array(
|
||||||
'ViewHelper',
|
'ViewHelper',
|
||||||
array('HtmlTag', array('tag' => 'div'))
|
array('HtmlTag', array('tag' => 'div'))
|
||||||
|
@ -6,6 +6,7 @@ namespace Icinga\Forms\Security;
|
|||||||
|
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use LogicException;
|
use LogicException;
|
||||||
|
use Zend_Form_Element;
|
||||||
use Icinga\Application\Icinga;
|
use Icinga\Application\Icinga;
|
||||||
use Icinga\Forms\ConfigForm;
|
use Icinga\Forms\ConfigForm;
|
||||||
use Icinga\Util\String;
|
use Icinga\Util\String;
|
||||||
@ -18,14 +19,14 @@ class RoleForm extends ConfigForm
|
|||||||
/**
|
/**
|
||||||
* Provided permissions by currently loaded modules
|
* Provided permissions by currently loaded modules
|
||||||
*
|
*
|
||||||
* @var array
|
* @type array
|
||||||
*/
|
*/
|
||||||
protected $providedPermissions = array();
|
protected $providedPermissions = array('*' => '*');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provided restrictions by currently loaded modules
|
* Provided restrictions by currently loaded modules
|
||||||
*
|
*
|
||||||
* @var array
|
* @type array
|
||||||
*/
|
*/
|
||||||
protected $providedRestrictions = array();
|
protected $providedRestrictions = array();
|
||||||
|
|
||||||
@ -35,14 +36,26 @@ class RoleForm extends ConfigForm
|
|||||||
*/
|
*/
|
||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
|
$helper = new Zend_Form_Element('bogus');
|
||||||
foreach (Icinga::app()->getModuleManager()->getLoadedModules() as $module) {
|
foreach (Icinga::app()->getModuleManager()->getLoadedModules() as $module) {
|
||||||
foreach ($module->getProvidedPermissions() as $permission) {
|
foreach ($module->getProvidedPermissions() as $permission) {
|
||||||
/** @var object $permission */
|
/** @type object $permission */
|
||||||
$this->providedPermissions[$permission->name] = $permission->name . ': ' . $permission->description;
|
$this->providedPermissions[$permission->name] = $permission->name . ': ' . $permission->description;
|
||||||
}
|
}
|
||||||
foreach ($module->getProvidedRestrictions() as $restriction) {
|
foreach ($module->getProvidedRestrictions() as $restriction) {
|
||||||
/** @var object $restriction */
|
/** @type object $restriction */
|
||||||
$this->providedRestrictions[$restriction->name] = $restriction->description;
|
$name = $helper->filterName($restriction->name); // Zend only permits alphanumerics, the underscore,
|
||||||
|
// the circumflex and any ASCII character in range
|
||||||
|
// \x7f to \xff (127 to 255)
|
||||||
|
while (isset($this->providedRestrictions[$name])) {
|
||||||
|
// Because Zend_Form_Element::filterName() replaces any not permitted character with the empty
|
||||||
|
// string we may have duplicate names, e.g. 're/striction' and 'restriction'
|
||||||
|
$name .= '_';
|
||||||
|
}
|
||||||
|
$this->providedRestrictions[$name] = array(
|
||||||
|
'description' => $restriction->description,
|
||||||
|
'name' => $restriction->name
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,8 +72,8 @@ class RoleForm extends ConfigForm
|
|||||||
'name',
|
'name',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'label' => t('Role Name'),
|
'label' => $this->translate('Role Name'),
|
||||||
'description' => t('The name of the role'),
|
'description' => $this->translate('The name of the role'),
|
||||||
'ignore' => true
|
'ignore' => true
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -68,35 +81,37 @@ class RoleForm extends ConfigForm
|
|||||||
'textarea',
|
'textarea',
|
||||||
'users',
|
'users',
|
||||||
array(
|
array(
|
||||||
'label' => t('Users'),
|
'label' => $this->translate('Users'),
|
||||||
'description' => t('Comma-separated list of users that are assigned to the role')
|
'description' => $this->translate('Comma-separated list of users that are assigned to the role')
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'textarea',
|
'textarea',
|
||||||
'groups',
|
'groups',
|
||||||
array(
|
array(
|
||||||
'label' => t('Groups'),
|
'label' => $this->translate('Groups'),
|
||||||
'description' => t('Comma-separated list of groups that are assigned to the role')
|
'description' => $this->translate('Comma-separated list of groups that are assigned to the role')
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'multiselect',
|
'multiselect',
|
||||||
'permissions',
|
'permissions',
|
||||||
array(
|
array(
|
||||||
'label' => t('Permissions Set'),
|
'label' => $this->translate('Permissions Set'),
|
||||||
'description' => t('The permissions to grant. You may select more than one permission'),
|
'description' => $this->translate(
|
||||||
|
'The permissions to grant. You may select more than one permission'
|
||||||
|
),
|
||||||
'multiOptions' => $this->providedPermissions
|
'multiOptions' => $this->providedPermissions
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
foreach ($this->providedRestrictions as $name => $description) {
|
foreach ($this->providedRestrictions as $name => $spec) {
|
||||||
$this->addElement(
|
$this->addElement(
|
||||||
'text',
|
'text',
|
||||||
$name,
|
$name,
|
||||||
array(
|
array(
|
||||||
'label' => $name,
|
'label' => $spec['name'],
|
||||||
'description' => $description
|
'description' => $spec['description']
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -120,7 +135,7 @@ class RoleForm extends ConfigForm
|
|||||||
}
|
}
|
||||||
if (! $this->config->hasSection($name)) {
|
if (! $this->config->hasSection($name)) {
|
||||||
throw new InvalidArgumentException(sprintf(
|
throw new InvalidArgumentException(sprintf(
|
||||||
t('Can\'t load role \'%s\'. Role does not exist'),
|
$this->translate('Can\'t load role \'%s\'. Role does not exist'),
|
||||||
$name
|
$name
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -129,6 +144,15 @@ class RoleForm extends ConfigForm
|
|||||||
? String::trimSplit($role['permissions'])
|
? String::trimSplit($role['permissions'])
|
||||||
: null;
|
: null;
|
||||||
$role['name'] = $name;
|
$role['name'] = $name;
|
||||||
|
$restrictions = array();
|
||||||
|
foreach ($this->providedRestrictions as $name => $spec) {
|
||||||
|
if (isset($role[$spec['name']])) {
|
||||||
|
// Translate restriction names to filtered element names
|
||||||
|
$restrictions[$name] = $role[$spec['name']];
|
||||||
|
unset($role[$spec['name']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$role = array_merge($role, $restrictions);
|
||||||
$this->populate($role);
|
$this->populate($role);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -152,7 +176,7 @@ class RoleForm extends ConfigForm
|
|||||||
}
|
}
|
||||||
if ($this->config->hasSection($name)) {
|
if ($this->config->hasSection($name)) {
|
||||||
throw new InvalidArgumentException(sprintf(
|
throw new InvalidArgumentException(sprintf(
|
||||||
t('Can\'t add role \'%s\'. Role already exists'),
|
$this->translate('Can\'t add role \'%s\'. Role already exists'),
|
||||||
$name
|
$name
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -178,7 +202,7 @@ class RoleForm extends ConfigForm
|
|||||||
}
|
}
|
||||||
if (! $this->config->hasSection($name)) {
|
if (! $this->config->hasSection($name)) {
|
||||||
throw new InvalidArgumentException(sprintf(
|
throw new InvalidArgumentException(sprintf(
|
||||||
t('Can\'t remove role \'%s\'. Role does not exist'),
|
$this->translate('Can\'t remove role \'%s\'. Role does not exist'),
|
||||||
$name
|
$name
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -211,7 +235,7 @@ class RoleForm extends ConfigForm
|
|||||||
} else {
|
} else {
|
||||||
if (! $this->config->hasSection($name)) {
|
if (! $this->config->hasSection($name)) {
|
||||||
throw new InvalidArgumentException(sprintf(
|
throw new InvalidArgumentException(sprintf(
|
||||||
t('Can\'t update role \'%s\'. Role does not exist'),
|
$this->translate('Can\'t update role \'%s\'. Role does not exist'),
|
||||||
$name
|
$name
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -230,6 +254,15 @@ class RoleForm extends ConfigForm
|
|||||||
if (isset($values['permissions'])) {
|
if (isset($values['permissions'])) {
|
||||||
$values['permissions'] = implode(', ', $values['permissions']);
|
$values['permissions'] = implode(', ', $values['permissions']);
|
||||||
}
|
}
|
||||||
|
$restrictions = array();
|
||||||
|
foreach ($this->providedRestrictions as $name => $spec) {
|
||||||
|
if (isset($values[$name])) {
|
||||||
|
// Translate filtered element names to restriction names
|
||||||
|
$restrictions[$spec['name']] = $values[$name];
|
||||||
|
unset($values[$name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$values = array_merge($values, $restrictions);
|
||||||
return $values;
|
return $values;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
use Icinga\Web\Url;
|
use Icinga\Web\Url;
|
||||||
use Icinga\Web\Menu;
|
use Icinga\Web\Menu;
|
||||||
use Icinga\Web\MenuRenderer;
|
use Icinga\Web\MenuRenderer;
|
||||||
use Icinga\Web\Widget\SearchDashboard;
|
|
||||||
|
|
||||||
// Don't render a menu for unauthenticated users unless menu is auth aware
|
// Don't render a menu for unauthenticated users unless menu is auth aware
|
||||||
if (! $this->auth()->isAuthenticated()) {
|
if (! $this->auth()->isAuthenticated()) {
|
||||||
@ -11,15 +10,16 @@ if (! $this->auth()->isAuthenticated()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<div
|
<div id="menu" data-last-update="<?= (time() - 14) ?>000" data-base-target="_main" class="container"
|
||||||
id="menu" data-last-update="<?= (time() - 14) ?>000" data-base-target="_main" class="container" data-icinga-url="<?=$this->href('layout/menu');?>"
|
data-icinga-url="<?= $this->href('layout/menu') ?>" data-icinga-refresh="15">
|
||||||
data-icinga-refresh="15"
|
<?= $this->partial(
|
||||||
>
|
'layout/menu.phtml',
|
||||||
<? if (SearchDashboard::search('dummy')->getPane('search')->hasDashlets()): ?>
|
'default',
|
||||||
<form action="<?= $this->href('search') ?>" method="get" role="search">
|
array(
|
||||||
<input type="text" name="q" class="search autofocus" placeholder="<?= $this->translate('Search...') ?>"
|
'menuRenderer' => new MenuRenderer(
|
||||||
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" />
|
Menu::load(),
|
||||||
</form>
|
Url::fromRequest()->without('renderLayout')->getRelativeUrl()
|
||||||
<? endif; ?>
|
)
|
||||||
<?= new MenuRenderer(Menu::load(), Url::fromRequest()->without('renderLayout')->getRelativeUrl()); ?>
|
)
|
||||||
|
) ?>
|
||||||
</div>
|
</div>
|
||||||
|
@ -57,7 +57,7 @@ class Zend_View_Helper_FormDateTime extends Zend_View_Helper_FormElement
|
|||||||
$type = $attribs['local'] === true ? 'datetime-local' : 'datetime';
|
$type = $attribs['local'] === true ? 'datetime-local' : 'datetime';
|
||||||
unset($attribs['local']); // Unset local to not render it again in $this->_htmlAttribs($attribs)
|
unset($attribs['local']); // Unset local to not render it again in $this->_htmlAttribs($attribs)
|
||||||
$html5 = sprintf(
|
$html5 = sprintf(
|
||||||
'<input type="%s" name="%s" id="%s" value="%s"%s%s%s%s%s',
|
'<input type="%s" name="%s" id="%s" step="1" value="%s"%s%s%s%s%s',
|
||||||
$type,
|
$type,
|
||||||
$this->view->escape($name),
|
$this->view->escape($name),
|
||||||
$this->view->escape($id),
|
$this->view->escape($id),
|
||||||
|
@ -1,11 +1,28 @@
|
|||||||
<div id="login">
|
<div id="login">
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<img class="fade-in one" src="<?= $this->baseUrl('img/logo_icinga_big.png') ?>" alt="<?= t('The Icinga logo') ?>" >
|
<img class="fade-in one" src="<?= $this->baseUrl('img/logo_icinga_big.png'); ?>" alt="<?= $this->translate('The Icinga logo'); ?>" >
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form" data-base-target="layout">
|
<div class="form" data-base-target="layout">
|
||||||
<h1>Welcome to Icinga Web 2</h1>
|
<?php if ($requiresSetup): ?>
|
||||||
|
<p class="config-note"><?= sprintf(
|
||||||
|
$this->translate(
|
||||||
|
'It appears that you did not configure Icinga Web 2 yet so it\'s not possible to log in without any defined '
|
||||||
|
. 'authentication method. Please define a authentication method by following the instructions in the'
|
||||||
|
. ' %1$sdocumentation%3$s or by using our %2$sweb-based setup-wizard%3$s.'
|
||||||
|
),
|
||||||
|
'<a href="http://docs.icinga.org/" title="' . $this->translate('Icinga Web 2 Documentation') . '">', // TODO: More exact documentation link..
|
||||||
|
'<a href="' . $this->href('setup') . '" title="' . $this->translate('Icinga Web 2 Setup-Wizard') . '">',
|
||||||
|
'</a>'
|
||||||
|
); ?></p>
|
||||||
|
<?php elseif ($requiresExternalAuth): ?>
|
||||||
|
<p class="info-box"><span class="icon-info"></span><?= $this->translate(
|
||||||
|
'You\'re currently not authenticated using any of the web server\'s authentication mechanisms.'
|
||||||
|
. ' Make sure you\'ll configure such, otherwise you\'ll not be able to login.'
|
||||||
|
); ?></p>
|
||||||
|
<?php endif ?>
|
||||||
|
<h1><?= $this->translate('Welcome to Icinga Web 2'); ?></h1>
|
||||||
<?php
|
<?php
|
||||||
/* TODO: remove this as soon as notifications and forms are ready */
|
/* TODO: remove this as soon as notifications and forms are ready */
|
||||||
if (isset($this->errorInfo)): ?>
|
if (isset($this->errorInfo)): ?>
|
||||||
@ -14,18 +31,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<?= $this->form ?>
|
<?= $this->form ?>
|
||||||
<div class="footer">Icinga Web 2 © 2013-2014<br><a href="https://www.icinga.org">The Icinga Project</a></div>
|
<div class="footer">Icinga Web 2 © 2013-2015<br><a href="https://www.icinga.org"><?= $this->translate('The Icinga Project'); ?></a></div>
|
||||||
<?php if ($configMissing): ?>
|
|
||||||
<div class="config-note"><?= sprintf(
|
|
||||||
t(
|
|
||||||
'You seem not to have Icinga Web 2 configured yet so it\'s not possible to log in without any defined '
|
|
||||||
. 'authentication method. Please define a authentication method by following the instructions in the'
|
|
||||||
. ' %1$sdocumentation%3$s or by using our %2$sweb-based setup-wizard%3$s.'
|
|
||||||
),
|
|
||||||
'<a href="http://docs.icinga.org/" title="Icinga Web 2 Documentation">', // TODO: Documentation link
|
|
||||||
'<a href="' . $this->href('setup') . '" title="Icinga Web 2 Setup-Wizard">',
|
|
||||||
'</a>'
|
|
||||||
); ?></div>
|
|
||||||
<?php endif ?>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="controls">
|
<div class="controls" data-base-target="_main">
|
||||||
<?= $tabs; ?>
|
<?= $tabs; ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="content" data-base-target="_next">
|
<div class="content" data-base-target="_next">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="controls">
|
<div class="controls" data-base-target="_main">
|
||||||
<?= $this->tabs->render($this); ?>
|
<?= $this->tabs->render($this); ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
<div class="controls">
|
|
||||||
<?= $this->tabs->render($this); ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content">
|
|
||||||
<?php $errors = $this->form->getErrorMessages(); ?>
|
|
||||||
|
|
||||||
<?php if (isset($this->messageBox)): ?>
|
|
||||||
<?= $this->messageBox->render() ?>
|
|
||||||
<?php endif ?>
|
|
||||||
|
|
||||||
<?php if ($this->successMessage): ?>
|
|
||||||
<div>
|
|
||||||
<i class="icinga-icon-success"></i>
|
|
||||||
<strong><?= $this->escape($this->successMessage); ?></strong>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if (!empty($errors)) : ?>
|
|
||||||
<div>
|
|
||||||
<h4>Errors occured when trying to save the project.</h4>
|
|
||||||
<p>
|
|
||||||
The following errors occured when trying to save the configuration:
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<?php foreach($errors as $error): ?>
|
|
||||||
<li><?= $this->escape($error) ?></li>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php endif; ?>
|
|
||||||
<?= $this->form ?>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
<div class="controls">
|
<div class="controls" data-base-target="_right">
|
||||||
<?= $this->tabs ?>
|
<?= $this->tabs ?>
|
||||||
<h1><?= $this->escape($module->getTitle()) ?></h1>
|
<h1><?= $this->escape($module->getTitle()) ?></h1>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="controls">
|
<div class="controls" data-base-target="_main">
|
||||||
<?= $tabs; ?>
|
<?= $tabs; ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="content" data-base-target="_next">
|
<div class="content" data-base-target="_next">
|
||||||
|
@ -5,7 +5,7 @@ use Icinga\Web\Widget\SearchDashboard;
|
|||||||
<? if (SearchDashboard::search('dummy')->getPane('search')->hasDashlets()): ?>
|
<? if (SearchDashboard::search('dummy')->getPane('search')->hasDashlets()): ?>
|
||||||
<form action="<?= $this->href('search') ?>" method="get" role="search">
|
<form action="<?= $this->href('search') ?>" method="get" role="search">
|
||||||
<input
|
<input
|
||||||
type="text" name="q" class="search autofocus" placeholder="<?= $this->translate('Search...') ?>"
|
type="text" name="q" class="search" placeholder="<?= $this->translate('Search...') ?>"
|
||||||
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="controls">
|
<div class="controls" data-base-target="_main">
|
||||||
<?= $tabs ?>
|
<?= $tabs ?>
|
||||||
<h1><?= $this->translate('Roles') ?></h1>
|
<h1><?= $this->translate('Roles') ?></h1>
|
||||||
</div>
|
</div>
|
||||||
@ -30,7 +30,7 @@
|
|||||||
<td>
|
<td>
|
||||||
<?php
|
<?php
|
||||||
// TODO(el): $role->without(...) or $role->shift(...) would be nice!
|
// TODO(el): $role->without(...) or $role->shift(...) would be nice!
|
||||||
$restrictions = $role;
|
$restrictions = clone $role;
|
||||||
unset($restrictions['users']);
|
unset($restrictions['users']);
|
||||||
unset($restrictions['groups']);
|
unset($restrictions['groups']);
|
||||||
unset($restrictions['permissions']);
|
unset($restrictions['permissions']);
|
||||||
|
@ -24,7 +24,7 @@ For delegating authentication to the web server simply add `autologin` to your a
|
|||||||
|
|
||||||
````
|
````
|
||||||
[autologin]
|
[autologin]
|
||||||
backend = autologin
|
backend = external
|
||||||
````
|
````
|
||||||
|
|
||||||
If your web server is not configured for authentication though the `autologin` section has no effect.
|
If your web server is not configured for authentication though the `autologin` section has no effect.
|
||||||
|
@ -1,90 +1,83 @@
|
|||||||
# Externel Authentication
|
# External Authentication
|
||||||
|
|
||||||
It is possible to use the authentication mechanism of the webserver,
|
It is possible to utilize the authentication mechanism of the webserver instead
|
||||||
instead of using the internal authentication-manager to
|
of the internal authentication of Icinga Web 2 to authenticate users. This might
|
||||||
authenticate users. This might be useful if you only have very few users, and
|
be useful if you only have very few users and user management over **.htaccess**
|
||||||
user management over *.htaccess* is sufficient, or if you must use some other
|
is not sufficient or if you are required to use some other authentication
|
||||||
authentication mechanism that is only available through your webserver.
|
mechanism that is only available by utilizing the webserver.
|
||||||
|
|
||||||
When external authentication is used, Icingaweb will entrust the
|
Icinga Web 2 will entrust the complete authentication process to the
|
||||||
complete authentication process to the external authentication provider (the webserver):
|
authentication provider of the webserver, if external authentication is used.
|
||||||
The provider should take care of authenticating the user and declining
|
So it is very important that the webserver's authentication is configured
|
||||||
all requests with invalid or missing credentials. When the authentication
|
correctly as wrong configuration might lead to unauthorized access or a
|
||||||
was succesful, it should provide the authenticated users name to its php-module
|
malfunction in the login-process.
|
||||||
and Icingaweb will assume that the user is authorized to access the page.
|
|
||||||
Because of this it is very important that the webservers authentication is
|
|
||||||
configured correctly, as wrong configuration could lead to unauthorized
|
|
||||||
access to the site, or a broken login-process.
|
|
||||||
|
|
||||||
|
## Using External Authentication
|
||||||
|
|
||||||
## Use External Authentication
|
External authentication in Icinga Web 2 requires the following preparations:
|
||||||
|
|
||||||
Using external authentication in Icingaweb requires two steps to work:
|
1. The external authentication must be set up properly to correctly
|
||||||
|
authenticate users
|
||||||
|
2. Icinga Web 2 must be configured to use external authentication
|
||||||
|
|
||||||
1. The external authentication must be set up correctly to always
|
### Preparing the External Authentication Provider
|
||||||
authenticate the users.
|
|
||||||
2. Icingaweb must be configured to use the external authentication.
|
|
||||||
|
|
||||||
|
This step depends heavily on the used webserver and authentication mechanism you
|
||||||
|
want to use. It is not possible to cover all possibillities and you should
|
||||||
|
probably read the documentation for your webserver to get detailed instructions
|
||||||
|
on how to set up authentication properly.
|
||||||
|
|
||||||
### Prepare the External Authentication Provider
|
In general you need to make sure that:
|
||||||
|
|
||||||
This step depends heavily on the used webserver and authentication
|
|
||||||
mechanism you want to use. It is not possible to cover all possibillities
|
|
||||||
and you should probably read the documentation for your webserver for
|
|
||||||
detailed instructions on how to set up authentication properly.
|
|
||||||
|
|
||||||
In general, you need to make sure that:
|
|
||||||
|
|
||||||
- All routes require authentication
|
|
||||||
- Only permitted users are allowed to authenticate
|
|
||||||
|
|
||||||
|
- All routes require authentication
|
||||||
|
- Only permitted users are allowed to authenticate
|
||||||
|
|
||||||
#### Example Configuration for Apache and HTTPDigestAuthentication
|
#### Example Configuration for Apache and HTTPDigestAuthentication
|
||||||
|
|
||||||
The following example will show how to enable external authentication in Apache using
|
The following example will show how to enable external authentication in Apache
|
||||||
*HTTP Digest Authentication*.
|
using *HTTP Digest Authentication*.
|
||||||
|
|
||||||
##### Create users
|
##### Creating users
|
||||||
|
|
||||||
To create users for a digest authentication we can use the tool *htdigest*.
|
To create users for digest authentication you can use the tool *htdigest*. In
|
||||||
We choose *.icingawebdigest* as a name for the created file, containing
|
this example **.icingawebdigest** is the name of the file containing the user
|
||||||
the user credentials.
|
credentials.
|
||||||
|
|
||||||
This command will create a new file with the user *jdoe*. *htdigest*
|
This command creates a new file with the user *jdoe*. *htdigest* will prompt
|
||||||
will prompt you for your password, after it has been executed. If you
|
you for a password. If you want to add more users to the file you need to omit
|
||||||
want to add more users to the file you need to ommit the *-c* parameter
|
the *-c* parameter in all following commands to not to overwrite the file.
|
||||||
in all further commands to avoInid the file to be overwritten.
|
|
||||||
|
|
||||||
|
````
|
||||||
|
sudo htdigest -c /etc/icingaweb2/.icingawebdigest "Icinga Web 2" jdoe
|
||||||
|
````
|
||||||
|
|
||||||
sudo htdigest -c /etc/httpd/conf.d/.icingawebdigest "Icingaweb 2" jdoe
|
##### Configuring the Webserver
|
||||||
|
|
||||||
|
The webserver should require authentication for all public Icinga Web 2 files.
|
||||||
|
|
||||||
##### Set up authentication
|
````
|
||||||
|
<Directory "/usr/share/icingaweb2/public">
|
||||||
|
AuthType digest
|
||||||
|
AuthName "Icinga Web 2"
|
||||||
|
AuthDigestProvider file
|
||||||
|
AuthUserFile /etc/icingaweb2/.icingawebdigest
|
||||||
|
Require valid-user
|
||||||
|
</Directory>
|
||||||
|
````
|
||||||
|
|
||||||
The webserver should require authentication for all public icingaweb files.
|
### Preparing Icinga Web 2
|
||||||
|
|
||||||
|
Once external authentication is set up correctly you need to configure Icinga
|
||||||
|
Web 2. In case you already completed the setup wizard it is likely that you are
|
||||||
|
now finished.
|
||||||
|
|
||||||
<Directory "/var/www/html/icingaweb">
|
To get Icinga Web 2 to use external authentication the file
|
||||||
AuthType digest
|
**config/authentication.ini** is required. Just add the following section
|
||||||
AuthName "Icingaweb 2"
|
called "autologin", or any name of your choice, and save your changes:
|
||||||
AuthDigestProvider file
|
|
||||||
AuthUserFile /etc/httpd/conf.d/.icingawebdigest
|
|
||||||
Require valid-user
|
|
||||||
</Directory>
|
|
||||||
|
|
||||||
|
````
|
||||||
### Prepare Icingaweb
|
[autologin]
|
||||||
|
backend = external
|
||||||
|
````
|
||||||
|
|
||||||
When the external authentication is set up correctly, we need
|
Congratulations! You are now logged in when visiting Icinga Web 2.
|
||||||
to configure IcingaWeb to use it as an authentication source. The
|
|
||||||
configuration key *authenticationMode* in the section *global* defines
|
|
||||||
if the authentication should be handled internally or externally. Since
|
|
||||||
we want to delegate the authentication to the Webserver we choose
|
|
||||||
"external" as the new value:
|
|
||||||
|
|
||||||
|
|
||||||
[global]
|
|
||||||
; ...
|
|
||||||
authenticationMode = "external"
|
|
||||||
; ...
|
|
||||||
|
|
@ -6,7 +6,7 @@ system and distribution you are running. But it is also possible to install Icin
|
|||||||
## <a id="installation-requirements"></a> Installing Requirements
|
## <a id="installation-requirements"></a> Installing Requirements
|
||||||
|
|
||||||
* A web server, e.g. Apache or nginx
|
* A web server, e.g. Apache or nginx
|
||||||
* PHP >= 5.3.0
|
* PHP >= 5.3.0 w/ gettext and OpenSSL support
|
||||||
* MySQL or PostgreSQL PHP libraries when using a database for authentication or storing user preferences into a database
|
* MySQL or PostgreSQL PHP libraries when using a database for authentication or storing user preferences into a database
|
||||||
* LDAP PHP library when using Active Directory or LDAP for authentication
|
* LDAP PHP library when using Active Directory or LDAP for authentication
|
||||||
* Icinga 1.x w/ Livestatus or IDO, Icinga 2 w/ Livestatus or IDO feature enabled
|
* Icinga 1.x w/ Livestatus or IDO, Icinga 2 w/ Livestatus or IDO feature enabled
|
||||||
@ -26,7 +26,7 @@ repository either via git or http protocol using the following URLs:
|
|||||||
* http://git.icinga.org/icingaweb2.git
|
* http://git.icinga.org/icingaweb2.git
|
||||||
|
|
||||||
There is also a browsable version available at
|
There is also a browsable version available at
|
||||||
[gi.icinga.org](https://git.icinga.org/?p=icingaweb2.git;a=summary "Icinga Web 2 Git Repository").
|
[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.
|
This version also offers snapshots for easy download which you can use if you do not have git present on your system.
|
||||||
|
|
||||||
````
|
````
|
||||||
@ -38,25 +38,73 @@ git clone git://git.icinga.org/icingaweb2.git
|
|||||||
Choose a target directory and move Icinga Web 2 there.
|
Choose a target directory and move Icinga Web 2 there.
|
||||||
|
|
||||||
````
|
````
|
||||||
mv icingaweb2 /usr/share/icingaweb
|
mv icingaweb2 /usr/share/icingaweb2
|
||||||
````
|
````
|
||||||
|
|
||||||
**Step 3: Configuring the Web Server**
|
**Step 3: Configuring the Web Server**
|
||||||
|
|
||||||
Use `icingacli` to generate web server configuration for either Apache or nginx.
|
Use `icingacli` to generate web server configuration for either Apache or nginx.
|
||||||
|
|
||||||
*Apache*
|
Apache:
|
||||||
|
|
||||||
````
|
````
|
||||||
./bin/icingacli setup config webserver apache --document-root /usr/share/icingaweb/public
|
./bin/icingacli setup config webserver apache --document-root /usr/share/icingaweb2/public
|
||||||
````
|
````
|
||||||
|
|
||||||
*nginx*
|
nginx:
|
||||||
|
|
||||||
````
|
````
|
||||||
./bin/icingacli setup config webserver nginx --document-root /usr/share/icingaweb/public
|
./bin/icingacli setup config webserver nginx --document-root /usr/share/icingaweb2/public
|
||||||
````
|
````
|
||||||
|
|
||||||
**Step 4: Web Setup**
|
**Step 4: Preparing Web Setup**
|
||||||
|
|
||||||
Visit Icinga Web 2 in your browser and complete installation using the web setup.
|
Because both web and CLI must have access to configuration and logs, permissions will be managed using a special
|
||||||
|
system group. The web server user and CLI user have to be added to this system group.
|
||||||
|
|
||||||
|
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`:
|
||||||
|
|
||||||
|
Fedora, RHEL and CentOS:
|
||||||
|
````
|
||||||
|
usermod -a -G icingaweb2 apache
|
||||||
|
````
|
||||||
|
|
||||||
|
SLES and OpenSUSE:
|
||||||
|
````
|
||||||
|
usermod -G icingaweb2 wwwrun
|
||||||
|
````
|
||||||
|
|
||||||
|
Debian and Ubuntu:
|
||||||
|
````
|
||||||
|
usermod -a -G icingaweb2 wwwrun
|
||||||
|
````
|
||||||
|
|
||||||
|
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
|
||||||
|
````
|
||||||
|
|
||||||
|
**Step 5: Web Setup**
|
||||||
|
|
||||||
|
Visit Icinga Web 2 in your browser and complete installation using the web setup: /icingaweb2/setup
|
||||||
|
52
doc/vagrant.md
Normal file
52
doc/vagrant.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Vagrant
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
* Vagrant >= version 1.5
|
||||||
|
* VirtualBox or Parallels
|
||||||
|
|
||||||
|
> **Note:** The deployment of the virtual machine is tested against Vagrant starting with version 1.5.
|
||||||
|
> Unfortunately older versions will not work.
|
||||||
|
|
||||||
|
## General
|
||||||
|
|
||||||
|
The Icinga Web 2 project ships with a Vagrant virtual machine that integrates
|
||||||
|
the source code with various services and example data in a controlled
|
||||||
|
environment. This enables developers and users to test Livestatus,
|
||||||
|
MySQL and PostgreSQL backends as well as the LDAP authentication. All you
|
||||||
|
have to do is install Vagrant and run:
|
||||||
|
|
||||||
|
````
|
||||||
|
vagrant up
|
||||||
|
````
|
||||||
|
|
||||||
|
> **Note:** The first boot of the vm takes a fairly long time because
|
||||||
|
> you'll download a plain CentOS base box and Vagrant will automatically
|
||||||
|
> provision the environment on the first go.
|
||||||
|
|
||||||
|
After you should be able to browse [localhost:8080/icingaweb2](http://localhost:8080/icingaweb2).
|
||||||
|
|
||||||
|
## Log into Icinga Web 2
|
||||||
|
|
||||||
|
Both LDAP and a MySQL are configured as authentication backend. Please use one of the following login credentials:
|
||||||
|
|
||||||
|
> LDAP:
|
||||||
|
>> **Username**: `jdoe`
|
||||||
|
|
||||||
|
>> **Password**: `password`
|
||||||
|
|
||||||
|
>MySQL:
|
||||||
|
>> **Username**: `icingaadmin`
|
||||||
|
|
||||||
|
>> **Password**: `icinga`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Testing the Source Code
|
||||||
|
|
||||||
|
All software required to run tests is installed in the virtual machine.
|
||||||
|
In order to run all tests you have to execute the following command:
|
||||||
|
|
||||||
|
````
|
||||||
|
vagrant ssh -c "icingacli test php unit"
|
||||||
|
````
|
428
icingaweb2.spec
428
icingaweb2.spec
@ -1,237 +1,271 @@
|
|||||||
#/**
|
%define revision 1.beta2
|
||||||
# * This file is part of Icinga Web 2.
|
|
||||||
# *
|
|
||||||
# * Icinga Web 2 - Head for multiple monitoring backends.
|
|
||||||
# * Copyright (C) 2014 Icinga Development Team
|
|
||||||
# *
|
|
||||||
# * This program is free software; you can redistribute it and/or
|
|
||||||
# * modify it under the terms of the GNU General Public License
|
|
||||||
# * as published by the Free Software Foundation; either version 2
|
|
||||||
# * of the License, or (at your option) any later version.
|
|
||||||
# *
|
|
||||||
# * This program is distributed in the hope that it will be useful,
|
|
||||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# * GNU General Public License for more details.
|
|
||||||
# *
|
|
||||||
# * You should have received a copy of the GNU General Public License
|
|
||||||
# * along with this program; if not, write to the Free Software
|
|
||||||
# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
# *
|
|
||||||
# * @copyright 2014 Icinga Development Team <info@icinga.org>
|
|
||||||
# * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
|
||||||
# * @author Icinga Development Team <info@icinga.org>
|
|
||||||
# *
|
|
||||||
# */
|
|
||||||
|
|
||||||
%define revision 1
|
|
||||||
|
|
||||||
%define configdir %{_sysconfdir}/%{name}
|
|
||||||
%define sharedir %{_datadir}/%{name}
|
|
||||||
%define prefixdir %{_datadir}/%{name}
|
|
||||||
%define usermodparam -a -G
|
|
||||||
%define logdir %{_localstatedir}/log/%{name}
|
|
||||||
%define docdir %{sharedir}/doc
|
|
||||||
|
|
||||||
%if "%{_vendor}" == "suse"
|
|
||||||
%define phpname php5
|
|
||||||
%define phpzendname php5-ZendFramework
|
|
||||||
%define apache2modphpname apache2-mod_php5
|
|
||||||
%endif
|
|
||||||
# SLE 11 = 1110
|
|
||||||
%if 0%{?suse_version} == 1110
|
|
||||||
%define phpname php53
|
|
||||||
%define apache2modphpname apache2-mod_php53
|
|
||||||
%define usermodparam -A
|
|
||||||
%endif
|
|
||||||
|
|
||||||
%if "%{_vendor}" == "redhat"
|
|
||||||
%define phpname php
|
|
||||||
%define phpzendname php-ZendFramework
|
|
||||||
%endif
|
|
||||||
|
|
||||||
# el5 requires newer php53 rather than php (5.1)
|
|
||||||
%if 0%{?el5} || 0%{?rhel} == 5 || "%{?dist}" == ".el5"
|
|
||||||
%define phpname php53
|
|
||||||
%endif
|
|
||||||
|
|
||||||
%if "%{_vendor}" == "suse"
|
|
||||||
%define apacheconfdir %{_sysconfdir}/apache2/conf.d
|
|
||||||
%define apacheuser wwwrun
|
|
||||||
%define apachegroup www
|
|
||||||
%define extcmdfile %{_localstatedir}/run/icinga2/cmd/icinga.cmd
|
|
||||||
%define livestatussocket %{_localstatedir}/run/icinga2/cmd/livestatus
|
|
||||||
%endif
|
|
||||||
%if "%{_vendor}" == "redhat"
|
|
||||||
%define apacheconfdir %{_sysconfdir}/httpd/conf.d
|
|
||||||
%define apacheuser apache
|
|
||||||
%define apachegroup apache
|
|
||||||
%define extcmdfile %{_localstatedir}/run/icinga2/cmd/icinga.cmd
|
|
||||||
%define livestatussocket %{_localstatedir}/run/icinga2/cmd/livestatus
|
|
||||||
%endif
|
|
||||||
|
|
||||||
Summary: Open Source host, service and network monitoring Web UI
|
|
||||||
Name: icingaweb2
|
Name: icingaweb2
|
||||||
Version: 0.0.1
|
Version: 2.0.0
|
||||||
Release: %{revision}%{?dist}
|
Release: %{revision}%{?dist}
|
||||||
License: GPLv2
|
Summary: Icinga Web 2
|
||||||
Group: Applications/System
|
Group: Applications/System
|
||||||
URL: http://www.icinga.org
|
License: GPL
|
||||||
|
URL: https://icinga.org
|
||||||
|
Source0: https://github.com/Icinga/%{name}/archive/v%{version}.tar.gz
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
|
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}
|
||||||
|
Packager: Icinga Team <info@icinga.org>
|
||||||
|
|
||||||
%if "%{_vendor}" == "suse"
|
%if 0%{?fedora} || 0%{?rhel}
|
||||||
AutoReqProv: Off
|
%define wwwconfigdir %{_sysconfdir}/httpd/conf.d
|
||||||
|
%define wwwuser apache
|
||||||
|
%if 0%{?rhel} == 5
|
||||||
|
%define php php53
|
||||||
|
%define php_cli php53-cli
|
||||||
|
%else
|
||||||
|
%define php php
|
||||||
|
%define php_cli php-cli
|
||||||
|
%endif
|
||||||
|
%if 0%{?rhel} == 6
|
||||||
|
%define zend php-ZendFramework
|
||||||
|
%else
|
||||||
|
%define zend %{name}-vendor-Zend
|
||||||
|
%endif
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
Source: icingaweb2-%{version}.tar.gz
|
|
||||||
|
|
||||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
%if 0%{?suse_version}
|
||||||
|
%define wwwconfigdir %{_sysconfdir}/apache2/conf.d
|
||||||
BuildRequires: %{phpname} >= 5.3.0
|
%define wwwuser wwwrun
|
||||||
BuildRequires: %{phpname}-devel >= 5.3.0
|
%define zend php5-ZendFramework
|
||||||
BuildRequires: %{phpname}-ldap
|
%if 0%{?suse_version} == 1110
|
||||||
BuildRequires: %{phpname}-pdo
|
%define php php53
|
||||||
BuildRequires: %{phpzendname}
|
Requires: apache2-mod_php53
|
||||||
%if "%{_vendor}" != "suse"
|
%else
|
||||||
BuildRequires: %{phpzendname}-Db-Adapter-Pdo
|
%define php php5
|
||||||
BuildRequires: %{phpzendname}-Db-Adapter-Pdo-Mysql
|
Requires: apache2-mod_php5
|
||||||
BuildRequires: %{phpzendname}-Db-Adapter-Pdo-Pgsql
|
%endif
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%if "%{_vendor}" == "redhat"
|
Requires(pre): shadow-utils
|
||||||
%endif
|
Requires: %{name}-common = %{version}-%{release}
|
||||||
%if "%{_vendor}" == "suse"
|
Requires: php-Icinga = %{version}-%{release}
|
||||||
Requires: %{phpname}-devel >= 5.3.0
|
Requires: %{name}-vendor-dompdf
|
||||||
BuildRequires: %{phpname}-json
|
Requires: %{name}-vendor-HTMLPurifier
|
||||||
BuildRequires: %{phpname}-sockets
|
Requires: %{name}-vendor-JShrink
|
||||||
BuildRequires: %{phpname}-dom
|
Requires: %{name}-vendor-lessphp
|
||||||
%endif
|
Requires: %{name}-vendor-Parsedown
|
||||||
|
Requires: %{zend}
|
||||||
Requires: %{phpname} >= 5.3.0
|
|
||||||
Requires: %{phpzendname}
|
|
||||||
Requires: %{phpname}-ldap
|
|
||||||
Requires: %{phpname}-pdo
|
|
||||||
%if "%{_vendor}" == "redhat"
|
|
||||||
Requires: %{phpname}-common
|
|
||||||
Requires: %{phpzendname}-Db-Adapter-Pdo
|
|
||||||
Requires: %{phpzendname}-Db-Adapter-Pdo-Mysql
|
|
||||||
Requires: php-pear
|
|
||||||
%endif
|
|
||||||
%if "%{_vendor}" == "suse"
|
|
||||||
Requires: %{phpname}-pear
|
|
||||||
Requires: %{phpname}-dom
|
|
||||||
Requires: %{phpname}-tokenizer
|
|
||||||
Requires: %{phpname}-gettext
|
|
||||||
Requires: %{phpname}-ctype
|
|
||||||
Requires: %{phpname}-json
|
|
||||||
Requires: %{apache2modphpname}
|
|
||||||
%endif
|
|
||||||
|
|
||||||
Requires: php-Icinga
|
|
||||||
|
|
||||||
|
|
||||||
%description
|
%description
|
||||||
Icinga Web 2 for Icinga 2 or Icinga 1.x using multiple backends
|
Icinga Web 2
|
||||||
for example DB IDO.
|
|
||||||
|
|
||||||
%package -n icingacli
|
|
||||||
Summary: Icinga CLI
|
|
||||||
Group: Applications/System
|
|
||||||
Requires: %{name} = %{version}-%{release}
|
|
||||||
Requires: php-Icinga
|
|
||||||
|
|
||||||
%description -n icingacli
|
%define basedir %{_datadir}/%{name}
|
||||||
Icinga CLI using php-Icinga Icinga Web 2 backend.
|
%define bindir %{_bindir}
|
||||||
|
%define configdir %{_sysconfdir}/%{name}
|
||||||
|
%define logdir %{_localstatedir}/log/%{name}
|
||||||
|
%define phpdir %{_datadir}/php
|
||||||
|
%define icingawebgroup icingaweb2
|
||||||
|
%define docsdir %{_datadir}/doc/%{name}
|
||||||
|
|
||||||
|
|
||||||
|
%package common
|
||||||
|
Summary: Common files for Icinga Web 2 and the Icinga CLI
|
||||||
|
Group: Applications/System
|
||||||
|
|
||||||
|
%description common
|
||||||
|
Common files for Icinga Web 2 and the Icinga CLI
|
||||||
|
|
||||||
|
|
||||||
%package -n php-Icinga
|
%package -n php-Icinga
|
||||||
Summary: Icinga Web 2 PHP Libraries
|
Summary: Icinga Web 2 PHP library
|
||||||
Group: Applications/System
|
Group: Development/Libraries
|
||||||
Requires: %{name} = %{version}-%{release}
|
Requires: %{php} >= 5.3.0
|
||||||
Requires: %{phpname} >= 5.3.0
|
Requires: %{php}-gd %{php}-intl
|
||||||
Requires: %{phpzendname}
|
%{?fedora:Requires: php-pecl-imagick}
|
||||||
|
%{?rhel:Requires: php-pecl-imagick}
|
||||||
|
%{?suse_version:Requires: %{php}-gettext %{php}-openssl php5-imagick}
|
||||||
|
|
||||||
%description -n php-Icinga
|
%description -n php-Icinga
|
||||||
Icinga Web 2 PHP Libraries required by the web frontend and cli tool.
|
Icinga Web 2 PHP library
|
||||||
|
|
||||||
|
|
||||||
|
%package -n icingacli
|
||||||
|
Summary: Icinga CLI
|
||||||
|
Group: Applications/System
|
||||||
|
Requires: %{name}-common = %{version}-%{release}
|
||||||
|
Requires: php-Icinga = %{version}-%{release}
|
||||||
|
%{?fedora:Requires: %{php_cli} >= 5.3.0 bash-completion}
|
||||||
|
%{?rhel:Requires: %{php_cli} >= 5.3.0 bash-completion}
|
||||||
|
%{?suse_version:Requires: %{php} >= 5.3.0}
|
||||||
|
|
||||||
|
%description -n icingacli
|
||||||
|
Icinga CLI
|
||||||
|
|
||||||
|
|
||||||
|
%package vendor-dompdf
|
||||||
|
Version: 0.6.1
|
||||||
|
Release: 1%{?dist}
|
||||||
|
Summary: Icinga Web 2 vendor library dompdf
|
||||||
|
Group: Development/Libraries
|
||||||
|
Requires: %{php} >= 5.3.0
|
||||||
|
|
||||||
|
%description vendor-dompdf
|
||||||
|
Icinga Web 2 vendor library dompdf
|
||||||
|
|
||||||
|
|
||||||
|
%package vendor-HTMLPurifier
|
||||||
|
Version: 4.6.0
|
||||||
|
Release: 1%{?dist}
|
||||||
|
Summary: Icinga Web 2 vendor library HTMLPurifier
|
||||||
|
Group: Development/Libraries
|
||||||
|
Requires: %{php} >= 5.3.0
|
||||||
|
|
||||||
|
%description vendor-HTMLPurifier
|
||||||
|
Icinga Web 2 vendor library HTMLPurifier
|
||||||
|
|
||||||
|
|
||||||
|
%package vendor-JShrink
|
||||||
|
Version: 1.0.1
|
||||||
|
Release: 1%{?dist}
|
||||||
|
Summary: Icinga Web 2 vendor library JShrink
|
||||||
|
Group: Development/Libraries
|
||||||
|
Requires: %{php} >= 5.3.0
|
||||||
|
|
||||||
|
%description vendor-JShrink
|
||||||
|
Icinga Web 2 vendor library JShrink
|
||||||
|
|
||||||
|
|
||||||
|
%package vendor-lessphp
|
||||||
|
Version: 0.4.0
|
||||||
|
Release: 1%{?dist}
|
||||||
|
Summary: Icinga Web 2 vendor library lessphp
|
||||||
|
Group: Development/Libraries
|
||||||
|
Requires: %{php} >= 5.3.0
|
||||||
|
|
||||||
|
%description vendor-lessphp
|
||||||
|
Icinga Web 2 vendor library lessphp
|
||||||
|
|
||||||
|
|
||||||
|
%package vendor-Parsedown
|
||||||
|
Version: 1.0.0
|
||||||
|
Release: 1%{?dist}
|
||||||
|
Summary: Icinga Web 2 vendor library Parsedown
|
||||||
|
Group: Development/Libraries
|
||||||
|
Requires: %{php} >= 5.3.0
|
||||||
|
|
||||||
|
%description vendor-Parsedown
|
||||||
|
Icinga Web 2 vendor library Parsedown
|
||||||
|
|
||||||
|
|
||||||
|
%package vendor-Zend
|
||||||
|
Version: 1.12.9
|
||||||
|
Release: 1%{?dist}
|
||||||
|
Summary: Icinga Web 2 vendor library Zend Framework
|
||||||
|
Group: Development/Libraries
|
||||||
|
Requires: %{php} >= 5.3.0
|
||||||
|
|
||||||
|
%description vendor-Zend
|
||||||
|
Icinga Web 2 vendor library Zend
|
||||||
|
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
#VERSION=0.0.1; git archive --format=tar --prefix=icingaweb2-$VERSION/ HEAD | gzip >icingaweb2-$VERSION.tar.gz
|
%setup -q
|
||||||
%setup -q -n %{name}-%{version}
|
|
||||||
|
|
||||||
%build
|
%build
|
||||||
|
|
||||||
%install
|
%install
|
||||||
[ "%{buildroot}" != "/" ] && [ -d "%{buildroot}" ] && rm -rf %{buildroot}
|
rm -rf %{buildroot}
|
||||||
|
mkdir -p %{buildroot}/{%{basedir}/{modules,library,public},%{bindir},%{configdir}/modules/setup,%{logdir},%{phpdir},%{wwwconfigdir},%{_sysconfdir}/bash_completion.d,%{docsdir}}
|
||||||
# prepare configuration for sub packages
|
cp -prv application doc %{buildroot}/%{basedir}
|
||||||
|
cp -pv etc/bash_completion.d/icingacli %{buildroot}/%{_sysconfdir}/bash_completion.d/icingacli
|
||||||
# install rhel apache config
|
cp -prv modules/{monitoring,setup} %{buildroot}/%{basedir}/modules
|
||||||
install -D -m0644 packages/files/apache/icingaweb.conf %{buildroot}/%{apacheconfdir}/icingaweb.conf
|
cp -prv library/Icinga %{buildroot}/%{phpdir}
|
||||||
|
cp -prv library/vendor %{buildroot}/%{basedir}/library
|
||||||
# install public, library, modules
|
cp -prv public/{css,img,js,error_norewrite.html} %{buildroot}/%{basedir}/public
|
||||||
%{__mkdir} -p %{buildroot}/%{sharedir}
|
cp -pv packages/files/apache/icingaweb2.conf %{buildroot}/%{wwwconfigdir}/icingaweb2.conf
|
||||||
%{__mkdir} -p %{buildroot}/%{logdir}
|
cp -pv packages/files/bin/icingacli %{buildroot}/%{bindir}
|
||||||
%{__mkdir} -p %{buildroot}/%{docdir}
|
cp -pv packages/files/public/index.php %{buildroot}/%{basedir}/public
|
||||||
%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name}
|
cp -prv etc/schema %{buildroot}/%{docsdir}
|
||||||
%{__mkdir} -p %{buildroot}/%{_sysconfdir}/dashboard
|
cp -prv packages/files/config/modules/setup %{buildroot}/%{configdir}/modules/
|
||||||
%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name}/modules
|
|
||||||
%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name}/modules/monitoring
|
|
||||||
%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name}/enabledModules
|
|
||||||
|
|
||||||
# make sure to install local icingacli for setup wizard token generation & webserver config
|
|
||||||
%{__cp} -r application doc library modules public bin %{buildroot}/%{sharedir}/
|
|
||||||
|
|
||||||
# enable the monitoring module by default
|
|
||||||
ln -s %{sharedir}/modules/monitoring %{buildroot}/%{_sysconfdir}/%{name}/enabledModules/monitoring
|
|
||||||
## config
|
|
||||||
|
|
||||||
# symlink icingacli
|
|
||||||
mkdir -p %{buildroot}/usr/bin
|
|
||||||
ln -sf %{sharedir}/bin/icingacli %{buildroot}/usr/bin/icingacli
|
|
||||||
|
|
||||||
%pre
|
%pre
|
||||||
# Add apacheuser in the icingacmd group
|
getent group icingacmd >/dev/null || groupadd -r icingacmd
|
||||||
# If the group exists, add the apacheuser in the icingacmd group.
|
%if 0%{?suse_version}
|
||||||
# It is not neccessary that icinga2-web is installed on the same system as
|
usermod -G icingacmd,%{icingawebgroup} %{wwwuser}
|
||||||
# icinga and only on systems with icinga installed the icingacmd
|
%else
|
||||||
# group exists. In all other cases the user used for ssh access has
|
usermod -a -G icingacmd,%{icingawebgroup} %{wwwuser}
|
||||||
# to be added to the icingacmd group on the remote icinga server.
|
%endif
|
||||||
getent group icingacmd > /dev/null
|
exit 0
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
%{_sbindir}/usermod %{usermodparam} icingacmd %{apacheuser}
|
|
||||||
fi
|
|
||||||
|
|
||||||
%preun
|
|
||||||
|
|
||||||
%post
|
|
||||||
|
|
||||||
%clean
|
%clean
|
||||||
[ "%{buildroot}" != "/" ] && [ -d "%{buildroot}" ] && rm -rf %{buildroot}
|
rm -rf %{buildroot}
|
||||||
|
|
||||||
%files
|
%files
|
||||||
# main dirs
|
|
||||||
%defattr(-,root,root)
|
%defattr(-,root,root)
|
||||||
%doc etc/schema doc packages/RPM.md
|
%{basedir}/application/controllers
|
||||||
%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/public
|
%{basedir}/application/fonts
|
||||||
%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/modules
|
%{basedir}/application/forms
|
||||||
# configs
|
%{basedir}/application/layouts
|
||||||
|
%{basedir}/application/views
|
||||||
|
%{basedir}/doc
|
||||||
|
%{basedir}/modules
|
||||||
|
%{basedir}/public
|
||||||
|
%{wwwconfigdir}/icingaweb2.conf
|
||||||
|
%attr(2775,root,%{icingawebgroup}) %dir %{logdir}
|
||||||
|
%{docsdir}
|
||||||
|
%docdir %{docsdir}
|
||||||
|
%attr(2770,root,%{icingawebgroup}) %config(noreplace) %dir %{configdir}/modules/setup
|
||||||
|
%attr(0660,root,%{icingawebgroup}) %config(noreplace) %{configdir}/modules/setup/config.ini
|
||||||
|
|
||||||
|
|
||||||
|
%pre common
|
||||||
|
getent group %{icingawebgroup} >/dev/null || groupadd -r %{icingawebgroup}
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
%files common
|
||||||
%defattr(-,root,root)
|
%defattr(-,root,root)
|
||||||
%config(noreplace) %attr(-,root,root) %{apacheconfdir}/icingaweb.conf
|
%{basedir}/application/locale
|
||||||
%config(noreplace) %attr(-,%{apacheuser},%{apachegroup}) %{configdir}
|
%dir %{basedir}/modules
|
||||||
# logs
|
%attr(2770,root,%{icingawebgroup}) %config(noreplace) %dir %{configdir}
|
||||||
%attr(2775,%{apacheuser},%{apachegroup}) %dir %{logdir}
|
%attr(2770,root,%{icingawebgroup}) %config(noreplace) %dir %{configdir}/modules
|
||||||
# shipped docs
|
|
||||||
%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/doc
|
|
||||||
|
|
||||||
%files -n php-Icinga
|
%files -n php-Icinga
|
||||||
%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/application
|
%defattr(-,root,root)
|
||||||
%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/library
|
%{phpdir}/Icinga
|
||||||
|
|
||||||
|
|
||||||
%files -n icingacli
|
%files -n icingacli
|
||||||
%attr(0755,root,root) /usr/bin/icingacli
|
%defattr(-,root,root)
|
||||||
%attr(0755,root,root) %{sharedir}/bin/icingacli
|
%{basedir}/application/clicommands
|
||||||
%attr(0755,root,root) %{sharedir}/bin/license_writer.py
|
%{_sysconfdir}/bash_completion.d/icingacli
|
||||||
|
%attr(0755,root,root) %{bindir}/icingacli
|
||||||
|
|
||||||
%changelog
|
|
||||||
|
%files vendor-dompdf
|
||||||
|
%defattr(-,root,root)
|
||||||
|
%{basedir}/library/vendor/dompdf
|
||||||
|
|
||||||
|
|
||||||
|
%files vendor-HTMLPurifier
|
||||||
|
%defattr(-,root,root)
|
||||||
|
%{basedir}/library/vendor/HTMLPurifier
|
||||||
|
|
||||||
|
|
||||||
|
%files vendor-JShrink
|
||||||
|
%defattr(-,root,root)
|
||||||
|
%{basedir}/library/vendor/JShrink
|
||||||
|
|
||||||
|
|
||||||
|
%files vendor-lessphp
|
||||||
|
%defattr(-,root,root)
|
||||||
|
%{basedir}/library/vendor/lessphp
|
||||||
|
|
||||||
|
|
||||||
|
%files vendor-Parsedown
|
||||||
|
%defattr(-,root,root)
|
||||||
|
%{basedir}/library/vendor/Parsedown
|
||||||
|
|
||||||
|
|
||||||
|
%files vendor-Zend
|
||||||
|
%defattr(-,root,root)
|
||||||
|
%{basedir}/library/vendor/Zend
|
||||||
|
@ -113,6 +113,13 @@ abstract class ApplicationBootstrap
|
|||||||
*/
|
*/
|
||||||
protected $isWeb = false;
|
protected $isWeb = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether Icinga Web 2 requires setup
|
||||||
|
*
|
||||||
|
* @type bool
|
||||||
|
*/
|
||||||
|
protected $requiresSetup = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
@ -133,7 +140,7 @@ abstract class ApplicationBootstrap
|
|||||||
if (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) {
|
if (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) {
|
||||||
$configDir = $_SERVER['ICINGAWEB_CONFIGDIR'];
|
$configDir = $_SERVER['ICINGAWEB_CONFIGDIR'];
|
||||||
} else {
|
} else {
|
||||||
$configDir = '/etc/icingaweb';
|
$configDir = '/etc/icingaweb2';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$canonical = realpath($configDir);
|
$canonical = realpath($configDir);
|
||||||
@ -333,7 +340,7 @@ abstract class ApplicationBootstrap
|
|||||||
/**
|
/**
|
||||||
* Setup Icinga auto loader
|
* Setup Icinga auto loader
|
||||||
*
|
*
|
||||||
* @return self
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setupAutoloader()
|
public function setupAutoloader()
|
||||||
{
|
{
|
||||||
@ -366,7 +373,7 @@ abstract class ApplicationBootstrap
|
|||||||
/**
|
/**
|
||||||
* Setup module manager
|
* Setup module manager
|
||||||
*
|
*
|
||||||
* @return self
|
* @return $this
|
||||||
*/
|
*/
|
||||||
protected function setupModuleManager()
|
protected function setupModuleManager()
|
||||||
{
|
{
|
||||||
@ -378,25 +385,10 @@ abstract class ApplicationBootstrap
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Load all core modules
|
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
protected function loadCoreModules()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$this->moduleManager->loadCoreModules();
|
|
||||||
} catch (NotReadableError $e) {
|
|
||||||
Logger::error(new IcingaException('Cannot load core modules. An exception was thrown:', $e));
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load all enabled modules
|
* Load all enabled modules
|
||||||
*
|
*
|
||||||
* @return self
|
* @return $this
|
||||||
*/
|
*/
|
||||||
protected function loadEnabledModules()
|
protected function loadEnabledModules()
|
||||||
{
|
{
|
||||||
@ -408,10 +400,47 @@ abstract class ApplicationBootstrap
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the setup module if Icinga Web 2 requires setup or the setup token exists
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
protected function loadSetupModuleIfNecessary()
|
||||||
|
{
|
||||||
|
if (! @file_exists($this->config->resolvePath('authentication.ini'))) {
|
||||||
|
$this->requiresSetup = true;
|
||||||
|
$this->moduleManager->loadModule('setup');
|
||||||
|
} elseif ($this->setupTokenExists()) {
|
||||||
|
// Load setup module but do not require setup
|
||||||
|
$this->moduleManager->loadModule('setup');
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether Icinga Web 2 requires setup
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function requiresSetup()
|
||||||
|
{
|
||||||
|
return $this->requiresSetup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether the setup token exists
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function setupTokenExists()
|
||||||
|
{
|
||||||
|
return @file_exists($this->config->resolvePath('setup.token'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup default logging
|
* Setup default logging
|
||||||
*
|
*
|
||||||
* @return self
|
* @return $this
|
||||||
*/
|
*/
|
||||||
protected function setupLogging()
|
protected function setupLogging()
|
||||||
{
|
{
|
||||||
@ -428,7 +457,7 @@ abstract class ApplicationBootstrap
|
|||||||
/**
|
/**
|
||||||
* Load Configuration
|
* Load Configuration
|
||||||
*
|
*
|
||||||
* @return self
|
* @return $this
|
||||||
*/
|
*/
|
||||||
protected function loadConfig()
|
protected function loadConfig()
|
||||||
{
|
{
|
||||||
@ -447,7 +476,7 @@ abstract class ApplicationBootstrap
|
|||||||
/**
|
/**
|
||||||
* Error handling configuration
|
* Error handling configuration
|
||||||
*
|
*
|
||||||
* @return self
|
* @return $this
|
||||||
*/
|
*/
|
||||||
protected function setupErrorHandling()
|
protected function setupErrorHandling()
|
||||||
{
|
{
|
||||||
@ -473,7 +502,7 @@ abstract class ApplicationBootstrap
|
|||||||
/**
|
/**
|
||||||
* Set up logger
|
* Set up logger
|
||||||
*
|
*
|
||||||
* @return self
|
* @return $this
|
||||||
*/
|
*/
|
||||||
protected function setupLogger()
|
protected function setupLogger()
|
||||||
{
|
{
|
||||||
@ -490,7 +519,7 @@ abstract class ApplicationBootstrap
|
|||||||
/**
|
/**
|
||||||
* Set up the resource factory
|
* Set up the resource factory
|
||||||
*
|
*
|
||||||
* @return self
|
* @return $this
|
||||||
*/
|
*/
|
||||||
protected function setupResourceFactory()
|
protected function setupResourceFactory()
|
||||||
{
|
{
|
||||||
|
@ -44,7 +44,7 @@ class Cli extends ApplicationBootstrap
|
|||||||
->setupLogger()
|
->setupLogger()
|
||||||
->setupResourceFactory()
|
->setupResourceFactory()
|
||||||
->setupModuleManager()
|
->setupModuleManager()
|
||||||
->loadCoreModules();
|
->loadSetupModuleIfNecessary();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function setupLogging()
|
protected function setupLogging()
|
||||||
|
@ -279,7 +279,7 @@ class Config implements Countable, Iterator
|
|||||||
*
|
*
|
||||||
* @param string $file The file to parse
|
* @param string $file The file to parse
|
||||||
*
|
*
|
||||||
* @throws NotReadableError When the file does not exist or cannot be read
|
* @throws NotReadableError When the file cannot be read
|
||||||
*/
|
*/
|
||||||
public static function fromIni($file)
|
public static function fromIni($file)
|
||||||
{
|
{
|
||||||
@ -292,7 +292,7 @@ class Config implements Countable, Iterator
|
|||||||
$config = new static(new ConfigObject(parse_ini_file($filepath, true)));
|
$config = new static(new ConfigObject(parse_ini_file($filepath, true)));
|
||||||
$config->setConfigFile($filepath);
|
$config->setConfigFile($filepath);
|
||||||
return $config;
|
return $config;
|
||||||
} else {
|
} elseif (@file_exists($filepath)) {
|
||||||
throw new NotReadableError(t('Cannot read config file "%s". Permission denied'), $filepath);
|
throw new NotReadableError(t('Cannot read config file "%s". Permission denied'), $filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,7 +322,7 @@ class Config implements Countable, Iterator
|
|||||||
*/
|
*/
|
||||||
public static function app($configname = 'config', $fromDisk = false)
|
public static function app($configname = 'config', $fromDisk = false)
|
||||||
{
|
{
|
||||||
if (!isset(self::$app[$configname]) || $fromDisk) {
|
if (! isset(self::$app[$configname]) || $fromDisk) {
|
||||||
self::$app[$configname] = static::fromIni(static::resolvePath($configname . '.ini'));
|
self::$app[$configname] = static::fromIni(static::resolvePath($configname . '.ini'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,12 +341,12 @@ class Config implements Countable, Iterator
|
|||||||
*/
|
*/
|
||||||
public static function module($modulename, $configname = 'config', $fromDisk = false)
|
public static function module($modulename, $configname = 'config', $fromDisk = false)
|
||||||
{
|
{
|
||||||
if (!isset(self::$modules[$modulename])) {
|
if (! isset(self::$modules[$modulename])) {
|
||||||
self::$modules[$modulename] = array();
|
self::$modules[$modulename] = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$moduleConfigs = self::$modules[$modulename];
|
$moduleConfigs = self::$modules[$modulename];
|
||||||
if (!isset($moduleConfigs[$configname]) || $fromDisk) {
|
if (! isset($moduleConfigs[$configname]) || $fromDisk) {
|
||||||
$moduleConfigs[$configname] = static::fromIni(
|
$moduleConfigs[$configname] = static::fromIni(
|
||||||
static::resolvePath('modules/' . $modulename . '/' . $configname . '.ini')
|
static::resolvePath('modules/' . $modulename . '/' . $configname . '.ini')
|
||||||
);
|
);
|
||||||
|
@ -6,10 +6,8 @@ namespace Icinga\Application;
|
|||||||
|
|
||||||
require_once dirname(__FILE__) . '/ApplicationBootstrap.php';
|
require_once dirname(__FILE__) . '/ApplicationBootstrap.php';
|
||||||
|
|
||||||
use Icinga\Exception\ProgrammingError;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this if you want to make use of Icinga funtionality in other web projects
|
* Use this if you want to make use of Icinga functionality in other web projects
|
||||||
*
|
*
|
||||||
* Usage example:
|
* Usage example:
|
||||||
* <code>
|
* <code>
|
||||||
|
@ -68,18 +68,6 @@ class Manager
|
|||||||
*/
|
*/
|
||||||
private $modulePaths = array();
|
private $modulePaths = array();
|
||||||
|
|
||||||
/**
|
|
||||||
* The core modules
|
|
||||||
*
|
|
||||||
* Core modules do not need to be enabled to load and cannot be disabled
|
|
||||||
* by the user. This must not be writable programmatically!
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $coreModules = array(
|
|
||||||
'setup'
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of the module manager
|
* Create a new instance of the module manager
|
||||||
*
|
*
|
||||||
@ -170,21 +158,7 @@ class Manager
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to set all core modules in loaded state
|
* Try to set all enabled modules in loaded sate
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
* @see Manager::loadModule()
|
|
||||||
*/
|
|
||||||
public function loadCoreModules()
|
|
||||||
{
|
|
||||||
foreach ($this->coreModules as $name) {
|
|
||||||
$this->loadModule($name);
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to set all enabled modules in loaded state
|
|
||||||
*
|
*
|
||||||
* @return self
|
* @return self
|
||||||
* @see Manager::loadModule()
|
* @see Manager::loadModule()
|
||||||
@ -239,8 +213,6 @@ class Manager
|
|||||||
'Cannot enable module "%s". Module is not installed.',
|
'Cannot enable module "%s". Module is not installed.',
|
||||||
$name
|
$name
|
||||||
);
|
);
|
||||||
} elseif (in_array($name, $this->coreModules)) {
|
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clearstatcache(true);
|
clearstatcache(true);
|
||||||
@ -458,7 +430,7 @@ class Manager
|
|||||||
}
|
}
|
||||||
|
|
||||||
$installed = $this->listInstalledModules();
|
$installed = $this->listInstalledModules();
|
||||||
foreach (array_diff($installed, $this->coreModules) as $name) {
|
foreach ($installed as $name) {
|
||||||
$info[$name] = (object) array(
|
$info[$name] = (object) array(
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'path' => $this->installedBaseDirs[$name],
|
'path' => $this->installedBaseDirs[$name],
|
||||||
|
@ -759,15 +759,15 @@ class Module
|
|||||||
protected function registerAutoloader()
|
protected function registerAutoloader()
|
||||||
{
|
{
|
||||||
$moduleName = ucfirst($this->getName());
|
$moduleName = ucfirst($this->getName());
|
||||||
|
|
||||||
$moduleLibraryDir = $this->getLibDir(). '/'. $moduleName;
|
$moduleLibraryDir = $this->getLibDir(). '/'. $moduleName;
|
||||||
if (is_dir($this->getBaseDir()) && is_dir($this->getLibDir()) && is_dir($moduleLibraryDir)) {
|
if (is_dir($moduleLibraryDir)) {
|
||||||
$this->app->getLoader()->registerNamespace('Icinga\\Module\\' . $moduleName, $moduleLibraryDir);
|
$this->app->getLoader()->registerNamespace('Icinga\\Module\\' . $moduleName, $moduleLibraryDir);
|
||||||
if (is_dir($this->getFormDir())) {
|
}
|
||||||
$this->app->getLoader()->registerNamespace(
|
|
||||||
'Icinga\\Module\\' . $moduleName. '\\Forms',
|
$moduleFormDir = $this->getFormDir();
|
||||||
$this->getFormDir()
|
if (is_dir($moduleFormDir)) {
|
||||||
);
|
$this->app->getLoader()->registerNamespace('Icinga\\Module\\' . $moduleName. '\\Forms', $moduleFormDir);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -104,7 +104,7 @@ class Web extends ApplicationBootstrap
|
|||||||
->setupZendMvc()
|
->setupZendMvc()
|
||||||
->setupFormNamespace()
|
->setupFormNamespace()
|
||||||
->setupModuleManager()
|
->setupModuleManager()
|
||||||
->loadCoreModules()
|
->loadSetupModuleIfNecessary()
|
||||||
->loadEnabledModules()
|
->loadEnabledModules()
|
||||||
->setupRoute()
|
->setupRoute()
|
||||||
->setupPagination();
|
->setupPagination();
|
||||||
|
@ -87,9 +87,16 @@ class DbUserBackend extends UserBackend
|
|||||||
*/
|
*/
|
||||||
protected function getPasswordHash($username)
|
protected function getPasswordHash($username)
|
||||||
{
|
{
|
||||||
$stmt = $this->conn->getDbAdapter()->prepare(
|
if ($this->conn->getDbType() === 'pgsql') {
|
||||||
'SELECT password_hash FROM icingaweb_user WHERE name = :name AND active = 1'
|
// Since PostgreSQL version 9.0 the default value for bytea_output is 'hex' instead of 'escape'
|
||||||
);
|
$stmt = $this->conn->getDbAdapter()->prepare(
|
||||||
|
'SELECT ENCODE(password_hash, \'escape\') FROM icingaweb_user WHERE name = :name AND active = 1'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$stmt = $this->conn->getDbAdapter()->prepare(
|
||||||
|
'SELECT password_hash FROM icingaweb_user WHERE name = :name AND active = 1'
|
||||||
|
);
|
||||||
|
}
|
||||||
$stmt->execute(array(':name' => $username));
|
$stmt->execute(array(':name' => $username));
|
||||||
$stmt->bindColumn(1, $lob, PDO::PARAM_LOB);
|
$stmt->bindColumn(1, $lob, PDO::PARAM_LOB);
|
||||||
$stmt->fetch(PDO::FETCH_BOUND);
|
$stmt->fetch(PDO::FETCH_BOUND);
|
||||||
|
@ -11,7 +11,7 @@ use Icinga\User;
|
|||||||
/**
|
/**
|
||||||
* Test login with external authentication mechanism, e.g. Apache
|
* Test login with external authentication mechanism, e.g. Apache
|
||||||
*/
|
*/
|
||||||
class AutoLoginBackend extends UserBackend
|
class ExternalBackend extends UserBackend
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Regexp expression to strip values from a username
|
* Regexp expression to strip values from a username
|
||||||
@ -21,7 +21,7 @@ class AutoLoginBackend extends UserBackend
|
|||||||
private $stripUsernameRegexp;
|
private $stripUsernameRegexp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new autologin backend
|
* Create new authentication backend of type "external"
|
||||||
*
|
*
|
||||||
* @param ConfigObject $config
|
* @param ConfigObject $config
|
||||||
*/
|
*/
|
||||||
@ -33,7 +33,7 @@ class AutoLoginBackend extends UserBackend
|
|||||||
/**
|
/**
|
||||||
* Count the available users
|
* Count the available users
|
||||||
*
|
*
|
||||||
* Autologin backends will always return 1
|
* Authenticaton backends of type "external" will always return 1
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
@ -213,7 +213,7 @@ class LdapUserBackend extends UserBackend
|
|||||||
*/
|
*/
|
||||||
public function count()
|
public function count()
|
||||||
{
|
{
|
||||||
return $this->conn->count($this->selectUsers());
|
return $this->selectUsers()->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,7 +63,7 @@ class Manager
|
|||||||
);
|
);
|
||||||
$config = new Config();
|
$config = new Config();
|
||||||
}
|
}
|
||||||
if ($config->hasSection('preferences')) {
|
if ($config->get('preferences', 'store', 'ini') !== 'none') {
|
||||||
$preferencesConfig = $config->getSection('preferences');
|
$preferencesConfig = $config->getSection('preferences');
|
||||||
try {
|
try {
|
||||||
$preferencesStore = PreferencesStore::create(
|
$preferencesStore = PreferencesStore::create(
|
||||||
@ -165,6 +165,7 @@ class Manager
|
|||||||
*/
|
*/
|
||||||
public function hasPermission($permission)
|
public function hasPermission($permission)
|
||||||
{
|
{
|
||||||
|
return true;
|
||||||
if (! $this->isAuthenticated()) {
|
if (! $this->isAuthenticated()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
namespace Icinga\Authentication;
|
namespace Icinga\Authentication;
|
||||||
|
|
||||||
use Countable;
|
use Countable;
|
||||||
use Icinga\Authentication\Backend\AutoLoginBackend;
|
use Icinga\Authentication\Backend\ExternalBackend;
|
||||||
use Icinga\Authentication\Backend\DbUserBackend;
|
use Icinga\Authentication\Backend\DbUserBackend;
|
||||||
use Icinga\Authentication\Backend\LdapUserBackend;
|
use Icinga\Authentication\Backend\LdapUserBackend;
|
||||||
use Icinga\Data\ConfigObject;
|
use Icinga\Data\ConfigObject;
|
||||||
@ -69,8 +69,8 @@ abstract class UserBackend implements Countable
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
$backendType = strtolower($backendType);
|
$backendType = strtolower($backendType);
|
||||||
if ($backendType === 'autologin') {
|
if ($backendType === 'external') {
|
||||||
$backend = new AutoLoginBackend($backendConfig);
|
$backend = new ExternalBackend($backendConfig);
|
||||||
$backend->setName($name);
|
$backend->setName($name);
|
||||||
return $backend;
|
return $backend;
|
||||||
}
|
}
|
||||||
|
@ -78,24 +78,23 @@ class Axis implements Drawable
|
|||||||
private $yUnit = null;
|
private $yUnit = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the displayed labels should be aligned horizontally or diagonally
|
* The minimum amount of units each step must take up
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
*/
|
*/
|
||||||
private $labelRotationStyle = self::LABEL_ROTATE_DIAGONAL;
|
public $minUnitsPerStep = 80;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the label rotation style for the horizontal axis
|
* The minimum amount of units each tick must take up
|
||||||
*
|
*
|
||||||
* <ul>
|
* @var int
|
||||||
* <li><b>LABEL_ROTATE_HORIZONTAL</b>: Labels will be displayed horizontally </li>
|
|
||||||
* <li><b>LABEL_ROTATE_DIAGONAL</b>: Labels will be rotated by 45° </li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param $style The rotation mode
|
|
||||||
*/
|
*/
|
||||||
public function setHorizontalLabelRotationStyle($style)
|
public $minUnitsPerTick = 15;
|
||||||
{
|
|
||||||
$this->labelRotationStyle = $style;
|
/**
|
||||||
}
|
* If the displayed labels should be aligned horizontally or diagonally
|
||||||
|
*/
|
||||||
|
protected $labelRotationStyle = self::LABEL_ROTATE_HORIZONTAL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inform the axis about an added dataset
|
* Inform the axis about an added dataset
|
||||||
@ -160,58 +159,74 @@ class Axis implements Drawable
|
|||||||
*/
|
*/
|
||||||
private function renderHorizontalAxis(RenderContext $ctx, DOMElement $group)
|
private function renderHorizontalAxis(RenderContext $ctx, DOMElement $group)
|
||||||
{
|
{
|
||||||
|
$steps = $this->ticksPerX($this->xUnit->getTicks(), $ctx->getNrOfUnitsX(), $this->minUnitsPerStep);
|
||||||
|
$ticks = $this->ticksPerX($this->xUnit->getTicks(), $ctx->getNrOfUnitsX(), $this->minUnitsPerTick);
|
||||||
|
|
||||||
|
// Steps should always be ticks
|
||||||
|
if ($ticks !== $steps) {
|
||||||
|
$steps = $ticks * 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether there is enough room for regular labels
|
||||||
|
$labelRotationStyle = $this->labelRotationStyle;
|
||||||
|
if ($this->labelsOversized($this->xUnit, 6)) {
|
||||||
|
$labelRotationStyle = self::LABEL_ROTATE_DIAGONAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
$line = new Line(0, 100, 100, 100);
|
$line = new Line(0, 100, 100, 100);
|
||||||
$line->setStrokeWidth(2);
|
$line->setStrokeWidth(2);
|
||||||
$group->appendChild($line->toSvg($ctx));
|
$group->appendChild($line->toSvg($ctx));
|
||||||
|
*/
|
||||||
|
|
||||||
// contains the approximate end position of the last label
|
// contains the approximate end position of the last label
|
||||||
$lastLabelEnd = -1;
|
$lastLabelEnd = -1;
|
||||||
$shift = 0;
|
$shift = 0;
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
foreach ($this->xUnit as $label => $pos) {
|
foreach ($this->xUnit as $label => $pos) {
|
||||||
if ($this->labelRotationStyle === self::LABEL_ROTATE_HORIZONTAL) {
|
|
||||||
// If the last label would overlap this label we shift the y axis a bit
|
if ($i % $ticks === 0) {
|
||||||
if ($lastLabelEnd > $pos) {
|
/*
|
||||||
$shift = ($shift + 5) % 10;
|
$tick = new Line($pos, 100, $pos, 101);
|
||||||
} else {
|
$group->appendChild($tick->toSvg($ctx));
|
||||||
$shift = 0;
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($i % $steps === 0) {
|
||||||
|
if ($labelRotationStyle === self::LABEL_ROTATE_HORIZONTAL) {
|
||||||
|
// If the last label would overlap this label we shift the y axis a bit
|
||||||
|
if ($lastLabelEnd > $pos) {
|
||||||
|
$shift = ($shift + 5) % 10;
|
||||||
|
} else {
|
||||||
|
$shift = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$labelField = new Text($pos + 0.5, ($this->xLabel ? 107 : 105) + $shift, $label);
|
||||||
|
if ($labelRotationStyle === self::LABEL_ROTATE_HORIZONTAL) {
|
||||||
|
$labelField->setAlignment(Text::ALIGN_MIDDLE)
|
||||||
|
->setFontSize('2.5em');
|
||||||
|
} else {
|
||||||
|
$labelField->setFontSize('2.5em');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($labelRotationStyle === self::LABEL_ROTATE_DIAGONAL) {
|
||||||
|
$labelField = new Rotator($labelField, 45);
|
||||||
|
}
|
||||||
|
$labelField = $labelField->toSvg($ctx);
|
||||||
|
|
||||||
|
$group->appendChild($labelField);
|
||||||
|
|
||||||
|
if ($this->drawYGrid) {
|
||||||
|
$bgLine = new Line($pos, 0, $pos, 100);
|
||||||
|
$bgLine->setStrokeWidth(0.5)
|
||||||
|
->setStrokeColor('#BFBFBF');
|
||||||
|
$group->appendChild($bgLine->toSvg($ctx));
|
||||||
|
}
|
||||||
|
$lastLabelEnd = $pos + strlen($label) * 1.2;
|
||||||
}
|
}
|
||||||
|
$i++;
|
||||||
$tick = new Line($pos, 100, $pos, 102);
|
|
||||||
$group->appendChild($tick->toSvg($ctx));
|
|
||||||
|
|
||||||
$labelField = new Text($pos + 0.5, ($this->xLabel ? 107 : 105) + $shift, $label);
|
|
||||||
if ($this->labelRotationStyle === self::LABEL_ROTATE_HORIZONTAL) {
|
|
||||||
$labelField->setAlignment(Text::ALIGN_MIDDLE)
|
|
||||||
->setFontSize('1.8em');
|
|
||||||
} else {
|
|
||||||
$labelField->setFontSize('2.5em');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->labelRotationStyle === self::LABEL_ROTATE_DIAGONAL) {
|
|
||||||
$labelField = new Rotator($labelField, 45);
|
|
||||||
}
|
|
||||||
$labelField = $labelField->toSvg($ctx);
|
|
||||||
|
|
||||||
$group->appendChild($labelField);
|
|
||||||
|
|
||||||
if ($this->drawYGrid) {
|
|
||||||
$bgLine = new Line($pos, 0, $pos, 100);
|
|
||||||
$bgLine->setStrokeWidth(0.5)
|
|
||||||
->setStrokeColor('#232');
|
|
||||||
$group->appendChild($bgLine->toSvg($ctx));
|
|
||||||
}
|
|
||||||
$lastLabelEnd = $pos + strlen($label) * 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// render the label for this axis
|
|
||||||
if ($this->xLabel) {
|
|
||||||
$axisLabel = new Text(50, 104, $this->xLabel);
|
|
||||||
$axisLabel->setFontSize('2em')
|
|
||||||
->setFontWeight('bold')
|
|
||||||
->setAlignment(Text::ALIGN_MIDDLE);
|
|
||||||
$group->appendChild($axisLabel->toSvg($ctx));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,34 +238,59 @@ class Axis implements Drawable
|
|||||||
*/
|
*/
|
||||||
private function renderVerticalAxis(RenderContext $ctx, DOMElement $group)
|
private function renderVerticalAxis(RenderContext $ctx, DOMElement $group)
|
||||||
{
|
{
|
||||||
|
$steps = $this->ticksPerX($this->yUnit->getTicks(), $ctx->getNrOfUnitsY(), $this->minUnitsPerStep);
|
||||||
|
$ticks = $this->ticksPerX($this->yUnit->getTicks(), $ctx->getNrOfUnitsY(), $this->minUnitsPerTick);
|
||||||
|
|
||||||
|
// Steps should always be ticks
|
||||||
|
if ($ticks !== $steps) {
|
||||||
|
$steps = $ticks * 5;
|
||||||
|
}
|
||||||
|
/*
|
||||||
$line = new Line(0, 0, 0, 100);
|
$line = new Line(0, 0, 0, 100);
|
||||||
$line->setStrokeWidth(2);
|
$line->setStrokeWidth(2);
|
||||||
$group->appendChild($line->toSvg($ctx));
|
$group->appendChild($line->toSvg($ctx));
|
||||||
|
*/
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
foreach ($this->yUnit as $label => $pos) {
|
foreach ($this->yUnit as $label => $pos) {
|
||||||
$pos = 100 - $pos;
|
$pos = 100 - $pos;
|
||||||
$tick = new Line(0, $pos, -1, $pos);
|
|
||||||
$group->appendChild($tick->toSvg($ctx));
|
|
||||||
|
|
||||||
$labelField = new Text(-0.5, $pos+0.5, $label);
|
if ($i % $ticks === 0) {
|
||||||
$labelField->setFontSize('1.8em')
|
// draw a tick
|
||||||
->setAlignment(Text::ALIGN_END);
|
//$tick = new Line(0, $pos, -1, $pos);
|
||||||
|
//$group->appendChild($tick->toSvg($ctx));
|
||||||
$group->appendChild($labelField->toSvg($ctx));
|
|
||||||
if ($this->drawXGrid) {
|
|
||||||
$bgLine = new Line(0, $pos, 100, $pos);
|
|
||||||
$bgLine->setStrokeWidth(0.5)
|
|
||||||
->setStrokeColor('#343');
|
|
||||||
$group->appendChild($bgLine->toSvg($ctx));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($i % $steps === 0) {
|
||||||
|
// draw a step
|
||||||
|
$labelField = new Text(-0.5, $pos + 0.5, $label);
|
||||||
|
$labelField->setFontSize('2.5em')
|
||||||
|
->setAlignment(Text::ALIGN_END);
|
||||||
|
|
||||||
|
$group->appendChild($labelField->toSvg($ctx));
|
||||||
|
if ($this->drawXGrid) {
|
||||||
|
$bgLine = new Line(0, $pos, 100, $pos);
|
||||||
|
$bgLine->setStrokeWidth(0.5)
|
||||||
|
->setStrokeColor('#BFBFBF');
|
||||||
|
$group->appendChild($bgLine->toSvg($ctx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->yLabel) {
|
if ($this->yLabel || $this->xLabel) {
|
||||||
$axisLabel = new Text(-8, 50, $this->yLabel);
|
if ($this->yLabel && $this->xLabel) {
|
||||||
|
$txt = $this->yLabel . ' / ' . $this->xLabel;
|
||||||
|
} else if ($this->xLabel) {
|
||||||
|
$txt = $this->xLabel;
|
||||||
|
} else {
|
||||||
|
$txt = $this->yLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
$axisLabel = new Text(50, -3, $txt);
|
||||||
$axisLabel->setFontSize('2em')
|
$axisLabel->setFontSize('2em')
|
||||||
->setFontWeight('bold')
|
->setFontWeight('bold')
|
||||||
->setAlignment(Text::ALIGN_MIDDLE);
|
->setAlignment(Text::ALIGN_MIDDLE);
|
||||||
$axisLabel = new Rotator($axisLabel, 90);
|
|
||||||
|
|
||||||
$group->appendChild($axisLabel->toSvg($ctx));
|
$group->appendChild($axisLabel->toSvg($ctx));
|
||||||
}
|
}
|
||||||
@ -416,4 +456,32 @@ class Axis implements Drawable
|
|||||||
$this->renderVerticalAxis($ctx, $group);
|
$this->renderVerticalAxis($ctx, $group);
|
||||||
return $group;
|
return $group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function ticksPerX($ticks, $units, $min)
|
||||||
|
{
|
||||||
|
$per = 1;
|
||||||
|
while ($per * $units / $ticks < $min) {
|
||||||
|
$per++;
|
||||||
|
}
|
||||||
|
return $per;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether at least one label of the given Axis
|
||||||
|
* is bigger than the given maxLength
|
||||||
|
*
|
||||||
|
* @param AxisUnit $axis The axis that contains the labels that will be checked
|
||||||
|
*
|
||||||
|
* @return boolean Whether at least one label is bigger than maxLength
|
||||||
|
*/
|
||||||
|
private function labelsOversized(AxisUnit $axis, $maxLength = 5)
|
||||||
|
{
|
||||||
|
$oversized = false;
|
||||||
|
foreach ($axis as $label => $pos) {
|
||||||
|
if (strlen($label) > $maxLength) {
|
||||||
|
$oversized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $oversized;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ class BarGraph extends Styleable implements Drawable
|
|||||||
*
|
*
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
private $barWidth = 4;
|
private $barWidth = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The dataset to use for this bar graph
|
* The dataset to use for this bar graph
|
||||||
@ -122,6 +122,14 @@ class BarGraph extends Styleable implements Drawable
|
|||||||
$doc = $ctx->getDocument();
|
$doc = $ctx->getDocument();
|
||||||
$group = $doc->createElement('g');
|
$group = $doc->createElement('g');
|
||||||
$idx = 0;
|
$idx = 0;
|
||||||
|
|
||||||
|
if (count($this->dataSet) > 15) {
|
||||||
|
$this->barWidth = 2;
|
||||||
|
}
|
||||||
|
if (count($this->dataSet) > 25) {
|
||||||
|
$this->barWidth = 1;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($this->dataSet as $x => $point) {
|
foreach ($this->dataSet as $x => $point) {
|
||||||
// add white background bar, to prevent other bars from altering transparency effects
|
// add white background bar, to prevent other bars from altering transparency effects
|
||||||
$bar = $this->drawSingleBar($point, $idx++, 'white', $this->strokeWidth, $idx)->toSvg($ctx);
|
$bar = $this->drawSingleBar($point, $idx++, 'white', $this->strokeWidth, $idx)->toSvg($ctx);
|
||||||
|
@ -45,6 +45,13 @@ class LineGraph extends Styleable implements Drawable
|
|||||||
*/
|
*/
|
||||||
public $strokeWidth = 5;
|
public $strokeWidth = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of the displayed dots
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $dotWith = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new LineGraph displaying the given dataset
|
* Create a new LineGraph displaying the given dataset
|
||||||
*
|
*
|
||||||
@ -138,8 +145,8 @@ class LineGraph extends Styleable implements Drawable
|
|||||||
$group = $path->toSvg($ctx);
|
$group = $path->toSvg($ctx);
|
||||||
if ($this->showDataPoints === true) {
|
if ($this->showDataPoints === true) {
|
||||||
foreach ($this->dataset as $point) {
|
foreach ($this->dataset as $point) {
|
||||||
$dot = new Circle($point[0], $point[1], $this->strokeWidth*5);
|
$dot = new Circle($point[0], $point[1], $this->dotWith);
|
||||||
$dot->setFill('black');
|
$dot->setFill($this->strokeColor);
|
||||||
|
|
||||||
$group->appendChild($dot->toSvg($ctx));
|
$group->appendChild($dot->toSvg($ctx));
|
||||||
}
|
}
|
||||||
|
@ -66,13 +66,14 @@ class Legend implements Drawable
|
|||||||
$outer->getLayout()->setPadding(2, 2, 2, 2);
|
$outer->getLayout()->setPadding(2, 2, 2, 2);
|
||||||
$nrOfColumns = 4;
|
$nrOfColumns = 4;
|
||||||
|
|
||||||
$leftstep = 100 / $nrOfColumns;
|
|
||||||
$topstep = 10 / $nrOfColumns + 2;
|
$topstep = 10 / $nrOfColumns + 2;
|
||||||
|
|
||||||
$top = 0;
|
$top = 0;
|
||||||
$left = 0;
|
$left = 0;
|
||||||
$lastLabelEndPos = -1;
|
$lastLabelEndPos = -1;
|
||||||
foreach ($this->dataset as $color => $text) {
|
foreach ($this->dataset as $color => $text) {
|
||||||
|
$leftstep = 100 / $nrOfColumns + strlen($text);
|
||||||
|
|
||||||
// Make sure labels don't overlap each other
|
// Make sure labels don't overlap each other
|
||||||
while ($lastLabelEndPos >= $left) {
|
while ($lastLabelEndPos >= $left) {
|
||||||
$left += $leftstep;
|
$left += $leftstep;
|
||||||
|
@ -61,7 +61,7 @@ class Circle extends Styleable implements Drawable
|
|||||||
$circle = $ctx->getDocument()->createElement('circle');
|
$circle = $ctx->getDocument()->createElement('circle');
|
||||||
$circle->setAttribute('cx', Format::formatSVGNumber($coords[0]));
|
$circle->setAttribute('cx', Format::formatSVGNumber($coords[0]));
|
||||||
$circle->setAttribute('cy', Format::formatSVGNumber($coords[1]));
|
$circle->setAttribute('cy', Format::formatSVGNumber($coords[1]));
|
||||||
$circle->setAttribute('r', 5);
|
$circle->setAttribute('r', $this->radius);
|
||||||
$circle->setAttribute('style', $this->getStyle());
|
$circle->setAttribute('style', $this->getStyle());
|
||||||
$this->applyAttributes($circle);
|
$this->applyAttributes($circle);
|
||||||
return $circle;
|
return $circle;
|
||||||
|
@ -9,13 +9,14 @@ use Iterator;
|
|||||||
/**
|
/**
|
||||||
* Base class for Axis Units
|
* Base class for Axis Units
|
||||||
*
|
*
|
||||||
|
* An AxisUnit takes a set of values and places them on a given range
|
||||||
|
*
|
||||||
* Concrete subclasses must implement the iterator interface, with
|
* Concrete subclasses must implement the iterator interface, with
|
||||||
* getCurrent returning the axis relative position and getValue the label
|
* getCurrent returning the axis relative position and getValue the label
|
||||||
* that will be displayed
|
* that will be displayed
|
||||||
*/
|
*/
|
||||||
interface AxisUnit extends Iterator
|
interface AxisUnit extends Iterator
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a dataset to this AxisUnit, required for dynamic min and max vlaues
|
* Add a dataset to this AxisUnit, required for dynamic min and max vlaues
|
||||||
*
|
*
|
||||||
@ -46,4 +47,11 @@ interface AxisUnit extends Iterator
|
|||||||
* @param int $max The new maximum value
|
* @param int $max The new maximum value
|
||||||
*/
|
*/
|
||||||
public function setMax($max);
|
public function setMax($max);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of ticks of this axis
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getTicks();
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ namespace Icinga\Chart\Unit;
|
|||||||
*/
|
*/
|
||||||
class LinearUnit implements AxisUnit
|
class LinearUnit implements AxisUnit
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The minimum value to display
|
* The minimum value to display
|
||||||
*
|
*
|
||||||
@ -43,7 +42,7 @@ class LinearUnit implements AxisUnit
|
|||||||
*
|
*
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
private $nrOfTicks = 10;
|
protected $nrOfTicks = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The currently displayed tick
|
* The currently displayed tick
|
||||||
@ -95,45 +94,13 @@ class LinearUnit implements AxisUnit
|
|||||||
if (!$this->staticMin) {
|
if (!$this->staticMin) {
|
||||||
$this->min = min($this->min, $datapoints[0]);
|
$this->min = min($this->min, $datapoints[0]);
|
||||||
}
|
}
|
||||||
if (!$this->staticMin || !$this->staticMax) {
|
|
||||||
$this->updateMaxValue();
|
|
||||||
}
|
|
||||||
$this->currentTick = 0;
|
$this->currentTick = 0;
|
||||||
$this->currentValue = $this->min;
|
$this->currentValue = $this->min;
|
||||||
return $this;
|
if ($this->max === $this->min) {
|
||||||
}
|
$this->max = $this->min + 10;
|
||||||
|
|
||||||
/**
|
|
||||||
* Refresh the range depending on the current values of min, max and nrOfTicks
|
|
||||||
*/
|
|
||||||
private function updateMaxValue()
|
|
||||||
{
|
|
||||||
$this->max = $this->calculateTickRange($this->max - $this->min, $this->nrOfTicks) *
|
|
||||||
$this->nrOfTicks + $this->min;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine the minimum tick range that is necessary to display the given value range
|
|
||||||
* correctly
|
|
||||||
*
|
|
||||||
* @param int range The range to display
|
|
||||||
* @param int ticks The amount of ticks to use
|
|
||||||
*
|
|
||||||
* @return int The value for each tick
|
|
||||||
*/
|
|
||||||
private function calculateTickRange($range, $ticks)
|
|
||||||
{
|
|
||||||
$factor = 1;
|
|
||||||
$steps = array(1, 2, 5);
|
|
||||||
$step = 0;
|
|
||||||
while ($range / ($factor * $steps[$step]) > $ticks) {
|
|
||||||
$step++;
|
|
||||||
if ($step === count($steps)) {
|
|
||||||
$step = 0;
|
|
||||||
$factor *= 10;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return $steps[$step] * $factor;
|
$this->nrOfTicks = $this->max - $this->min;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,7 +116,7 @@ class LinearUnit implements AxisUnit
|
|||||||
} elseif ($value > $this->max) {
|
} elseif ($value > $this->max) {
|
||||||
return 100;
|
return 100;
|
||||||
} else {
|
} else {
|
||||||
return 100 * ($value - $this->min) / $this->max - $this->min;
|
return 100 * ($value - $this->min) / $this->nrOfTicks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +178,6 @@ class LinearUnit implements AxisUnit
|
|||||||
if ($max !== null) {
|
if ($max !== null) {
|
||||||
$this->max = $max;
|
$this->max = $max;
|
||||||
$this->staticMax = true;
|
$this->staticMax = true;
|
||||||
$this->updateMaxValue();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +191,6 @@ class LinearUnit implements AxisUnit
|
|||||||
if ($min !== null) {
|
if ($min !== null) {
|
||||||
$this->min = $min;
|
$this->min = $min;
|
||||||
$this->staticMin = true;
|
$this->staticMin = true;
|
||||||
$this->updateMaxValue();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,4 +213,14 @@ class LinearUnit implements AxisUnit
|
|||||||
{
|
{
|
||||||
return $this->max;
|
return $this->max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of ticks necessary to display this AxisUnit
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getTicks()
|
||||||
|
{
|
||||||
|
return $this->nrOfTicks;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
264
library/Icinga/Chart/Unit/LogarithmicUnit.php
Normal file
264
library/Icinga/Chart/Unit/LogarithmicUnit.php
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
|
namespace Icinga\Chart\Unit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logarithmic tick distribution over the axis
|
||||||
|
*
|
||||||
|
* This class does not use the actual logarithm, but a slightly altered version called the
|
||||||
|
* Log-Modulo transformation. This is necessary, since a regular logarithmic scale is not able to display negative
|
||||||
|
* values and zero-points. See <a href="http://blogs.sas.com/content/iml/2014/07/14/log-transformation-of-pos-neg>
|
||||||
|
* this article </a> for a more detailed description.
|
||||||
|
*/
|
||||||
|
class LogarithmicUnit implements AxisUnit
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var
|
||||||
|
*/
|
||||||
|
protected $currentTick;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var
|
||||||
|
*/
|
||||||
|
protected $minExp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var
|
||||||
|
*/
|
||||||
|
protected $maxExp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True when the minimum value is static and isn't affected by the data set
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $staticMin = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True when the maximum value is static and isn't affected by the data set
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $staticMax = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and initialize this AxisUnit
|
||||||
|
*
|
||||||
|
* @param int $nrOfTicks The number of ticks to use
|
||||||
|
*/
|
||||||
|
public function __construct($base = 10)
|
||||||
|
{;
|
||||||
|
$this->base = $base;
|
||||||
|
$this->minExp = PHP_INT_MAX;
|
||||||
|
$this->maxExp = ~PHP_INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a dataset and calculate the minimum and maximum value for this AxisUnit
|
||||||
|
*
|
||||||
|
* @param array $dataset The dataset to add
|
||||||
|
* @param int $idx The idx (0 for x, 1 for y)
|
||||||
|
*
|
||||||
|
* @return self Fluent interface
|
||||||
|
*/
|
||||||
|
public function addValues(array $dataset, $idx = 0)
|
||||||
|
{
|
||||||
|
$datapoints = array();
|
||||||
|
|
||||||
|
foreach ($dataset['data'] as $points) {
|
||||||
|
$datapoints[] = $points[$idx];
|
||||||
|
}
|
||||||
|
if (empty($datapoints)) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
sort($datapoints);
|
||||||
|
if (!$this->staticMax) {
|
||||||
|
$this->maxExp = max($this->maxExp, $this->logCeil($datapoints[count($datapoints) - 1]));
|
||||||
|
}
|
||||||
|
if (!$this->staticMin) {
|
||||||
|
$this->minExp = min($this->minExp, $this->logFloor($datapoints[0]));
|
||||||
|
}
|
||||||
|
$this->currentTick = 0;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform the absolute value to an axis relative value
|
||||||
|
*
|
||||||
|
* @param int $value The absolute coordinate from the data set
|
||||||
|
* @return float|int The axis relative coordinate (between 0 and 100)
|
||||||
|
*/
|
||||||
|
public function transform($value)
|
||||||
|
{
|
||||||
|
if ($value < $this->pow($this->minExp)) {
|
||||||
|
return 0;
|
||||||
|
} elseif ($value > $this->pow($this->maxExp)) {
|
||||||
|
return 100;
|
||||||
|
} else {
|
||||||
|
return 100 * ($this->log($value) - $this->minExp) / $this->getTicks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the position of the current tick
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function current()
|
||||||
|
{
|
||||||
|
return $this->currentTick * (100 / $this->getTicks());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the next tick and tick value
|
||||||
|
*/
|
||||||
|
public function next()
|
||||||
|
{
|
||||||
|
++ $this->currentTick;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the label for the current tick
|
||||||
|
*
|
||||||
|
* @return string The label for the current tick
|
||||||
|
*/
|
||||||
|
public function key()
|
||||||
|
{
|
||||||
|
$currentBase = $this->currentTick + $this->minExp;
|
||||||
|
if (abs($currentBase) > 4) {
|
||||||
|
return $this->base . 'E' . $currentBase;
|
||||||
|
}
|
||||||
|
return (string) intval($this->pow($currentBase));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True when we're at a valid tick (iterator interface)
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function valid()
|
||||||
|
{
|
||||||
|
return $this->currentTick >= 0 && $this->currentTick < $this->getTicks();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the current tick and label value
|
||||||
|
*/
|
||||||
|
public function rewind()
|
||||||
|
{
|
||||||
|
$this->currentTick = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a log-modulo transformation
|
||||||
|
*
|
||||||
|
* @param $value The value to transform
|
||||||
|
*
|
||||||
|
* @return double The transformed value
|
||||||
|
*/
|
||||||
|
protected function log($value)
|
||||||
|
{
|
||||||
|
$sign = $value > 0 ? 1 : -1;
|
||||||
|
return $sign * log1p($sign * $value) / log($this->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the biggest exponent necessary to display the given data point
|
||||||
|
*
|
||||||
|
* @param $value
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
protected function logCeil($value)
|
||||||
|
{
|
||||||
|
return ceil($this->log($value)) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the smallest exponent necessary to display the given data point
|
||||||
|
*
|
||||||
|
* @param $value
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
protected function logFloor($value)
|
||||||
|
{
|
||||||
|
return floor($this->log($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inverse function to the log-modulo transformation
|
||||||
|
*
|
||||||
|
* @param $value
|
||||||
|
*
|
||||||
|
* @return double
|
||||||
|
*/
|
||||||
|
protected function pow($value)
|
||||||
|
{
|
||||||
|
if ($value == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
$sign = $value > 0 ? 1 : -1;
|
||||||
|
return $sign * (pow($this->base, $sign * $value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the axis minimum value to a fixed value
|
||||||
|
*
|
||||||
|
* @param int $min The new minimum value
|
||||||
|
*/
|
||||||
|
public function setMin($min)
|
||||||
|
{
|
||||||
|
$this->minExp = $this->logFloor($min);
|
||||||
|
$this->staticMin = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the axis maximum value to a fixed value
|
||||||
|
*
|
||||||
|
* @param int $max The new maximum value
|
||||||
|
*/
|
||||||
|
public function setMax($max)
|
||||||
|
{
|
||||||
|
$this->maxExp = $this->logCeil($max);
|
||||||
|
$this->staticMax = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current minimum value of the axis
|
||||||
|
*
|
||||||
|
* @return int The minimum set for this axis
|
||||||
|
*/
|
||||||
|
public function getMin()
|
||||||
|
{
|
||||||
|
return $this->pow($this->minExp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current maximum value of the axis
|
||||||
|
*
|
||||||
|
* @return int The maximum set for this axis
|
||||||
|
*/
|
||||||
|
public function getMax()
|
||||||
|
{
|
||||||
|
return $this->pow($this->maxExp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of ticks necessary to display this AxisUnit
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getTicks()
|
||||||
|
{
|
||||||
|
return $this->maxExp - $this->minExp;
|
||||||
|
}
|
||||||
|
}
|
@ -118,4 +118,14 @@ class StaticAxis implements AxisUnit
|
|||||||
{
|
{
|
||||||
return reset($this->items);
|
return reset($this->items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of ticks of this axis
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getTicks()
|
||||||
|
{
|
||||||
|
return count($this->items);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,10 @@ abstract class Command
|
|||||||
{
|
{
|
||||||
protected $app;
|
protected $app;
|
||||||
protected $docs;
|
protected $docs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type Params
|
||||||
|
*/
|
||||||
protected $params;
|
protected $params;
|
||||||
protected $screen;
|
protected $screen;
|
||||||
protected $isVerbose;
|
protected $isVerbose;
|
||||||
@ -124,7 +128,7 @@ abstract class Command
|
|||||||
|
|
||||||
public function fail($msg)
|
public function fail($msg)
|
||||||
{
|
{
|
||||||
throw new IcingaException('%s', $msg);
|
throw new IcingaException($msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDefaultActionName()
|
public function getDefaultActionName()
|
||||||
|
@ -8,6 +8,11 @@ use Icinga\Data\Filter\Filter;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for filtering a result set
|
* Interface for filtering a result set
|
||||||
|
*
|
||||||
|
* @deprecated(EL): addFilter and applyFilter do the same in all usages.
|
||||||
|
* addFilter could be replaced w/ getFilter()->add(). We must no require classes implementing this interface to
|
||||||
|
* implement redundant methods over and over again. This interface must be moved to the namespace Icinga\Data\Filter.
|
||||||
|
* It lacks documentation.
|
||||||
*/
|
*/
|
||||||
interface Filterable
|
interface Filterable
|
||||||
{
|
{
|
||||||
|
71
library/Icinga/File/FileExtensionFilterIterator.php
Normal file
71
library/Icinga/File/FileExtensionFilterIterator.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
|
namespace Icinga\File;
|
||||||
|
|
||||||
|
use FilterIterator;
|
||||||
|
use Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator over files having a specific file extension
|
||||||
|
*
|
||||||
|
* Usage example:
|
||||||
|
* <code>
|
||||||
|
* <?php
|
||||||
|
*
|
||||||
|
* namespace Icinga\Example;
|
||||||
|
*
|
||||||
|
* use RecursiveDirectoryIterator;
|
||||||
|
* use RecursiveIteratorIterator;
|
||||||
|
* use Icinga\File\FileExtensionFilterIterator;
|
||||||
|
*
|
||||||
|
* $markdownFiles = new FileExtensionFilterIterator(
|
||||||
|
* new RecursiveIteratorIterator(
|
||||||
|
* new RecursiveDirectoryIterator(__DIR__),
|
||||||
|
* RecursiveIteratorIterator::SELF_FIRST
|
||||||
|
* ),
|
||||||
|
* 'md'
|
||||||
|
* );
|
||||||
|
* </code>
|
||||||
|
*/
|
||||||
|
class FileExtensionFilterIterator extends FilterIterator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The extension to filter for
|
||||||
|
*
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
protected $extension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new FileExtensionFilterIterator
|
||||||
|
*
|
||||||
|
* @param Iterator $iterator Apply filter to this iterator
|
||||||
|
* @param string $extension The file extension to filter for. The file extension may not contain the leading dot
|
||||||
|
*/
|
||||||
|
public function __construct(Iterator $iterator, $extension)
|
||||||
|
{
|
||||||
|
$this->extension = '.' . ltrim(strtolower((string) $extension), '.');
|
||||||
|
parent::__construct($iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept files which match the file extension to filter for
|
||||||
|
*
|
||||||
|
* @return bool Whether the current element of the iterator is acceptable
|
||||||
|
* through this filter
|
||||||
|
*/
|
||||||
|
public function accept()
|
||||||
|
{
|
||||||
|
$current = $this->current();
|
||||||
|
/* @var $current \SplFileInfo */
|
||||||
|
if (! $current->isFile()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// SplFileInfo::getExtension() is only available since PHP 5 >= 5.3.6
|
||||||
|
$filename = $current->getFilename();
|
||||||
|
$sfx = substr($filename, -strlen($this->extension));
|
||||||
|
return $sfx === false ? false : strtolower($sfx) === $this->extension;
|
||||||
|
}
|
||||||
|
}
|
@ -27,7 +27,7 @@ class IniWriter extends Zend_Config_Writer_FileAbstract
|
|||||||
*
|
*
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
public static $fileMode = 0664;
|
public static $fileMode = 0660;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new INI writer
|
* Create a new INI writer
|
||||||
@ -90,11 +90,9 @@ class IniWriter extends Zend_Config_Writer_FileAbstract
|
|||||||
|
|
||||||
if ($setMode) {
|
if ($setMode) {
|
||||||
$mode = isset($this->options['filemode']) ? $this->options['filemode'] : static::$fileMode;
|
$mode = isset($this->options['filemode']) ? $this->options['filemode'] : static::$fileMode;
|
||||||
$old = umask(0); // Make sure that the mode we're going to set doesn't get mangled
|
|
||||||
if (is_int($mode) && false === @chmod($filePath, $mode)) {
|
if (is_int($mode) && false === @chmod($filePath, $mode)) {
|
||||||
throw new Zend_Config_Exception(sprintf('Failed to set file mode "%o" on file "%s"', $mode, $filePath));
|
throw new Zend_Config_Exception(sprintf('Failed to set file mode "%o" on file "%s"', $mode, $filePath));
|
||||||
}
|
}
|
||||||
umask($old);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +232,7 @@ class IniWriter extends Zend_Config_Writer_FileAbstract
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter for filename
|
* Getter for filename
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getFilename()
|
public function getFilename()
|
||||||
|
49
library/Icinga/File/NonEmptyFileIterator.php
Normal file
49
library/Icinga/File/NonEmptyFileIterator.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}
|
||||||
|
|
||||||
|
namespace Icinga\File;
|
||||||
|
|
||||||
|
use FilterIterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator over non-empty files
|
||||||
|
*
|
||||||
|
* Usage example:
|
||||||
|
* <code>
|
||||||
|
* <?php
|
||||||
|
*
|
||||||
|
* namespace Icinga\Example;
|
||||||
|
*
|
||||||
|
* use RecursiveDirectoryIterator;
|
||||||
|
* use RecursiveIteratorIterator;
|
||||||
|
* use Icinga\File\NonEmptyFilterIterator;
|
||||||
|
*
|
||||||
|
* $nonEmptyFiles = new NonEmptyFileIterator(
|
||||||
|
* new RecursiveIteratorIterator(
|
||||||
|
* new RecursiveDirectoryIterator(__DIR__),
|
||||||
|
* RecursiveIteratorIterator::SELF_FIRST
|
||||||
|
* )
|
||||||
|
* );
|
||||||
|
* </code>
|
||||||
|
*/
|
||||||
|
class NonEmptyFileIterator extends FilterIterator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Accept non-empty files
|
||||||
|
*
|
||||||
|
* @return bool Whether the current element of the iterator is acceptable
|
||||||
|
* through this filter
|
||||||
|
*/
|
||||||
|
public function accept()
|
||||||
|
{
|
||||||
|
$current = $this->current();
|
||||||
|
/** @type $current \SplFileInfo */
|
||||||
|
if (! $current->isFile()
|
||||||
|
|| $current->getSize() === 0
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
namespace Icinga\Protocol\Ldap;
|
namespace Icinga\Protocol\Ldap;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use Icinga\Protocol\Ldap\Exception as LdapException;
|
use Icinga\Protocol\Ldap\Exception as LdapException;
|
||||||
use Icinga\Application\Platform;
|
use Icinga\Application\Platform;
|
||||||
use Icinga\Application\Config;
|
use Icinga\Application\Config;
|
||||||
@ -97,6 +98,9 @@ class Connection
|
|||||||
protected $namingContexts;
|
protected $namingContexts;
|
||||||
protected $discoverySuccess = false;
|
protected $discoverySuccess = false;
|
||||||
|
|
||||||
|
protected $lastResult;
|
||||||
|
protected $pageCookie;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
@ -238,7 +242,8 @@ class Connection
|
|||||||
*/
|
*/
|
||||||
public function fetchRow($query, $fields = array())
|
public function fetchRow($query, $fields = array())
|
||||||
{
|
{
|
||||||
// TODO: This is ugly, make it better!
|
$query = clone $query;
|
||||||
|
$query->limit(1);
|
||||||
$results = $this->fetchAll($query, $fields);
|
$results = $this->fetchAll($query, $fields);
|
||||||
return array_shift($results);
|
return array_shift($results);
|
||||||
}
|
}
|
||||||
@ -250,44 +255,56 @@ class Connection
|
|||||||
*/
|
*/
|
||||||
public function count(Query $query)
|
public function count(Query $query)
|
||||||
{
|
{
|
||||||
$results = $this->runQuery($query, '+');
|
$this->connect();
|
||||||
if (! $results) {
|
$this->bind();
|
||||||
return 0;
|
|
||||||
|
$count = 0;
|
||||||
|
$results = $this->runQuery($query);
|
||||||
|
while (! empty($results)) {
|
||||||
|
$count += ldap_count_entries($this->ds, $results);
|
||||||
|
$results = $this->runQuery($query);
|
||||||
}
|
}
|
||||||
return ldap_count_entries($this->ds, $results);
|
|
||||||
|
return $count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fetchAll($query, $fields = array())
|
public function fetchAll(Query $query, $fields = array())
|
||||||
{
|
{
|
||||||
$offset = null;
|
$this->connect();
|
||||||
$limit = null;
|
$this->bind();
|
||||||
|
|
||||||
|
$offset = $limit = null;
|
||||||
if ($query->hasLimit()) {
|
if ($query->hasLimit()) {
|
||||||
$offset = $query->getOffset();
|
$offset = $query->getOffset();
|
||||||
$limit = $query->getLimit();
|
$limit = $query->getLimit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$count = 0;
|
||||||
$entries = array();
|
$entries = array();
|
||||||
$results = $this->runQuery($query, $fields);
|
$results = $this->runQuery($query, $fields);
|
||||||
if (! $results) {
|
while (! empty($results)) {
|
||||||
return array();
|
$entry = ldap_first_entry($this->ds, $results);
|
||||||
}
|
while ($entry) {
|
||||||
$entry = ldap_first_entry($this->ds, $results);
|
$count++;
|
||||||
$count = 0;
|
if (
|
||||||
while ($entry) {
|
($offset === null || $offset <= $count)
|
||||||
if (($offset === null || $offset <= $count)
|
&& ($limit === null || $limit > count($entries))
|
||||||
&& ($limit === null || ($offset + $limit) >= $count)
|
) {
|
||||||
) {
|
$entries[ldap_get_dn($this->ds, $entry)] = $this->cleanupAttributes(
|
||||||
$attrs = ldap_get_attributes($this->ds, $entry);
|
ldap_get_attributes($this->ds, $entry)
|
||||||
$entries[ldap_get_dn($this->ds, $entry)]
|
);
|
||||||
= $this->cleanupAttributes($attrs);
|
}
|
||||||
|
|
||||||
|
$entry = ldap_next_entry($this->ds, $entry);
|
||||||
}
|
}
|
||||||
$count++;
|
|
||||||
$entry = ldap_next_entry($this->ds, $entry);
|
$results = $this->runQuery($query, $fields);
|
||||||
}
|
}
|
||||||
ldap_free_result($results);
|
|
||||||
return $entries;
|
return $entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function cleanupAttributes(& $attrs)
|
protected function cleanupAttributes($attrs)
|
||||||
{
|
{
|
||||||
$clean = (object) array();
|
$clean = (object) array();
|
||||||
for ($i = 0; $i < $attrs['count']; $i++) {
|
for ($i = 0; $i < $attrs['count']; $i++) {
|
||||||
@ -303,26 +320,55 @@ class Connection
|
|||||||
return $clean;
|
return $clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function runQuery($query, $fields)
|
protected function runQuery(Query $query, $fields = array())
|
||||||
{
|
{
|
||||||
$this->connect();
|
if ($query->getUsePagedResults() && version_compare(PHP_VERSION, '5.4.0') >= 0) {
|
||||||
$this->bind();
|
if ($this->pageCookie === null) {
|
||||||
if ($query instanceof Query) {
|
$this->pageCookie = '';
|
||||||
$fields = $query->listFields();
|
} else {
|
||||||
|
try {
|
||||||
|
ldap_control_paged_result_response($this->ds, $this->lastResult, $this->pageCookie);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->pageCookie = '';
|
||||||
|
Logger::debug(
|
||||||
|
'Unable to request paged LDAP results. Does the server allow paged search requests? (%s)',
|
||||||
|
$e->getMessage()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ldap_free_result($this->lastResult);
|
||||||
|
if (! $this->pageCookie) {
|
||||||
|
$this->pageCookie = $this->lastResult = null;
|
||||||
|
// Abandon the paged search request so that subsequent requests succeed
|
||||||
|
ldap_control_paged_result($this->ds, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does not matter whether we'll use a valid page size here,
|
||||||
|
// as the server applies its hard limit in case its too high
|
||||||
|
ldap_control_paged_result(
|
||||||
|
$this->ds,
|
||||||
|
$query->hasLimit() ? $query->getLimit() : 500,
|
||||||
|
true,
|
||||||
|
$this->pageCookie
|
||||||
|
);
|
||||||
|
} elseif ($this->lastResult !== null) {
|
||||||
|
ldap_free_result($this->lastResult);
|
||||||
|
$this->lastResult = null;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
// WARNING:
|
|
||||||
// We do not support pagination right now, and there is no chance to
|
|
||||||
// do so for PHP < 5.4. Warnings about "Sizelimit exceeded" will
|
|
||||||
// therefore not be hidden right now.
|
|
||||||
$base = $query->hasBase() ? $query->getBase() : $this->root_dn;
|
$base = $query->hasBase() ? $query->getBase() : $this->root_dn;
|
||||||
$results = @ldap_search(
|
$results = @ldap_search(
|
||||||
$this->ds,
|
$this->ds,
|
||||||
$base,
|
$base,
|
||||||
$query->create(),
|
$query->create(),
|
||||||
$fields,
|
empty($fields) ? $query->listFields() : $fields,
|
||||||
0, // Attributes and values
|
0, // Attributes and values
|
||||||
0 // No limit - at least where possible
|
$query->hasLimit() ? $query->getOffset() + $query->getLimit() : 0 // No limit - at least where possible
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($results === false) {
|
if ($results === false) {
|
||||||
if (ldap_errno($this->ds) === self::LDAP_NO_SUCH_OBJECT) {
|
if (ldap_errno($this->ds) === self::LDAP_NO_SUCH_OBJECT) {
|
||||||
return false;
|
return false;
|
||||||
@ -336,12 +382,12 @@ class Connection
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$list = array();
|
|
||||||
if ($query instanceof Query) {
|
foreach ($query->getSortColumns() as $col) {
|
||||||
foreach ($query->getSortColumns() as $col) {
|
ldap_sort($this->ds, $results, $col[0]);
|
||||||
ldap_sort($this->ds, $results, $col[0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->lastResult = $results;
|
||||||
return $results;
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ class Query
|
|||||||
protected $sort_columns = array();
|
protected $sort_columns = array();
|
||||||
protected $count;
|
protected $count;
|
||||||
protected $base;
|
protected $base;
|
||||||
|
protected $usePagedResults = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -61,6 +62,17 @@ class Query
|
|||||||
return $this->base;
|
return $this->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setUsePagedResults($state = true)
|
||||||
|
{
|
||||||
|
$this->usePagedResults = (bool) $state;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUsePagedResults()
|
||||||
|
{
|
||||||
|
return $this->usePagedResults;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count result set, ignoring limits
|
* Count result set, ignoring limits
|
||||||
*
|
*
|
||||||
|
@ -197,8 +197,8 @@ class User
|
|||||||
*/
|
*/
|
||||||
public function setPermissions(array $permissions)
|
public function setPermissions(array $permissions)
|
||||||
{
|
{
|
||||||
natcasesort($permissions);
|
|
||||||
if (! empty($permissions)) {
|
if (! empty($permissions)) {
|
||||||
|
natcasesort($permissions);
|
||||||
$this->permissions = array_combine($permissions, $permissions);
|
$this->permissions = array_combine($permissions, $permissions);
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -26,7 +26,7 @@ use Icinga\Data\Db\DbConnection;
|
|||||||
* // Create a INI store
|
* // Create a INI store
|
||||||
* $store = PreferencesStore::create(
|
* $store = PreferencesStore::create(
|
||||||
* new ConfigObject(
|
* new ConfigObject(
|
||||||
* 'type' => 'ini',
|
* 'store' => 'ini',
|
||||||
* 'config_path' => '/path/to/preferences'
|
* 'config_path' => '/path/to/preferences'
|
||||||
* ),
|
* ),
|
||||||
* $user // Instance of \Icinga\User
|
* $user // Instance of \Icinga\User
|
||||||
@ -117,13 +117,7 @@ abstract class PreferencesStore
|
|||||||
*/
|
*/
|
||||||
public static function create(ConfigObject $config, User $user)
|
public static function create(ConfigObject $config, User $user)
|
||||||
{
|
{
|
||||||
if (($type = $config->type) === null) {
|
$type = ucfirst(strtolower($config->get('store', 'ini')));
|
||||||
throw new ConfigurationError(
|
|
||||||
'Preferences configuration is missing the type directive'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$type = ucfirst(strtolower($type));
|
|
||||||
$storeClass = 'Icinga\\User\\Preferences\\Store\\' . $type . 'Store';
|
$storeClass = 'Icinga\\User\\Preferences\\Store\\' . $type . 'Store';
|
||||||
if (!class_exists($storeClass)) {
|
if (!class_exists($storeClass)) {
|
||||||
throw new ConfigurationError(
|
throw new ConfigurationError(
|
||||||
|
@ -36,4 +36,22 @@ class String
|
|||||||
{
|
{
|
||||||
return str_replace(' ', '', ucwords(str_replace($separator, ' ', strtolower($name))));
|
return str_replace(' ', '', ucwords(str_replace($separator, ' ', strtolower($name))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add ellipsis when a string is longer than max length
|
||||||
|
*
|
||||||
|
* @param string $string
|
||||||
|
* @param int $maxLength
|
||||||
|
* @param string $ellipsis
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function ellipsis($string, $maxLength, $ellipsis = '...')
|
||||||
|
{
|
||||||
|
if (strlen($string) > $maxLength) {
|
||||||
|
return substr($string, 0, $maxLength - strlen($ellipsis)) . $ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
namespace Icinga\Web\Controller;
|
namespace Icinga\Web\Controller;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Icinga\Authentication\Manager as AuthManager;
|
use Icinga\Authentication\Manager;
|
||||||
use Icinga\Application\Benchmark;
|
use Icinga\Application\Benchmark;
|
||||||
use Icinga\Application\Config;
|
use Icinga\Application\Config;
|
||||||
use Icinga\Exception\IcingaException;
|
use Icinga\Exception\IcingaException;
|
||||||
@ -47,6 +47,11 @@ class ActionController extends Zend_Controller_Action
|
|||||||
|
|
||||||
private $xhrLayout = 'inline';
|
private $xhrLayout = 'inline';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentication manager
|
||||||
|
*
|
||||||
|
* @type \Icinga\Authentication\Manager|null
|
||||||
|
*/
|
||||||
private $auth;
|
private $auth;
|
||||||
|
|
||||||
protected $params;
|
protected $params;
|
||||||
@ -101,6 +106,49 @@ class ActionController extends Zend_Controller_Action
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the authentication manager
|
||||||
|
*
|
||||||
|
* @return Manager
|
||||||
|
*/
|
||||||
|
public function Auth()
|
||||||
|
{
|
||||||
|
if ($this->auth === null) {
|
||||||
|
$this->auth = Manager::getInstance();
|
||||||
|
}
|
||||||
|
return $this->auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the current user has the given permission
|
||||||
|
*
|
||||||
|
* @param string $permission Name of the permission
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasPermission($permission)
|
||||||
|
{
|
||||||
|
return $this->Auth()->hasPermission($permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throw an exception if user lacks the given permission
|
||||||
|
*
|
||||||
|
* @param string $name Permission name
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function assertPermission($name)
|
||||||
|
{
|
||||||
|
if (! $this->Auth()->hasPermission($name)) {
|
||||||
|
// TODO: Shall this be an Auth Exception? Or a 404?
|
||||||
|
throw new IcingaException(
|
||||||
|
'Auth error, no permission for "%s"',
|
||||||
|
$name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function Config($file = null)
|
public function Config($file = null)
|
||||||
{
|
{
|
||||||
if ($file === null) {
|
if ($file === null) {
|
||||||
@ -110,14 +158,6 @@ class ActionController extends Zend_Controller_Action
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Auth()
|
|
||||||
{
|
|
||||||
if ($this->auth === null) {
|
|
||||||
$this->auth = AuthManager::getInstance();
|
|
||||||
}
|
|
||||||
return $this->auth;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Window()
|
public function Window()
|
||||||
{
|
{
|
||||||
if ($this->window === null) {
|
if ($this->window === null) {
|
||||||
@ -146,6 +186,22 @@ class ActionController extends Zend_Controller_Action
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Respond with HTTP 405 if the current request's method is not one of the given methods
|
||||||
|
*
|
||||||
|
* @param string $httpMethod Unlimited number of allowed HTTP methods
|
||||||
|
*
|
||||||
|
* @throws \Zend_Controller_Action_Exception If the request method is not one of the given methods
|
||||||
|
*/
|
||||||
|
public function assertHttpMethod($httpMethod)
|
||||||
|
{
|
||||||
|
$httpMethods = array_flip(array_map('strtoupper', func_get_args()));
|
||||||
|
if (! isset($httpMethods[$this->getRequest()->getMethod()])) {
|
||||||
|
$this->getResponse()->setHeader('Allow', implode(', ', array_keys($httpMethods)));
|
||||||
|
throw new \Zend_Controller_Action_Exception($this->translate('Method Not Allowed'), 405);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return restriction information for an eventually authenticated user
|
* Return restriction information for an eventually authenticated user
|
||||||
*
|
*
|
||||||
@ -157,34 +213,6 @@ class ActionController extends Zend_Controller_Action
|
|||||||
return $this->Auth()->getRestrictions($name);
|
return $this->Auth()->getRestrictions($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the user currently authenticated has the given permission
|
|
||||||
*
|
|
||||||
* @param string $name Permission name
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function hasPermission($name)
|
|
||||||
{
|
|
||||||
return $this->Auth()->hasPermission($name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Throws an exception if user lacks the given permission
|
|
||||||
*
|
|
||||||
* @param string $name Permission name
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function assertPermission($name)
|
|
||||||
{
|
|
||||||
if (! $this->Auth()->hasPermission($name)) {
|
|
||||||
// TODO: Shall this be an Auth Exception? Or a 404?
|
|
||||||
throw new IcingaException(
|
|
||||||
'Auth error, no permission for "%s"',
|
|
||||||
$name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the controller requires a login. That is when the controller requires authentication and the
|
* Check whether the controller requires a login. That is when the controller requires authentication and the
|
||||||
* user is currently not authenticated
|
* user is currently not authenticated
|
||||||
@ -270,7 +298,7 @@ class ActionController extends Zend_Controller_Action
|
|||||||
/**
|
/**
|
||||||
* Redirect to the login path
|
* Redirect to the login path
|
||||||
*
|
*
|
||||||
* @param string $afterLogin The action to call when the login was successful. Defaults to '/index/welcome'
|
* @param Url $afterLogin The action to call when the login was successful. Defaults to '/index/welcome'
|
||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
|
@ -512,7 +512,7 @@ class Form extends Zend_Form
|
|||||||
|
|
||||||
$el = parent::createElement($type, $name, $options);
|
$el = parent::createElement($type, $name, $options);
|
||||||
|
|
||||||
if (($description = $el->getDescription()) !== null && ($label = $el->getDecorator('label')) !== null) {
|
if (($description = $el->getDescription()) !== null && ($label = $el->getDecorator('label')) !== false) {
|
||||||
$label->setOptions(array(
|
$label->setOptions(array(
|
||||||
'title' => $description,
|
'title' => $description,
|
||||||
'class' => 'has-feedback'
|
'class' => 'has-feedback'
|
||||||
@ -805,6 +805,24 @@ class Form extends Zend_Form
|
|||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the translation domain for this form
|
||||||
|
*
|
||||||
|
* The returned translation domain is either determined based on this form's qualified name or it is the default
|
||||||
|
* 'icinga' domain
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getTranslationDomain()
|
||||||
|
{
|
||||||
|
$parts = explode('\\', get_called_class());
|
||||||
|
if ($parts[1] === 'Module') {
|
||||||
|
// Assume format Icinga\Module\ModuleName\Forms\...
|
||||||
|
return strtolower($parts[2]);
|
||||||
|
}
|
||||||
|
return 'icinga';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translate a string
|
* Translate a string
|
||||||
*
|
*
|
||||||
@ -815,7 +833,7 @@ class Form extends Zend_Form
|
|||||||
*/
|
*/
|
||||||
protected function translate($text, $context = null)
|
protected function translate($text, $context = null)
|
||||||
{
|
{
|
||||||
return Translator::translate($text, $this->request->getModuleName(), $context);
|
return Translator::translate($text, $this->getTranslationDomain(), $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -834,7 +852,7 @@ class Form extends Zend_Form
|
|||||||
$textSingular,
|
$textSingular,
|
||||||
$textPlural,
|
$textPlural,
|
||||||
$number,
|
$number,
|
||||||
$this->request->getModuleName(),
|
$this->getTranslationDomain(),
|
||||||
$context
|
$context
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -43,12 +43,6 @@ class LessCompiler
|
|||||||
{
|
{
|
||||||
require_once 'lessphp/lessc.inc.php';
|
require_once 'lessphp/lessc.inc.php';
|
||||||
$this->lessc = new lessc();
|
$this->lessc = new lessc();
|
||||||
|
|
||||||
$this->lessc->setVariables(
|
|
||||||
array(
|
|
||||||
'baseurl' => '\'' . Zend_Controller_Front::getInstance()->getBaseUrl(). '\''
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function compress()
|
public function compress()
|
||||||
|
@ -248,7 +248,8 @@ class Menu implements RecursiveIterator
|
|||||||
|
|
||||||
$section->add(t('Logout'), array(
|
$section->add(t('Logout'), array(
|
||||||
'url' => 'authentication/logout',
|
'url' => 'authentication/logout',
|
||||||
'priority' => 700
|
'priority' => 700,
|
||||||
|
'renderer' => 'ForeignMenuItemRenderer'
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -366,7 +367,7 @@ class Menu implements RecursiveIterator
|
|||||||
/**
|
/**
|
||||||
* Return the url of this menu
|
* Return the url of this menu
|
||||||
*
|
*
|
||||||
* @return string
|
* @return Url
|
||||||
*/
|
*/
|
||||||
public function getUrl()
|
public function getUrl()
|
||||||
{
|
{
|
||||||
|
24
library/Icinga/Web/Menu/ForeignMenuItemRenderer.php
Normal file
24
library/Icinga/Web/Menu/ForeignMenuItemRenderer.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
|
namespace Icinga\Web\Menu;
|
||||||
|
|
||||||
|
use Icinga\Web\Menu;
|
||||||
|
use Icinga\Web\Url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A menu item with a link that surpasses the regular navigation link behavior
|
||||||
|
*/
|
||||||
|
class ForeignMenuItemRenderer implements MenuItemRenderer {
|
||||||
|
|
||||||
|
public function render(Menu $menu)
|
||||||
|
{
|
||||||
|
return sprintf(
|
||||||
|
'<a href="%s" target="_self">%s%s<span></span></a>',
|
||||||
|
$menu->getUrl() ?: '#',
|
||||||
|
$menu->getIcon() ? '<img src="' . Url::fromPath($menu->getIcon()) . '" class="icon" /> ' : '',
|
||||||
|
htmlspecialchars($menu->getTitle())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
5
library/Icinga/Web/Session/PhpSession.php
Normal file → Executable file
5
library/Icinga/Web/Session/PhpSession.php
Normal file → Executable file
@ -78,8 +78,9 @@ class PhpSession extends Session
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_writable(session_save_path())) {
|
$sessionSavePath = session_save_path();
|
||||||
throw new ConfigurationError('Can\'t save session');
|
if (session_module_name() === 'files' && !is_writable($sessionSavePath)) {
|
||||||
|
throw new ConfigurationError("Can't save session, path '$sessionSavePath' is not writable.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->exists()) {
|
if ($this->exists()) {
|
||||||
|
@ -96,6 +96,7 @@ class StyleSheet
|
|||||||
$cache->send($cacheFile);
|
$cache->send($cacheFile);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$less = new LessCompiler();
|
$less = new LessCompiler();
|
||||||
foreach ($lessFiles as $file) {
|
foreach ($lessFiles as $file) {
|
||||||
$less->addFile($file);
|
$less->addFile($file);
|
||||||
|
@ -4,10 +4,11 @@
|
|||||||
|
|
||||||
namespace Icinga\Web;
|
namespace Icinga\Web;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Zend_View_Abstract;
|
||||||
|
use Icinga\Authentication\Manager;
|
||||||
use Icinga\Exception\ProgrammingError;
|
use Icinga\Exception\ProgrammingError;
|
||||||
use Icinga\Util\Translator;
|
use Icinga\Util\Translator;
|
||||||
use Zend_View_Abstract;
|
|
||||||
use Closure;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icinga view
|
* Icinga view
|
||||||
@ -36,6 +37,13 @@ class View extends Zend_View_Abstract
|
|||||||
*/
|
*/
|
||||||
private $helperFunctions = array();
|
private $helperFunctions = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentication manager
|
||||||
|
*
|
||||||
|
* @type \Icinga\Authentication\Manager|null
|
||||||
|
*/
|
||||||
|
private $auth;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new view object
|
* Create a new view object
|
||||||
*
|
*
|
||||||
@ -154,6 +162,31 @@ class View extends Zend_View_Abstract
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the authentication manager
|
||||||
|
*
|
||||||
|
* @return Manager
|
||||||
|
*/
|
||||||
|
public function Auth()
|
||||||
|
{
|
||||||
|
if ($this->auth === null) {
|
||||||
|
$this->auth = Manager::getInstance();
|
||||||
|
}
|
||||||
|
return $this->auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the current user has the given permission
|
||||||
|
*
|
||||||
|
* @param string $permission Name of the permission
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasPermission($permission)
|
||||||
|
{
|
||||||
|
return $this->Auth()->hasPermission($permission);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use to include the view script in a scope that only allows public
|
* Use to include the view script in a scope that only allows public
|
||||||
* members.
|
* members.
|
||||||
|
8
library/Icinga/Web/View/helpers/string.php
Normal file
8
library/Icinga/Web/View/helpers/string.php
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
namespace Icinga\Web\View;
|
||||||
|
|
||||||
|
use Icinga\Util\String;
|
||||||
|
|
||||||
|
$this->addHelperFunction('ellipsis', function ($string, $maxLength, $ellipsis = '...') {
|
||||||
|
return String::ellipsis($string, $maxLength, $ellipsis);
|
||||||
|
});
|
@ -5,6 +5,7 @@
|
|||||||
namespace Icinga\Web\Widget\Chart;
|
namespace Icinga\Web\Widget\Chart;
|
||||||
|
|
||||||
use Icinga\Chart\PieChart;
|
use Icinga\Chart\PieChart;
|
||||||
|
use Icinga\Module\Monitoring\Plugin\PerfdataSet;
|
||||||
use Icinga\Web\Widget\AbstractWidget;
|
use Icinga\Web\Widget\AbstractWidget;
|
||||||
use Icinga\Web\Url;
|
use Icinga\Web\Url;
|
||||||
use Icinga\Util\Format;
|
use Icinga\Util\Format;
|
||||||
@ -28,36 +29,23 @@ class InlinePie extends AbstractWidget
|
|||||||
const NUMBER_FORMAT_RATIO = 'ratio';
|
const NUMBER_FORMAT_RATIO = 'ratio';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The template string used for rendering this widget
|
|
||||||
* The template string used for rendering this widget
|
* The template string used for rendering this widget
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $template =<<<'EOD'
|
private $template =<<<'EOD'
|
||||||
<span
|
<span sparkType="pie" class="sparkline {class}" {title} {size} sparkSliceColors="[{colors}]" values="{data}">
|
||||||
class="sparkline"
|
</span>
|
||||||
sparkTitle="{title}"
|
{noscript}
|
||||||
sparkWidth="{width}"
|
|
||||||
sparkHeight="{height}"
|
|
||||||
sparkBorderWidth="{borderWidth}"
|
|
||||||
sparkBorderColor="{borderColor}"
|
|
||||||
sparkTooltipChartTitle="{title}"
|
|
||||||
style="{style}"
|
|
||||||
labels="{labels}"
|
|
||||||
formatted="{formatted}"
|
|
||||||
hideEmptyLabel={hideEmptyLabel}
|
|
||||||
values="{data}"
|
|
||||||
tooltipFormat="{tooltipFormat}"
|
|
||||||
sparkSliceColors="[{colors}]"
|
|
||||||
sparkType="pie"></span>
|
|
||||||
<noscript>
|
|
||||||
<img class="inlinepie"
|
|
||||||
title="{title}" src="{url}" style="position: relative; top: 10px; width: {width}px; height: {height}px; {style}"
|
|
||||||
data-icinga-colors="{colors}" data-icinga-values="{data}"
|
|
||||||
/>
|
|
||||||
</noscript>
|
|
||||||
EOD;
|
EOD;
|
||||||
|
|
||||||
|
private $noscript =<<<'EOD'
|
||||||
|
<noscript>
|
||||||
|
<img class="inlinepie {class}" {title} src="{url}" data-icinga-colors="{colors}" data-icinga-values="{data}"/>
|
||||||
|
</noscript>
|
||||||
|
EOD;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Url
|
* @var Url
|
||||||
*/
|
*/
|
||||||
@ -68,35 +56,7 @@ EOD;
|
|||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $colors = array('#44bb77', '#ffaa44', '#ff5566', '#ddccdd');
|
private $colors = array('#049BAF', '#ffaa44', '#ff5566', '#ddccdd');
|
||||||
|
|
||||||
/**
|
|
||||||
* The width of the rendered chart
|
|
||||||
*
|
|
||||||
* @var int The value in px
|
|
||||||
*/
|
|
||||||
private $width = 16;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The height of the rendered chart
|
|
||||||
*
|
|
||||||
* @var int The value in px
|
|
||||||
*/
|
|
||||||
private $height = 16;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PieChart border width
|
|
||||||
*
|
|
||||||
* @var float
|
|
||||||
*/
|
|
||||||
private $borderWidth = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The color of the border
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $borderColor = '#fff';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The title of the chart
|
* The title of the chart
|
||||||
@ -106,11 +66,9 @@ EOD;
|
|||||||
private $title;
|
private $title;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The style for the HtmlElement
|
* @var
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
*/
|
||||||
private $style = '';
|
private $size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The data displayed by the pie-chart
|
* The data displayed by the pie-chart
|
||||||
@ -120,45 +78,9 @@ EOD;
|
|||||||
private $data;
|
private $data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The labels to display for each data set
|
* @var
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
*/
|
||||||
private $labels = array();
|
private $class = '';
|
||||||
|
|
||||||
/**
|
|
||||||
* If the tooltip for the "empty" area should be hidden
|
|
||||||
*
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
private $hideEmptyLabel = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The format string used to display tooltips
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $tooltipFormat = '<b>{{title}}</b></br> {{label}}: {{formatted}} ({{percent}}%)';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number format used to render numeric values in tooltips
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $format = self::NUMBER_FORMAT_NONE;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set if the tooltip for the empty area should be hidden
|
|
||||||
*
|
|
||||||
* @param bool $hide Whether to hide the empty area
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setHideEmptyLabel($hide = true)
|
|
||||||
{
|
|
||||||
$this->hideEmptyLabel = $hide;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the data to be displayed.
|
* Set the data to be displayed.
|
||||||
@ -175,24 +97,36 @@ EOD;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The labels to be displayed in the pie-chart
|
* Set the size of the inline pie
|
||||||
*
|
*
|
||||||
* @param mixed $label The label of the displayed value, or null for no labels
|
* @param int $size Sets both, the height and width
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setLabel($label)
|
public function setSize($size = null)
|
||||||
{
|
{
|
||||||
if (is_array($label)) {
|
$this->size = $size;
|
||||||
$this->url->setParam('labels', implode(',', array_keys($label)));
|
return $this;
|
||||||
} elseif ($label != null) {
|
}
|
||||||
$labelArr = array($label, $label, $label, '');
|
|
||||||
$this->url->setParam('labels', implode(',', $labelArr));
|
/**
|
||||||
$label = $labelArr;
|
* Do not display the NoScript fallback html
|
||||||
} else {
|
*/
|
||||||
$this->url->removeKey('labels');
|
public function disableNoScript()
|
||||||
}
|
{
|
||||||
$this->labels = $label;
|
$this->noscript = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the class to define the
|
||||||
|
*
|
||||||
|
* @param $class
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setSparklineClass($class)
|
||||||
|
{
|
||||||
|
$this->class = $class;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,105 +148,6 @@ EOD;
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the used number format
|
|
||||||
*
|
|
||||||
* @param $format string 'bytes' or 'time'
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setNumberFormat($format)
|
|
||||||
{
|
|
||||||
$this->format = $format;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A format string used to render the content of the piechart tooltips
|
|
||||||
*
|
|
||||||
* Placeholders using curly braces '{FOO}' are replace with their specific values. The format
|
|
||||||
* String may contain HTML-Markup. The available replaceable values are:
|
|
||||||
* <ul>
|
|
||||||
* <li><b>label</b>: The description for the current value </li>
|
|
||||||
* <li><b>formatted</b>: A string representing the formatted value </li>
|
|
||||||
* <li><b>value</b>: The raw (non-formatted) value used to render the piechart </li>
|
|
||||||
* <li><b>percent</b>: The percentage of the current value </li>
|
|
||||||
* </ul>
|
|
||||||
* Note: Changes will only affect JavaScript sparklines and not the SVG charts used for fallback
|
|
||||||
*
|
|
||||||
* @param $format
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setTooltipFormat($format)
|
|
||||||
{
|
|
||||||
$this->tooltipFormat = $format;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the height
|
|
||||||
*
|
|
||||||
* @param $height
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setHeight($height)
|
|
||||||
{
|
|
||||||
$this->height = $height;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the border width of the pie chart
|
|
||||||
*
|
|
||||||
* @param float $width Width in px
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setBorderWidth($width)
|
|
||||||
{
|
|
||||||
$this->borderWidth = $width;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the color of the pie chart border
|
|
||||||
*
|
|
||||||
* @param string $col The color string
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setBorderColor($col)
|
|
||||||
{
|
|
||||||
$this->borderColor = $col;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the width
|
|
||||||
*
|
|
||||||
* @param $width
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setWidth($width)
|
|
||||||
{
|
|
||||||
$this->width = $width;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the styling of the created HtmlElement
|
|
||||||
*
|
|
||||||
* @param string $style
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setStyle($style)
|
|
||||||
{
|
|
||||||
$this->style = $style;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the title of the displayed Data
|
* Set the title of the displayed Data
|
||||||
*
|
*
|
||||||
@ -322,7 +157,7 @@ EOD;
|
|||||||
*/
|
*/
|
||||||
public function setTitle($title)
|
public function setTitle($title)
|
||||||
{
|
{
|
||||||
$this->title = $title;
|
$this->title = 'title="' . htmlspecialchars($title) . '"';
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,13 +170,10 @@ EOD;
|
|||||||
*/
|
*/
|
||||||
public function __construct(array $data, $title, $colors = null)
|
public function __construct(array $data, $title, $colors = null)
|
||||||
{
|
{
|
||||||
$this->title = $title;
|
$this->setTitle($title);
|
||||||
$this->url = Url::fromPath('svg/chart.php');
|
$this->url = Url::fromPath('svg/chart.php');
|
||||||
if (array_key_exists('data', $data)) {
|
if (array_key_exists('data', $data)) {
|
||||||
$this->data = $data['data'];
|
$this->data = $data['data'];
|
||||||
if (array_key_exists('labels', $data)) {
|
|
||||||
$this->labels = $data['labels'];
|
|
||||||
}
|
|
||||||
if (array_key_exists('colors', $data)) {
|
if (array_key_exists('colors', $data)) {
|
||||||
$this->colors = $data['colors'];
|
$this->colors = $data['colors'];
|
||||||
}
|
}
|
||||||
@ -354,21 +186,6 @@ EOD;
|
|||||||
$this->setColors($this->colors);
|
$this->setColors($this->colors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a serialization containing the current label array
|
|
||||||
*
|
|
||||||
* @return string A serialized array of labels
|
|
||||||
*/
|
|
||||||
private function createLabelString ()
|
|
||||||
{
|
|
||||||
$labels = $this->labels;
|
|
||||||
foreach ($labels as $key => $label) {
|
|
||||||
$labels[$key] = str_replace('|', '', $label);
|
|
||||||
}
|
|
||||||
return isset($this->labels) && is_array($this->labels) ? implode('|', $this->labels) : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders this widget via the given view and returns the
|
* Renders this widget via the given view and returns the
|
||||||
* HTML as a string
|
* HTML as a string
|
||||||
@ -382,11 +199,11 @@ EOD;
|
|||||||
$pie->alignTopLeft();
|
$pie->alignTopLeft();
|
||||||
$pie->disableLegend();
|
$pie->disableLegend();
|
||||||
$pie->drawPie(array(
|
$pie->drawPie(array(
|
||||||
'data' => $this->data, 'colors' => $this->colors, 'labels' => $this->labels
|
'data' => $this->data, 'colors' => $this->colors
|
||||||
));
|
));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$png = $pie->toPng($this->width, $this->height);
|
$png = $pie->toPng($this->size, $this->size);
|
||||||
return '<img class="inlinepie" src="data:image/png;base64,' . base64_encode($png) . '" />';
|
return '<img class="inlinepie" src="data:image/png;base64,' . base64_encode($png) . '" />';
|
||||||
} catch (IcingaException $_) {
|
} catch (IcingaException $_) {
|
||||||
return '';
|
return '';
|
||||||
@ -394,17 +211,17 @@ EOD;
|
|||||||
}
|
}
|
||||||
|
|
||||||
$template = $this->template;
|
$template = $this->template;
|
||||||
|
// TODO: Check whether we are XHR and don't send
|
||||||
|
$template = str_replace('{noscript}', $this->noscript, $template);
|
||||||
$template = str_replace('{url}', $this->url, $template);
|
$template = str_replace('{url}', $this->url, $template);
|
||||||
|
$template = str_replace('{class}', $this->class, $template);
|
||||||
|
|
||||||
// style
|
// style
|
||||||
$template = str_replace('{width}', $this->width, $template);
|
$template = str_replace('{size}',
|
||||||
$template = str_replace('{height}', $this->height, $template);
|
isset($this->size) ? 'sparkWidth="' . $this->size . '" sparkHeight="' . $this->size . '" ' : '', $template);
|
||||||
$template = str_replace('{title}', htmlspecialchars($this->title), $template);
|
$template = str_replace('{title}', $this->title, $template);
|
||||||
$template = str_replace('{style}', $this->style, $template);
|
|
||||||
$template = str_replace('{colors}', implode(',', $this->colors), $template);
|
$template = str_replace('{colors}', implode(',', $this->colors), $template);
|
||||||
$template = str_replace('{borderWidth}', $this->borderWidth, $template);
|
|
||||||
$template = str_replace('{borderColor}', $this->borderColor, $template);
|
|
||||||
$template = str_replace('{hideEmptyLabel}', $this->hideEmptyLabel ? 'true' : 'false', $template);
|
|
||||||
|
|
||||||
// Locale-ignorant string cast. Please. Do. NOT. Remove. This. Again.
|
// Locale-ignorant string cast. Please. Do. NOT. Remove. This. Again.
|
||||||
// Problem is that implode respects locales when casting floats. This means
|
// Problem is that implode respects locales when casting floats. This means
|
||||||
@ -414,38 +231,7 @@ EOD;
|
|||||||
$data[] = sprintf('%F', $dat);
|
$data[] = sprintf('%F', $dat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// values
|
|
||||||
$formatted = array();
|
|
||||||
foreach ($this->data as $key => $value) {
|
|
||||||
$formatted[$key] = $this->formatValue($value);
|
|
||||||
}
|
|
||||||
$template = str_replace('{data}', htmlspecialchars(implode(',', $data)), $template);
|
$template = str_replace('{data}', htmlspecialchars(implode(',', $data)), $template);
|
||||||
$template = str_replace('{formatted}', htmlspecialchars(implode('|', $formatted)), $template);
|
|
||||||
$template = str_replace('{labels}', htmlspecialchars($this->createLabelString()), $template);
|
|
||||||
$template = str_replace('{tooltipFormat}', $this->tooltipFormat, $template);
|
|
||||||
return $template;
|
return $template;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Format the given value depending on the current value of numberFormat
|
|
||||||
*
|
|
||||||
* @param float $value The value to format
|
|
||||||
*
|
|
||||||
* @return string The formatted value
|
|
||||||
*/
|
|
||||||
private function formatValue($value)
|
|
||||||
{
|
|
||||||
if ($this->format === self::NUMBER_FORMAT_NONE) {
|
|
||||||
return (string)$value;
|
|
||||||
} elseif ($this->format === self::NUMBER_FORMAT_BYTES) {
|
|
||||||
return Format::bytes($value);
|
|
||||||
} elseif ($this->format === self::NUMBER_FORMAT_TIME) {
|
|
||||||
return Format::duration($value);
|
|
||||||
} elseif ($this->format === self::NUMBER_FORMAT_RATIO) {
|
|
||||||
return $value;
|
|
||||||
} else {
|
|
||||||
Logger::warning('Unknown format string "' . $this->format . '" for InlinePie, value not formatted.');
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -218,6 +218,25 @@ EOT;
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a tab
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function remove($name)
|
||||||
|
{
|
||||||
|
if ($this->has($name)) {
|
||||||
|
unset($this->tabs[$name]);
|
||||||
|
if (($dropdownIndex = array_search($name, $this->dropdownTabs)) !== false) {
|
||||||
|
array_splice($this->dropdownTabs, $dropdownIndex, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a tab to the dropdown on the right side of the tab-bar.
|
* Add a tab to the dropdown on the right side of the tab-bar.
|
||||||
*
|
*
|
||||||
|
@ -39,6 +39,13 @@ class Wizard
|
|||||||
*/
|
*/
|
||||||
const BTN_PREV = 'btn_prev';
|
const BTN_PREV = 'btn_prev';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This wizard's parent
|
||||||
|
*
|
||||||
|
* @var Wizard
|
||||||
|
*/
|
||||||
|
protected $parent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the wizard's current page
|
* The name of the wizard's current page
|
||||||
*
|
*
|
||||||
@ -71,19 +78,55 @@ class Wizard
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return this wizard's parent or null in case it has none
|
||||||
|
*
|
||||||
|
* @return Wizard|null
|
||||||
|
*/
|
||||||
|
public function getParent()
|
||||||
|
{
|
||||||
|
return $this->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this wizard's parent
|
||||||
|
*
|
||||||
|
* @param Wizard $wizard The parent wizard
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setParent(Wizard $wizard)
|
||||||
|
{
|
||||||
|
$this->parent = $wizard;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the pages being part of this wizard
|
* Return the pages being part of this wizard
|
||||||
*
|
*
|
||||||
|
* In case this is a nested wizard a flattened array of all contained pages is returned.
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getPages()
|
public function getPages()
|
||||||
{
|
{
|
||||||
return $this->pages;
|
$pages = array();
|
||||||
|
foreach ($this->pages as $page) {
|
||||||
|
if ($page instanceof self) {
|
||||||
|
$pages = array_merge($pages, $page->getPages());
|
||||||
|
} else {
|
||||||
|
$pages[] = $page;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the page with the given name
|
* Return the page with the given name
|
||||||
*
|
*
|
||||||
|
* Note that it's also possible to retrieve a nested wizard's page by using this method.
|
||||||
|
*
|
||||||
* @param string $name The name of the page to return
|
* @param string $name The name of the page to return
|
||||||
*
|
*
|
||||||
* @return null|Form The page or null in case there is no page with the given name
|
* @return null|Form The page or null in case there is no page with the given name
|
||||||
@ -98,22 +141,31 @@ class Wizard
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new page to this wizard
|
* Add a new page or wizard to this wizard
|
||||||
*
|
*
|
||||||
* @param Form $page The page to add to the wizard
|
* @param Form|Wizard $page The page or wizard to add to the wizard
|
||||||
*
|
*
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public function addPage(Form $page)
|
public function addPage($page)
|
||||||
{
|
{
|
||||||
|
if (! $page instanceof Form && ! $page instanceof self) {
|
||||||
|
throw InvalidArgumentException(
|
||||||
|
'The $page argument must be an instance of Icinga\Web\Form '
|
||||||
|
. 'or Icinga\Web\Wizard but is of type: ' . get_class($page)
|
||||||
|
);
|
||||||
|
} elseif ($page instanceof self) {
|
||||||
|
$page->setParent($this);
|
||||||
|
}
|
||||||
|
|
||||||
$this->pages[] = $page;
|
$this->pages[] = $page;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add multiple pages to this wizard
|
* Add multiple pages or wizards to this wizard
|
||||||
*
|
*
|
||||||
* @param array $pages The pages to add to the wizard
|
* @param array $pages The pages or wizards to add to the wizard
|
||||||
*
|
*
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
@ -148,6 +200,10 @@ class Wizard
|
|||||||
*/
|
*/
|
||||||
public function getCurrentPage()
|
public function getCurrentPage()
|
||||||
{
|
{
|
||||||
|
if ($this->parent) {
|
||||||
|
return $this->parent->getCurrentPage();
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->currentPage === null) {
|
if ($this->currentPage === null) {
|
||||||
$this->assertHasPages();
|
$this->assertHasPages();
|
||||||
$pages = $this->getPages();
|
$pages = $this->getPages();
|
||||||
@ -202,6 +258,10 @@ class Wizard
|
|||||||
{
|
{
|
||||||
$page = $this->getCurrentPage();
|
$page = $this->getCurrentPage();
|
||||||
|
|
||||||
|
if (($wizard = $this->findWizard($page)) !== null) {
|
||||||
|
return $wizard->handleRequest($request);
|
||||||
|
}
|
||||||
|
|
||||||
if ($request === null) {
|
if ($request === null) {
|
||||||
$request = $page->getRequest();
|
$request = $page->getRequest();
|
||||||
}
|
}
|
||||||
@ -238,6 +298,39 @@ class Wizard
|
|||||||
return $request;
|
return $request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the wizard for the given page or null if its not part of a wizard
|
||||||
|
*
|
||||||
|
* @param Form $page The page to return its wizard for
|
||||||
|
*
|
||||||
|
* @return Wizard|null
|
||||||
|
*/
|
||||||
|
protected function findWizard(Form $page)
|
||||||
|
{
|
||||||
|
foreach ($this->getWizards() as $wizard) {
|
||||||
|
if ($wizard->getPage($page->getName()) === $page) {
|
||||||
|
return $wizard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return this wizard's child wizards
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getWizards()
|
||||||
|
{
|
||||||
|
$wizards = array();
|
||||||
|
foreach ($this->pages as $pageOrWizard) {
|
||||||
|
if ($pageOrWizard instanceof self) {
|
||||||
|
$wizards[] = $pageOrWizard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $wizards;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the request data based on given form's request method
|
* Return the request data based on given form's request method
|
||||||
*
|
*
|
||||||
@ -264,6 +357,10 @@ class Wizard
|
|||||||
*/
|
*/
|
||||||
protected function getRequestedPage(array $requestData)
|
protected function getRequestedPage(array $requestData)
|
||||||
{
|
{
|
||||||
|
if ($this->parent) {
|
||||||
|
return $this->parent->getRequestedPage($requestData);
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($requestData[static::BTN_NEXT])) {
|
if (isset($requestData[static::BTN_NEXT])) {
|
||||||
return $requestData[static::BTN_NEXT];
|
return $requestData[static::BTN_NEXT];
|
||||||
} elseif (isset($requestData[static::BTN_PREV])) {
|
} elseif (isset($requestData[static::BTN_PREV])) {
|
||||||
@ -280,6 +377,10 @@ class Wizard
|
|||||||
*/
|
*/
|
||||||
protected function getDirection(Request $request = null)
|
protected function getDirection(Request $request = null)
|
||||||
{
|
{
|
||||||
|
if ($this->parent) {
|
||||||
|
return $this->parent->getDirection($request);
|
||||||
|
}
|
||||||
|
|
||||||
$currentPage = $this->getCurrentPage();
|
$currentPage = $this->getCurrentPage();
|
||||||
|
|
||||||
if ($request === null) {
|
if ($request === null) {
|
||||||
@ -299,7 +400,7 @@ class Wizard
|
|||||||
/**
|
/**
|
||||||
* Return the new page to set as current page
|
* Return the new page to set as current page
|
||||||
*
|
*
|
||||||
* Permission is checked by verifying that the requested page's previous page has page data available.
|
* Permission is checked by verifying that the requested page or its previous page has page data available.
|
||||||
* The requested page is automatically permitted without any checks if the origin page is its previous
|
* The requested page is automatically permitted without any checks if the origin page is its previous
|
||||||
* page or one that occurs later in order.
|
* page or one that occurs later in order.
|
||||||
*
|
*
|
||||||
@ -312,11 +413,15 @@ class Wizard
|
|||||||
*/
|
*/
|
||||||
protected function getNewPage($requestedPage, Form $originPage)
|
protected function getNewPage($requestedPage, Form $originPage)
|
||||||
{
|
{
|
||||||
|
if ($this->parent) {
|
||||||
|
return $this->parent->getNewPage($requestedPage, $originPage);
|
||||||
|
}
|
||||||
|
|
||||||
if (($page = $this->getPage($requestedPage)) !== null) {
|
if (($page = $this->getPage($requestedPage)) !== null) {
|
||||||
$permitted = true;
|
$permitted = true;
|
||||||
|
|
||||||
$pages = $this->getPages();
|
$pages = $this->getPages();
|
||||||
if (($index = array_search($page, $pages, true)) > 0) {
|
if (! $this->hasPageData($requestedPage) && ($index = array_search($page, $pages, true)) > 0) {
|
||||||
$previousPage = $pages[$index - 1];
|
$previousPage = $pages[$index - 1];
|
||||||
if ($originPage === null || ($previousPage->getName() !== $originPage->getName()
|
if ($originPage === null || ($previousPage->getName() !== $originPage->getName()
|
||||||
&& array_search($originPage, $pages, true) < $index))
|
&& array_search($originPage, $pages, true) < $index))
|
||||||
@ -335,6 +440,36 @@ class Wizard
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the next or previous page based on the given one
|
||||||
|
*
|
||||||
|
* @param Form $page The page to skip
|
||||||
|
*
|
||||||
|
* @return Form
|
||||||
|
*/
|
||||||
|
protected function skipPage(Form $page)
|
||||||
|
{
|
||||||
|
if ($this->parent) {
|
||||||
|
return $this->parent->skipPage($page);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->hasPageData($page->getName())) {
|
||||||
|
$pageData = & $this->getPageData();
|
||||||
|
unset($pageData[$page->getName()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pages = $this->getPages();
|
||||||
|
if ($this->getDirection() === static::FORWARD) {
|
||||||
|
$nextPage = $pages[array_search($page, $pages, true) + 1];
|
||||||
|
$newPage = $this->getNewPage($nextPage->getName(), $page);
|
||||||
|
} else { // $this->getDirection() === static::BACKWARD
|
||||||
|
$previousPage = $pages[array_search($page, $pages, true) - 1];
|
||||||
|
$newPage = $this->getNewPage($previousPage->getName(), $page);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $newPage;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether the given page is this wizard's last page
|
* Return whether the given page is this wizard's last page
|
||||||
*
|
*
|
||||||
@ -344,10 +479,27 @@ class Wizard
|
|||||||
*/
|
*/
|
||||||
protected function isLastPage(Form $page)
|
protected function isLastPage(Form $page)
|
||||||
{
|
{
|
||||||
|
if ($this->parent) {
|
||||||
|
return $this->parent->isLastPage($page);
|
||||||
|
}
|
||||||
|
|
||||||
$pages = $this->getPages();
|
$pages = $this->getPages();
|
||||||
return $page->getName() === end($pages)->getName();
|
return $page->getName() === end($pages)->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether all of this wizard's pages were visited by the user
|
||||||
|
*
|
||||||
|
* The base implementation just verifies that the very last page has page data available.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isComplete()
|
||||||
|
{
|
||||||
|
$pages = $this->getPages();
|
||||||
|
return $this->hasPageData($pages[count($pages) - 1]->getName());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether this wizard has been completed
|
* Set whether this wizard has been completed
|
||||||
*
|
*
|
||||||
@ -421,6 +573,10 @@ class Wizard
|
|||||||
*/
|
*/
|
||||||
public function getSession()
|
public function getSession()
|
||||||
{
|
{
|
||||||
|
if ($this->parent) {
|
||||||
|
return $this->parent->getSession();
|
||||||
|
}
|
||||||
|
|
||||||
return Session::getSession()->getNamespace(get_class($this));
|
return Session::getSession()->getNamespace(get_class($this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
library/vendor/Parsedown/SOURCE
vendored
1
library/vendor/Parsedown/SOURCE
vendored
@ -4,3 +4,4 @@ DESTINATION=.
|
|||||||
wget -O ${FILENAME}.tar.gz https://github.com/erusev/parsedown/archive/${RELEASE}.tar.gz
|
wget -O ${FILENAME}.tar.gz https://github.com/erusev/parsedown/archive/${RELEASE}.tar.gz
|
||||||
tar xfz ${FILENAME}.tar.gz -C $DESTINATION/ --strip-components 1 $FILENAME/Parsedown.php $FILENAME/LICENSE.txt
|
tar xfz ${FILENAME}.tar.gz -C $DESTINATION/ --strip-components 1 $FILENAME/Parsedown.php $FILENAME/LICENSE.txt
|
||||||
chmod 644 $DESTINATION/Parsedown.php
|
chmod 644 $DESTINATION/Parsedown.php
|
||||||
|
mv LICENSE.txt LICENSE
|
||||||
|
1
library/vendor/dompdf/SOURCE
vendored
1
library/vendor/dompdf/SOURCE
vendored
@ -1,6 +1,7 @@
|
|||||||
curl https://codeload.github.com/dompdf/dompdf/tar.gz/v0.6.1 -o dompdf-0.6.1.tar.gz
|
curl https://codeload.github.com/dompdf/dompdf/tar.gz/v0.6.1 -o dompdf-0.6.1.tar.gz
|
||||||
tar xzf dompdf-0.6.1.tar.gz --strip-components 1 dompdf-0.6.1/{include/*.php,lib,dompdf*.php,LICENSE.LGPL}
|
tar xzf dompdf-0.6.1.tar.gz --strip-components 1 dompdf-0.6.1/{include/*.php,lib,dompdf*.php,LICENSE.LGPL}
|
||||||
rm dompdf-0.6.1.tar.gz
|
rm dompdf-0.6.1.tar.gz
|
||||||
|
mv LICENSE.LGPL LICENSE
|
||||||
|
|
||||||
curl https://codeload.github.com/PhenX/php-font-lib/tar.gz/0.3.1 -o php-font-lib-0.3.1.tar.gz
|
curl https://codeload.github.com/PhenX/php-font-lib/tar.gz/0.3.1 -o php-font-lib-0.3.1.tar.gz
|
||||||
mkdir lib/php-font-lib/classes
|
mkdir lib/php-font-lib/classes
|
||||||
|
@ -8,12 +8,36 @@ use Icinga\Module\Doc\DocController;
|
|||||||
|
|
||||||
class Doc_IcingawebController extends DocController
|
class Doc_IcingawebController extends DocController
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Get the path to Icinga Web 2's documentation
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @throws Zend_Controller_Action_Exception If Icinga Web 2's documentation is not available
|
||||||
|
*/
|
||||||
|
protected function getPath()
|
||||||
|
{
|
||||||
|
$path = Icinga::app()->getBaseDir('doc');
|
||||||
|
if (is_dir($path)) {
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
|
if (($path = $this->Config()->get('documentation', 'icingaweb2')) !== null) {
|
||||||
|
if (is_dir($path)) {
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Zend_Controller_Action_Exception(
|
||||||
|
$this->translate('Documentation for Icinga Web 2 is not available'),
|
||||||
|
404
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View the toc of Icinga Web 2's documentation
|
* View the toc of Icinga Web 2's documentation
|
||||||
*/
|
*/
|
||||||
public function tocAction()
|
public function tocAction()
|
||||||
{
|
{
|
||||||
return $this->renderToc(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2', 'doc/icingaweb/chapter');
|
$this->renderToc($this->getPath(), 'Icinga Web 2', 'doc/icingaweb/chapter');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,12 +50,12 @@ class Doc_IcingawebController extends DocController
|
|||||||
$chapterId = $this->getParam('chapterId');
|
$chapterId = $this->getParam('chapterId');
|
||||||
if ($chapterId === null) {
|
if ($chapterId === null) {
|
||||||
throw new Zend_Controller_Action_Exception(
|
throw new Zend_Controller_Action_Exception(
|
||||||
$this->translate('Missing parameter \'chapterId\''),
|
sprintf($this->translate('Missing parameter \'%s\''), 'chapterId'),
|
||||||
404
|
404
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return $this->renderChapter(
|
$this->renderChapter(
|
||||||
Icinga::app()->getApplicationDir('/../doc'),
|
$this->getPath(),
|
||||||
$chapterId,
|
$chapterId,
|
||||||
'doc/icingaweb/toc',
|
'doc/icingaweb/toc',
|
||||||
'doc/icingaweb/chapter'
|
'doc/icingaweb/chapter'
|
||||||
@ -43,6 +67,6 @@ class Doc_IcingawebController extends DocController
|
|||||||
*/
|
*/
|
||||||
public function pdfAction()
|
public function pdfAction()
|
||||||
{
|
{
|
||||||
return $this->renderPdf(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2', 'doc/icingaweb/chapter');
|
$this->renderPdf($this->getPath(), 'Icinga Web 2', 'doc/icingaweb/chapter');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,40 @@ use Icinga\Module\Doc\Exception\DocException;
|
|||||||
|
|
||||||
class Doc_ModuleController extends DocController
|
class Doc_ModuleController extends DocController
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Get the path to a module documentation
|
||||||
|
*
|
||||||
|
* @param string $module The name of the module
|
||||||
|
* @param string $default The default path
|
||||||
|
* @param bool $suppressErrors Whether to not throw an exception if the module documentation is not
|
||||||
|
* available
|
||||||
|
*
|
||||||
|
* @return string|null Path to the documentation or null if the module documentation is not
|
||||||
|
* available and errors are suppressed
|
||||||
|
*
|
||||||
|
* @throws Zend_Controller_Action_Exception If the module documentation is not available and errors are not
|
||||||
|
* suppressed
|
||||||
|
*/
|
||||||
|
protected function getPath($module, $default, $suppressErrors = false)
|
||||||
|
{
|
||||||
|
if (is_dir($default)) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
if (($path = $this->Config()->get('documentation', 'modules')) !== null) {
|
||||||
|
$path = str_replace('{module}', $module, $path);
|
||||||
|
if (is_dir($path)) {
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($suppressErrors) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
throw new Zend_Controller_Action_Exception(
|
||||||
|
sprintf($this->translate('Documentation for module \'%s\' is not available'), $module),
|
||||||
|
404
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List modules which are enabled and having the 'doc' directory
|
* List modules which are enabled and having the 'doc' directory
|
||||||
*/
|
*/
|
||||||
@ -16,10 +50,10 @@ class Doc_ModuleController extends DocController
|
|||||||
{
|
{
|
||||||
$moduleManager = Icinga::app()->getModuleManager();
|
$moduleManager = Icinga::app()->getModuleManager();
|
||||||
$modules = array();
|
$modules = array();
|
||||||
foreach (Icinga::app()->getModuleManager()->listEnabledModules() as $enabledModule) {
|
foreach (Icinga::app()->getModuleManager()->listEnabledModules() as $module) {
|
||||||
$docDir = $moduleManager->getModuleDir($enabledModule, '/doc');
|
$path = $this->getPath($module, $moduleManager->getModuleDir($module, '/doc'), true);
|
||||||
if (is_dir($docDir)) {
|
if ($path !== null) {
|
||||||
$modules[] = $enabledModule;
|
$modules[] = $module;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->view->modules = $modules;
|
$this->view->modules = $modules;
|
||||||
@ -37,7 +71,7 @@ class Doc_ModuleController extends DocController
|
|||||||
{
|
{
|
||||||
if (empty($moduleName)) {
|
if (empty($moduleName)) {
|
||||||
throw new Zend_Controller_Action_Exception(
|
throw new Zend_Controller_Action_Exception(
|
||||||
$this->translate('Missing parameter \'moduleName\''),
|
sprintf($this->translate('Missing parameter \'%s\''), 'moduleName'),
|
||||||
404
|
404
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -63,16 +97,15 @@ class Doc_ModuleController extends DocController
|
|||||||
*/
|
*/
|
||||||
public function tocAction()
|
public function tocAction()
|
||||||
{
|
{
|
||||||
$moduleName = $this->getParam('moduleName');
|
$module = $this->getParam('moduleName');
|
||||||
$this->assertModuleEnabled($moduleName);
|
$this->assertModuleEnabled($module);
|
||||||
$this->view->moduleName = $moduleName;
|
$this->view->moduleName = $module;
|
||||||
$moduleManager = Icinga::app()->getModuleManager();
|
|
||||||
try {
|
try {
|
||||||
return $this->renderToc(
|
$this->renderToc(
|
||||||
$moduleManager->getModuleDir($moduleName, '/doc'),
|
$this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')),
|
||||||
$moduleName,
|
$module,
|
||||||
'doc/module/chapter',
|
'doc/module/chapter',
|
||||||
array('moduleName' => $moduleName)
|
array('moduleName' => $module)
|
||||||
);
|
);
|
||||||
} catch (DocException $e) {
|
} catch (DocException $e) {
|
||||||
throw new Zend_Controller_Action_Exception($e->getMessage(), 404);
|
throw new Zend_Controller_Action_Exception($e->getMessage(), 404);
|
||||||
@ -88,24 +121,23 @@ class Doc_ModuleController extends DocController
|
|||||||
*/
|
*/
|
||||||
public function chapterAction()
|
public function chapterAction()
|
||||||
{
|
{
|
||||||
$moduleName = $this->getParam('moduleName');
|
$module = $this->getParam('moduleName');
|
||||||
$this->assertModuleEnabled($moduleName);
|
$this->assertModuleEnabled($module);
|
||||||
$chapterId = $this->getParam('chapterId');
|
$chapterId = $this->getParam('chapterId');
|
||||||
if ($chapterId === null) {
|
if ($chapterId === null) {
|
||||||
throw new Zend_Controller_Action_Exception(
|
throw new Zend_Controller_Action_Exception(
|
||||||
$this->translate('Missing parameter \'chapterId\''),
|
sprintf($this->translate('Missing parameter \'%s\''), 'chapterId'),
|
||||||
404
|
404
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$this->view->moduleName = $moduleName;
|
$this->view->moduleName = $module;
|
||||||
$moduleManager = Icinga::app()->getModuleManager();
|
|
||||||
try {
|
try {
|
||||||
return $this->renderChapter(
|
$this->renderChapter(
|
||||||
$moduleManager->getModuleDir($moduleName, '/doc'),
|
$this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')),
|
||||||
$chapterId,
|
$chapterId,
|
||||||
$this->_helper->url->url(array('moduleName' => $moduleName), 'doc/module/toc'),
|
$this->_helper->url->url(array('moduleName' => $module), 'doc/module/toc'),
|
||||||
'doc/module/chapter',
|
'doc/module/chapter',
|
||||||
array('moduleName' => $moduleName)
|
array('moduleName' => $module)
|
||||||
);
|
);
|
||||||
} catch (DocException $e) {
|
} catch (DocException $e) {
|
||||||
throw new Zend_Controller_Action_Exception($e->getMessage(), 404);
|
throw new Zend_Controller_Action_Exception($e->getMessage(), 404);
|
||||||
@ -119,14 +151,13 @@ class Doc_ModuleController extends DocController
|
|||||||
*/
|
*/
|
||||||
public function pdfAction()
|
public function pdfAction()
|
||||||
{
|
{
|
||||||
$moduleName = $this->getParam('moduleName');
|
$module = $this->getParam('moduleName');
|
||||||
$this->assertModuleEnabled($moduleName);
|
$this->assertModuleEnabled($module);
|
||||||
$moduleManager = Icinga::app()->getModuleManager();
|
$this->renderPdf(
|
||||||
return $this->renderPdf(
|
$this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')),
|
||||||
$moduleManager->getModuleDir($moduleName, '/doc'),
|
$module,
|
||||||
$moduleName,
|
|
||||||
'doc/module/chapter',
|
'doc/module/chapter',
|
||||||
array('moduleName' => $moduleName)
|
array('moduleName' => $module)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// {{{ICINGA_LICENSE_HEADER}}}
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
// {{{ICINGA_LICENSE_HEADER}}}
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
/* @var $this \Icinga\Application\Modules\Module */
|
/** @type $this \Icinga\Application\Modules\Module */
|
||||||
|
|
||||||
$section = $this->menuSection($this->translate('Documentation'), array(
|
$section = $this->menuSection($this->translate('Documentation'), array(
|
||||||
'title' => 'Documentation',
|
'title' => 'Documentation',
|
||||||
|
67
modules/doc/doc/1-module-documentation.md
Normal file
67
modules/doc/doc/1-module-documentation.md
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# <a id="module-documentation"></a> Writing Module Documentation
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Icinga Web 2 is capable of viewing your module's documentation, if the documentation is written in
|
||||||
|
[Markdown](http://en.wikipedia.org/wiki/Markdown). Please refer to
|
||||||
|
[Markdown Syntax Documentation](http://daringfireball.net/projects/markdown/syntax) for Markdown's formatting syntax.
|
||||||
|
|
||||||
|
## <a id="location"></a> Where to Put Module Documentation?
|
||||||
|
|
||||||
|
By default, your module's Markdown documentation files must be placed in the `doc` directory beneath your module's root
|
||||||
|
directory, e.g.:
|
||||||
|
|
||||||
|
example-module/doc
|
||||||
|
|
||||||
|
## <a id="chapters"></a> Chapters
|
||||||
|
|
||||||
|
Each Markdown documentation file represents a chapter of your module's documentation. The first found heading inside
|
||||||
|
each file is the chapter's title. The order of chapters is based on the case insensitive "Natural Order" of your files'
|
||||||
|
names. <dfn>Natural Order</dfn> means that the file names are ordered in the way which seems natural to humans.
|
||||||
|
It is best practice to prefix Markdown documentation file names with numbers to ensure that they appear in the correct
|
||||||
|
order, e.g.:
|
||||||
|
|
||||||
|
1-about.md
|
||||||
|
2-installation.md
|
||||||
|
3-configuration.md
|
||||||
|
|
||||||
|
## <a id="toc"></a> Table Of Contents
|
||||||
|
|
||||||
|
The table of contents for your module's documentation is auto-generated based on all found headings inside each
|
||||||
|
Markdown documentation file.
|
||||||
|
|
||||||
|
## <a id="linking"></a> Linking Between Headings
|
||||||
|
|
||||||
|
For linking between headings, place an anchor where you want to link to, e.g.:
|
||||||
|
|
||||||
|
# <a id="heading"></a> Heading
|
||||||
|
|
||||||
|
Please note that anchors have to be unique across all your Markdown documentation files.
|
||||||
|
|
||||||
|
Now you can reference the anchor either in the same or **in another** Markdown documentation file, e.g.:
|
||||||
|
|
||||||
|
This is a link to [Heading](#heading).
|
||||||
|
|
||||||
|
Other tools support linking between headings by giving the filename plus the anchor to link to, e.g.:
|
||||||
|
|
||||||
|
This is a link to [About/Heading](1-about.md#heading.md)
|
||||||
|
|
||||||
|
This syntax is also supported in Icinga Web 2.
|
||||||
|
|
||||||
|
## <a id="images"></a> Including Images
|
||||||
|
|
||||||
|
Images must placed in the `img` directory beneath your module's `public` directory, e.g.:
|
||||||
|
|
||||||
|
example-module/public/img/doc
|
||||||
|
|
||||||
|
Module images can be accessed using the following URL:
|
||||||
|
|
||||||
|
{baseURL}/img/{moduleName}/{file} e.g. icingaweb/img/example-module/doc/example.png
|
||||||
|
|
||||||
|
Markdown's image syntax is very similar to Markdown's link syntax, but prefixed with an exclamation mark, e.g.:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
URLs to images inside your Markdown documentation files must be specified without the base URL, e.g.:
|
||||||
|
|
||||||
|

|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user