summaryrefslogtreecommitdiffstats
path: root/library/Graphite/Web/Controller
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-14 13:21:16 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-14 13:21:16 +0000
commit2e582fe0b8b6a8e67982ddb84935db1bd3b401fe (patch)
treedd511b321f308264952cffb005a4288ea4e478e6 /library/Graphite/Web/Controller
parentInitial commit. (diff)
downloadicingaweb2-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')
-rw-r--r--library/Graphite/Web/Controller/IcingadbGraphiteController.php110
-rw-r--r--library/Graphite/Web/Controller/MonitoringAwareController.php175
-rw-r--r--library/Graphite/Web/Controller/TimeRangePickerTrait.php115
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;
+ }
+}