diff --git a/application/controllers/HostController.php b/application/controllers/HostController.php index 198599b0..18e1704e 100644 --- a/application/controllers/HostController.php +++ b/application/controllers/HostController.php @@ -29,7 +29,11 @@ class HostController extends ObjectController { protected function checkDirectorPermissions() { - if (in_array($this->getRequest()->getActionName(), ['servicesro', 'findservice'])) { + if (in_array($this->getRequest()->getActionName(), [ + 'servicesro', + 'findservice', + 'invalidservice' + ])) { $this->assertPermission('director/monitoring/services-ro'); } else { $this->assertPermission('director/hosts'); @@ -97,22 +101,14 @@ class HostController extends ObjectController /** * @throws \Icinga\Exception\NotFoundError - * @throws \Icinga\Security\SecurityException */ public function findserviceAction() { $host = $this->getHostObject(); $redirector = new HostServiceRedirector($host, $this->getAuth()); - if ($this->hasPermission('director/hosts')) { - $this->redirectNow( - $redirector->getRedirectionUrl($this->params->get('service')) - ); - return; - } elseif ($this->hasPermission('director/monitoring/services-ro')) { - $this->redirectNow($this->url()->setPath('director/host/servicesro')); - } else { - $this->assertPermission('director/hosts'); - } + $this->redirectNow( + $redirector->getRedirectionUrl($this->params->get('service')) + ); } /** @@ -198,6 +194,10 @@ class HostController extends ObjectController } /** + * Hint: this duplicates quite some logic from servicesAction. We might want + * to clean this up, but as soon as we store fully resolved Services this + * will be obsolete anyways + * * @throws \Icinga\Exception\NotFoundError * @throws \Icinga\Security\SecurityException * @throws \Icinga\Exception\MissingParameterException @@ -209,11 +209,12 @@ class HostController extends ObjectController $service = $this->params->getRequired('service'); $db = $this->db(); $this->controls()->setTabs(new Tabs()); - $this->addSingleTab($this->translate('Configuration: Services')); - $this->addTitle($this->translate('Services: %s'), $host->getObjectName()); + $this->addSingleTab($this->translate('Configuration (read-only)')); + $this->addTitle($this->translate('Services on %s'), $host->getObjectName()); $content = $this->content(); $table = IcingaHostServiceTable::load($host) ->setReadonly() + ->highlightService($service) ->setTitle($this->translate('Individual Service objects')); if (count($table)) { @@ -224,6 +225,7 @@ class HostController extends ObjectController if ($applied instanceof CustomVariableDictionary) { $table = IcingaHostAppliedForServiceTable::load($host, $applied) ->setReadonly() + ->highlightService($service) ->setTitle($this->translate('Generated from host vars')); if (count($table)) { $content->add($table); @@ -237,6 +239,7 @@ class HostController extends ObjectController foreach ($parents as $parent) { $table = IcingaHostServiceTable::load($parent) ->setReadonly() + ->highlightService($service) ->setInheritedBy($host); if (count($table)) { $content->add( @@ -262,11 +265,14 @@ class HostController extends ObjectController // ->setHost($host) ->setAffectedHost($host) ->setReadonly() + ->highlightService($service) ->setTitle($title) ); } $table = IcingaHostAppliedServicesTable::load($host) + ->setReadonly() + ->highlightService($service) ->setTitle($this->translate('Applied services')); if (count($table)) { @@ -308,7 +314,7 @@ class HostController extends ObjectController ->setAffectedHost($affectedHost) ->setTitle($title); if ($roService) { - $table->setReadonly(); + $table->setReadonly()->highlightService($roService); } $this->content()->add($table); } diff --git a/doc/82-Changelog.md b/doc/82-Changelog.md index 395e5ab6..c44a51ef 100644 --- a/doc/82-Changelog.md +++ b/doc/82-Changelog.md @@ -15,6 +15,7 @@ before switching to a new version. * FIX: creating a new Basket with a "Custom Selection" failed with an error (#1733) * FIX: some new reserved keywords are now escaped correctly (#1765) * FIX: correctly render NOT used in apply rules (fixes #1777) +* FEATURE: RO users could want to see where a configured service originated (#1785) 1.6.0 ----- diff --git a/library/Director/Web/Table/IcingaHostAppliedForServiceTable.php b/library/Director/Web/Table/IcingaHostAppliedForServiceTable.php index 8203478d..a2e26eb4 100644 --- a/library/Director/Web/Table/IcingaHostAppliedForServiceTable.php +++ b/library/Director/Web/Table/IcingaHostAppliedForServiceTable.php @@ -2,6 +2,7 @@ namespace Icinga\Module\Director\Web\Table; +use dipl\Html\Html; use Icinga\Data\DataArray\ArrayDatasource; use Icinga\Module\Director\CustomVariable\CustomVariableDictionary; use Icinga\Module\Director\Objects\IcingaHost; @@ -24,6 +25,9 @@ class IcingaHostAppliedForServiceTable extends SimpleQueryBasedTable /** @var bool */ protected $readonly = false; + /** @var string|null */ + protected $highlightedService; + /** * @param IcingaHost $host * @param CustomVariableDictionary $dict @@ -67,23 +71,29 @@ class IcingaHostAppliedForServiceTable extends SimpleQueryBasedTable return $this; } + public function highlightService($service) + { + $this->highlightedService = $service; + + return $this; + } + public function renderRow($row) { if ($this->readonly) { - return $this::row([ - $row->service + if ($this->highlightedService === $row->service) { + $link = Html::tag('span', ['class' => 'icon-right-big'], $row->service); + } else { + $link = $row->service; + } + } else { + $link = Link::create($row->service, 'director/host/appliedservice', [ + 'name' => $this->host->object_name, + 'service' => $row->service, ]); } - return $this::row([ - Link::create( - $row->service, - 'director/host/appliedservice', - [ - 'name' => $this->host->object_name, - 'service' => $row->service, - ] - ) - ]); + + return $this::row([$link]); } public function getColumnsToBeRendered() diff --git a/library/Director/Web/Table/IcingaHostAppliedServicesTable.php b/library/Director/Web/Table/IcingaHostAppliedServicesTable.php index b5ae54f3..1478e181 100644 --- a/library/Director/Web/Table/IcingaHostAppliedServicesTable.php +++ b/library/Director/Web/Table/IcingaHostAppliedServicesTable.php @@ -2,6 +2,7 @@ namespace Icinga\Module\Director\Web\Table; +use dipl\Html\Html; use Icinga\Data\DataArray\ArrayDatasource; use Icinga\Data\Filter\Filter; use Icinga\Module\Director\Objects\HostApplyMatches; @@ -19,6 +20,12 @@ class IcingaHostAppliedServicesTable extends SimpleQueryBasedTable /** @var \Zend_Db_Adapter_Abstract */ protected $db; + /** @var bool */ + protected $readonly = false; + + /** @var string|null */ + protected $highlightedService; + private $allApplyRules; /** @@ -50,6 +57,26 @@ class IcingaHostAppliedServicesTable extends SimpleQueryBasedTable return $this; } + /** + * Show no related links + * + * @param bool $readonly + * @return $this + */ + public function setReadonly($readonly = true) + { + $this->readonly = (bool) $readonly; + + return $this; + } + + public function highlightService($service) + { + $this->highlightedService = $service; + + return $this; + } + public function renderRow($row) { $classes = []; @@ -62,20 +89,24 @@ class IcingaHostAppliedServicesTable extends SimpleQueryBasedTable $attributes = empty($classes) ? null : ['class' => $classes]; - return $this::row([ - Link::create( - sprintf( - $this->translate('%s (where %s)'), - $row->name, - $row->filter - ), - 'director/host/appliedservice', - [ - 'name' => $this->host->getObjectName(), - 'service_id' => $row->id, - ] - ) - ], $attributes); + if ($this->readonly) { + if ($this->highlightedService === $row->name) { + $link = Html::tag('a', ['class' => 'icon-right-big'], $row->name); + } else { + $link = Html::tag('a', $row->name); + } + } else { + $link = Link::create(sprintf( + $this->translate('%s (where %s)'), + $row->name, + $row->filter + ), 'director/host/appliedservice', [ + 'name' => $this->host->getObjectName(), + 'service_id' => $row->id, + ]); + } + + return $this::row([$link], $attributes); } /** diff --git a/library/Director/Web/Table/IcingaHostServiceTable.php b/library/Director/Web/Table/IcingaHostServiceTable.php index 3e9c603c..3dda12ef 100644 --- a/library/Director/Web/Table/IcingaHostServiceTable.php +++ b/library/Director/Web/Table/IcingaHostServiceTable.php @@ -2,6 +2,7 @@ namespace Icinga\Module\Director\Web\Table; +use dipl\Html\Html; use Icinga\Module\Director\Objects\IcingaHost; use dipl\Html\Link; use dipl\Web\Table\ZfQueryBasedTable; @@ -19,6 +20,9 @@ class IcingaHostServiceTable extends ZfQueryBasedTable /** @var bool */ protected $readonly = false; + /** @var string|null */ + protected $highlightedService; + protected $searchColumns = [ 'service', ]; @@ -66,6 +70,13 @@ class IcingaHostServiceTable extends ZfQueryBasedTable return $this; } + public function highlightService($service) + { + $this->highlightedService = $service; + + return $this; + } + public function renderRow($row) { $classes = []; @@ -86,7 +97,11 @@ class IcingaHostServiceTable extends ZfQueryBasedTable protected function getServiceLink($row) { if ($this->readonly) { - return $row->service; + if ($this->highlightedService === $row->service) { + return Html::tag('span', ['class' => 'icon-right-big'], $row->service); + } else { + return $row->service; + } } if ($target = $this->inheritedBy) { diff --git a/library/Director/Web/Table/IcingaServiceSetServiceTable.php b/library/Director/Web/Table/IcingaServiceSetServiceTable.php index 54ac1285..18e81bf2 100644 --- a/library/Director/Web/Table/IcingaServiceSetServiceTable.php +++ b/library/Director/Web/Table/IcingaServiceSetServiceTable.php @@ -2,6 +2,7 @@ namespace Icinga\Module\Director\Web\Table; +use dipl\Html\BaseHtmlElement; use dipl\Html\Html; use Icinga\Module\Director\Forms\RemoveLinkForm; use Icinga\Module\Director\Objects\IcingaHost; @@ -31,6 +32,9 @@ class IcingaServiceSetServiceTable extends ZfQueryBasedTable /** @var bool */ protected $readonly = false; + /** @var string|null */ + protected $highlightedService; + /** * @param IcingaServiceSet $set * @return static @@ -86,6 +90,13 @@ class IcingaServiceSetServiceTable extends ZfQueryBasedTable return $this; } + public function highlightService($service) + { + $this->highlightedService = $service; + + return $this; + } + protected function addHeaderColumnsTo(HtmlElement $parent) { if ($this->host || $this->affectedHost) { @@ -99,12 +110,16 @@ class IcingaServiceSetServiceTable extends ZfQueryBasedTable /** * @param $row - * @return Link + * @return BaseHtmlElement */ protected function getServiceLink($row) { if ($this->readonly) { - return $row->service; + if ($this->highlightedService === $row->service) { + return Html::tag('span', ['class' => 'icon-right-big'], $row->service); + } else { + return $row->service; + } } if ($this->affectedHost) { diff --git a/library/Director/Web/Widget/HostServiceRedirector.php b/library/Director/Web/Widget/HostServiceRedirector.php index d3a13508..1702e0c1 100644 --- a/library/Director/Web/Widget/HostServiceRedirector.php +++ b/library/Director/Web/Widget/HostServiceRedirector.php @@ -3,6 +3,7 @@ namespace Icinga\Module\Director\Web\Widget; use dipl\Web\Url; +use Icinga\Authentication\Auth; use Icinga\Data\Filter\Filter; use Icinga\Module\Director\Objects\HostApplyMatches; use Icinga\Module\Director\Objects\IcingaHost; @@ -14,6 +15,9 @@ class HostServiceRedirector /** @var IcingaHost */ protected $host; + /** @var Auth */ + protected $auth; + /** @var IcingaHost[] */ protected $parents; @@ -23,9 +27,10 @@ class HostServiceRedirector /** @var \Icinga\Module\Director\Db */ protected $db; - public function __construct(IcingaHost $host) + public function __construct(IcingaHost $host, Auth $auth) { $this->host = $host; + $this->auth = $auth; $this->db = $host->getConnection(); } @@ -36,16 +41,23 @@ class HostServiceRedirector */ public function getRedirectionUrl($serviceName) { - if ($url = $this->getSingleServiceUrl($serviceName)) { - return $url; - } elseif ($url = $this->getParentServiceUrl($serviceName)) { - return $url; - } elseif ($url = $this->getAppliedServiceUrl($serviceName)) { - return $url; - } elseif ($url = $this->getServiceSetServiceUrl($serviceName)) { - return $url; - } elseif ($url = $this->getAppliedServiceSetUrl($serviceName)) { - return $url; + if ($this->auth->hasPermission('director/host')) { + if ($url = $this->getSingleServiceUrl($serviceName)) { + return $url; + } elseif ($url = $this->getParentServiceUrl($serviceName)) { + return $url; + } elseif ($url = $this->getAppliedServiceUrl($serviceName)) { + return $url; + } elseif ($url = $this->getServiceSetServiceUrl($serviceName)) { + return $url; + } elseif ($url = $this->getAppliedServiceSetUrl($serviceName)) { + return $url; + } + } elseif ($this->auth->hasPermission('director/monitoring/services-ro')) { + return Url::fromPath('director/host/servicesro', [ + 'name' => $this->host->getObjectName(), + 'service' => $serviceName + ]); } return Url::fromPath('director/host/invalidservice', [