diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-14 13:21:16 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-14 13:21:16 +0000 |
commit | 2e582fe0b8b6a8e67982ddb84935db1bd3b401fe (patch) | |
tree | dd511b321f308264952cffb005a4288ea4e478e6 /library/Graphite/Web/Controller | |
parent | Initial commit. (diff) | |
download | icingaweb2-module-graphite-2e582fe0b8b6a8e67982ddb84935db1bd3b401fe.tar.xz icingaweb2-module-graphite-2e582fe0b8b6a8e67982ddb84935db1bd3b401fe.zip |
Adding upstream version 1.2.2.upstream/1.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/Graphite/Web/Controller')
3 files changed, 400 insertions, 0 deletions
diff --git a/library/Graphite/Web/Controller/IcingadbGraphiteController.php b/library/Graphite/Web/Controller/IcingadbGraphiteController.php new file mode 100644 index 0000000..36bc026 --- /dev/null +++ b/library/Graphite/Web/Controller/IcingadbGraphiteController.php @@ -0,0 +1,110 @@ +<?php + +/* Icinga Graphite Web | (c) 2022 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Graphite\Web\Controller; + +use Icinga\Application\Modules\Module; +use Icinga\Module\Graphite\ProvidedHook\Icingadb\IcingadbSupport; +use Icinga\Module\Icingadb\Common\Auth; +use Icinga\Module\Icingadb\Common\Database; +use Icinga\Module\Icingadb\Common\SearchControls; +use ipl\Orm\Query; +use ipl\Stdlib\Contract\Paginatable; +use ipl\Web\Compat\CompatController; +use ipl\Web\Control\LimitControl; +use ipl\Web\Control\PaginationControl; +use ipl\Web\Control\SortControl; +use ipl\Web\Filter\QueryString; +use ipl\Stdlib\Filter; +use ipl\Web\Url; + +class IcingadbGraphiteController extends CompatController +{ + use Auth; + use Database; + use SearchControls; + + /** @var bool Whether to use icingadb as the backend */ + protected $useIcingadbAsBackend; + + /** @var string[] Graph parameters */ + protected $graphParams = ['graphs_limit', 'graph_range', 'graph_start', 'graph_end', 'legacyParams']; + + /** @var Filter\Rule Filter from query string parameters */ + private $filter; + + protected function moduleInit() + { + $this->useIcingadbAsBackend = Module::exists('icingadb') && IcingadbSupport::useIcingaDbAsBackend(); + } + + /** + * Get the filter created from query string parameters + * + * @return Filter\Rule + */ + public function getFilter(): Filter\Rule + { + if ($this->filter === null) { + $this->filter = QueryString::parse((string) $this->params); + } + + return $this->filter; + } + + /** + * Create and return the LimitControl + * + * This automatically shifts the limit URL parameter from {@link $params}. + * + * @return LimitControl + */ + public function createLimitControl(): LimitControl + { + $limitControl = new LimitControl(Url::fromRequest()); + $limitControl->setDefaultLimit($this->getPageSize(null)); + + $this->params->shift($limitControl->getLimitParam()); + + return $limitControl; + } + + /** + * Create and return the PaginationControl + * + * This automatically shifts the pagination URL parameters from {@link $params}. + * + * @return PaginationControl + */ + public function createPaginationControl(Paginatable $paginatable): PaginationControl + { + $paginationControl = new PaginationControl($paginatable, Url::fromRequest()); + $paginationControl->setDefaultPageSize($this->getPageSize(null)); + $paginationControl->setAttribute('id', $this->getRequest()->protectId('pagination-control')); + + $this->params->shift($paginationControl->getPageParam()); + $this->params->shift($paginationControl->getPageSizeParam()); + + return $paginationControl->apply(); + } + + /** + * Create and return the SortControl + * + * This automatically shifts the sort URL parameter from {@link $params}. + * + * @param Query $query + * @param array $columns Possible sort columns as sort string-label pairs + * + * @return SortControl + */ + public function createSortControl(Query $query, array $columns): SortControl + { + $sortControl = SortControl::create($columns); + + $this->params->shift($sortControl->getSortParam()); + + return $sortControl->apply($query); + } +} diff --git a/library/Graphite/Web/Controller/MonitoringAwareController.php b/library/Graphite/Web/Controller/MonitoringAwareController.php new file mode 100644 index 0000000..dca2ebd --- /dev/null +++ b/library/Graphite/Web/Controller/MonitoringAwareController.php @@ -0,0 +1,175 @@ +<?php + +namespace Icinga\Module\Graphite\Web\Controller; + +use ArrayIterator; +use Icinga\Application\Modules\Module; +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filterable; +use Icinga\Exception\ConfigurationError; +use Icinga\Exception\QueryException; +use Icinga\Module\Graphite\ProvidedHook\Icingadb\IcingadbSupport; +use Icinga\Module\Monitoring\Backend\MonitoringBackend; +use Icinga\Module\Monitoring\Data\CustomvarProtectionIterator; +use Icinga\Module\Monitoring\DataView\DataView; +use Icinga\Util\Json; +use Icinga\File\Csv; +use Icinga\Web\Controller; +use Icinga\Web\Url; + +abstract class MonitoringAwareController extends Controller +{ + /** @var bool Whether to use icingadb as the backend */ + protected $useIcingadbAsBackend = false; + + /** + * Restrict the given monitored object query for the currently authenticated user + * + * @param DataView $dataView + * + * @return DataView The given data view + */ + protected function applyMonitoringRestriction(DataView $dataView) + { + $this->applyRestriction('monitoring/filter/objects', $dataView); + + return $dataView; + } + + protected function moduleInit() + { + if (Module::exists('icingadb') && IcingadbSupport::useIcingaDbAsBackend()) { + $this->useIcingadbAsBackend = true; + + return; + } + + $this->backend = MonitoringBackend::instance($this->_getParam('backend')); + $this->view->url = Url::fromRequest(); + } + + + protected function handleFormatRequest($query) + { + $desiredContentType = $this->getRequest()->getHeader('Accept'); + if ($desiredContentType === 'application/json') { + $desiredFormat = 'json'; + } elseif ($desiredContentType === 'text/csv') { + $desiredFormat = 'csv'; + } else { + $desiredFormat = strtolower($this->params->get('format', 'html')); + } + + if ($desiredFormat !== 'html' && ! $this->params->has('limit')) { + $query->limit(); // Resets any default limit and offset + } + + switch ($desiredFormat) { + case 'sql': + echo '<pre>' + . htmlspecialchars(wordwrap($query->dump())) + . '</pre>'; + exit; + case 'json': + $response = $this->getResponse(); + $response + ->setHeader('Content-Type', 'application/json') + ->setHeader('Cache-Control', 'no-store') + ->setHeader( + 'Content-Disposition', + 'inline; filename=' . $this->getRequest()->getActionName() . '.json' + ) + ->appendBody( + Json::sanitize( + iterator_to_array( + new CustomvarProtectionIterator( + new ArrayIterator($query->fetchAll()) + ) + ) + ) + ) + ->sendResponse(); + exit; + case 'csv': + $response = $this->getResponse(); + $response + ->setHeader('Content-Type', 'text/csv') + ->setHeader('Cache-Control', 'no-store') + ->setHeader( + 'Content-Disposition', + 'attachment; filename=' . $this->getRequest()->getActionName() . '.csv' + ) + ->appendBody((string) Csv::fromQuery(new CustomvarProtectionIterator($query))) + ->sendResponse(); + exit; + } + } + + /** + * Apply a restriction of the authenticated on the given filterable + * + * @param string $name Name of the restriction + * @param Filterable $filterable Filterable to restrict + * + * @return Filterable The filterable having the restriction applied + */ + protected function applyRestriction($name, Filterable $filterable) + { + $filterable->applyFilter($this->getRestriction($name)); + return $filterable; + } + + /** + * Get a restriction of the authenticated + * + * @param string $name Name of the restriction + * + * @return Filter Filter object + * @throws ConfigurationError If the restriction contains invalid filter columns + */ + protected function getRestriction($name) + { + $restriction = Filter::matchAny(); + $restriction->setAllowedFilterColumns(array( + 'host_name', + 'hostgroup_name', + 'instance_name', + 'service_description', + 'servicegroup_name', + function ($c) { + return preg_match('/^_(?:host|service)_/i', $c); + } + )); + foreach ($this->getRestrictions($name) as $filter) { + if ($filter === '*') { + return Filter::matchAll(); + } + try { + $restriction->addFilter(Filter::fromQueryString($filter)); + } catch (QueryException $e) { + throw new ConfigurationError( + $this->translate( + 'Cannot apply restriction %s using the filter %s. You can only use the following columns: %s' + ), + $name, + $filter, + implode(', ', array( + 'instance_name', + 'host_name', + 'hostgroup_name', + 'service_description', + 'servicegroup_name', + '_(host|service)_<customvar-name>' + )), + $e + ); + } + } + + if ($restriction->isEmpty()) { + return Filter::matchAll(); + } + + return $restriction; + } +} diff --git a/library/Graphite/Web/Controller/TimeRangePickerTrait.php b/library/Graphite/Web/Controller/TimeRangePickerTrait.php new file mode 100644 index 0000000..7352b1b --- /dev/null +++ b/library/Graphite/Web/Controller/TimeRangePickerTrait.php @@ -0,0 +1,115 @@ +<?php + +namespace Icinga\Module\Graphite\Web\Controller; + +use Icinga\Module\Graphite\Forms\TimeRangePicker\CommonForm; +use Icinga\Module\Graphite\Forms\TimeRangePicker\CustomForm; +use Icinga\Web\Request; +use Icinga\Web\Url; +use Icinga\Web\View; + +trait TimeRangePickerTrait +{ + /** + * @var CommonForm + */ + protected $timeRangePickerCommonForm; + + /** + * @var CustomForm + */ + protected $timeRangePickerCustomForm; + + /** + * Process the given request using the forms + * + * @param Request $request The request to be processed + * + * @return Request The request supposed to be processed + */ + protected function handleTimeRangePickerRequest(Request $request = null) + { + $this->getTimeRangePickerCommonForm()->handleRequest($request); + return $this->getTimeRangePickerCustomForm()->handleRequest($request); + } + + /** + * Render all needed forms and links + * + * @param View $view + * + * @return string + */ + protected function renderTimeRangePicker(View $view) + { + $url = Url::fromRequest()->getAbsoluteUrl(); + + return '<div class="timerangepicker-container">' + . $this->getTimeRangePickerCommonForm() + . '<div class="flyover flyover-arrow-top" data-flyover-suspends-auto-refresh id="' + . $view->protectId('graphite-customrange') + . '">' + . $view->qlink(null, '#', null, [ + 'title' => $view->translate('Specify custom time range'), + 'class' => 'button-link flyover-toggle', + 'icon' => 'service' + ]) + . '<div class="flyover-content">' . $this->getTimeRangePickerCustomForm() . '</div>' + . '</div>' + . '</div>'; + } + + /** + * Get {@link timeRangePickerCommonForm} + * + * @return CommonForm + */ + public function getTimeRangePickerCommonForm() + { + if ($this->timeRangePickerCommonForm === null) { + $this->timeRangePickerCommonForm = new CommonForm(); + } + + return $this->timeRangePickerCommonForm; + } + + /** + * Set {@link timeRangePickerCommonForm} + * + * @param CommonForm $timeRangePickerCommonForm + * + * @return $this + */ + public function setTimeRangePickerCommonForm(CommonForm $timeRangePickerCommonForm) + { + $this->timeRangePickerCommonForm = $timeRangePickerCommonForm; + return $this; + } + + /** + * Get {@link timeRangePickerCustomForm} + * + * @return CustomForm + */ + public function getTimeRangePickerCustomForm() + { + if ($this->timeRangePickerCustomForm === null) { + $this->timeRangePickerCustomForm = new CustomForm(); + } + + return $this->timeRangePickerCustomForm; + } + + /** + * Set {@link timeRangePickerCustomForm} + * + * @param CustomForm $timeRangePickerCustomForm + * + * @return $this + */ + public function setTimeRangePickerCustomForm(CustomForm $timeRangePickerCustomForm) + { + $this->timeRangePickerCustomForm = $timeRangePickerCustomForm; + return $this; + } +} |