From 98e84726c7b55a7b877105cecd503049942955cf Mon Sep 17 00:00:00 2001 From: oskarnrk Date: Fri, 22 Aug 2025 12:14:50 +0200 Subject: [PATCH 1/2] Add CustomVarsRetrieverHook for dynamic custom variable retrieval, updated ObjectSuggestions and Controller classes to utilize the new hook for enhanced search functionality --- .../Icingadb/Hook/CustomVarsRetrieverHook.php | 37 +++++++++++++++++++ .../Control/SearchBar/ObjectSuggestions.php | 6 ++- library/Icingadb/Web/Controller.php | 5 ++- 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 library/Icingadb/Hook/CustomVarsRetrieverHook.php diff --git a/library/Icingadb/Hook/CustomVarsRetrieverHook.php b/library/Icingadb/Hook/CustomVarsRetrieverHook.php new file mode 100644 index 000000000..0c2b5eca4 --- /dev/null +++ b/library/Icingadb/Hook/CustomVarsRetrieverHook.php @@ -0,0 +1,37 @@ +retrieveCustomVars($model); + if (!empty($customVars)) { + $columns = [...$columns, ...$customVars]; + } + } catch (Throwable $e) { + Logger::error( + 'Error retrieving Custom Vars for %s with table name "%s": %s', + get_class($model), + $model->getTableName(), + $e->getMessage() + ); + } + } + + return $columns; + } +} diff --git a/library/Icingadb/Web/Control/SearchBar/ObjectSuggestions.php b/library/Icingadb/Web/Control/SearchBar/ObjectSuggestions.php index ccc87e028..83d9ffd26 100644 --- a/library/Icingadb/Web/Control/SearchBar/ObjectSuggestions.php +++ b/library/Icingadb/Web/Control/SearchBar/ObjectSuggestions.php @@ -9,6 +9,7 @@ use Icinga\Module\Icingadb\Common\Database; use Icinga\Module\Icingadb\Data\QueryColumnsProvider; use Icinga\Module\Icingadb\Data\QueryValuesProvider; +use Icinga\Module\Icingadb\Hook\CustomVarsRetrieverHook; use ipl\Html\HtmlElement; use ipl\Orm\Model; use ipl\Stdlib\BaseFilter; @@ -92,7 +93,10 @@ protected function createQuickSearchFilter($searchTerm) $resolver = $model::on($this->getDb())->getResolver(); $quickFilter = Filter::any(); - foreach ($model->getSearchColumns() as $column) { + $customVarColumns = CustomVarsRetrieverHook::getCustomVarColumns($model); + $columns = [...$model->getSearchColumns(), ...$customVarColumns]; + + foreach ($columns as $column) { if (strpos($column, '.') === false) { $column = $resolver->qualifyColumn($column, $model->getTableName()); } diff --git a/library/Icingadb/Web/Controller.php b/library/Icingadb/Web/Controller.php index ede186c01..32c6159e2 100644 --- a/library/Icingadb/Web/Controller.php +++ b/library/Icingadb/Web/Controller.php @@ -13,7 +13,6 @@ use Icinga\Application\Logger; use Icinga\Application\Web; use Icinga\Data\ConfigObject; -use Icinga\Exception\Http\HttpBadRequestException; use Icinga\Exception\Json\JsonDecodeException; use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Common\Database; @@ -349,7 +348,9 @@ public function handleSearchRequest(Query $query, array $additionalColumns = []) */ protected function prepareSearchFilter(Query $query, string $search, Filter\Any $filter, array $additionalColumns) { - $columns = array_merge($query->getModel()->getSearchColumns(), $additionalColumns); + $model = $query->getModel(); + $customVarColumns = CustomVarsRetrieverHook::getCustomVarColumns($model); + $columns = array_merge($model->getSearchColumns(), $additionalColumns, $customVarColumns); foreach ($columns as $column) { if (strpos($column, '.') === false) { $column = $query->getResolver()->qualifyColumn($column, $query->getModel()->getTableName()); From 6fb547618becc0161145727372b487b543149472 Mon Sep 17 00:00:00 2001 From: Gianluca Piccolo Date: Tue, 16 Jun 2026 11:18:28 +0200 Subject: [PATCH 2/2] Refactor search functionality to use SearchColumnProviderHook for custom variable retrieval and added new SearchColumnProviderHook class --- library/Icingadb/Common/SearchControls.php | 13 +++++ .../Icingadb/Hook/CustomVarsRetrieverHook.php | 37 ------------- .../Hook/SearchColumnsProviderHook.php | 52 +++++++++++++++++++ .../Control/SearchBar/ObjectSuggestions.php | 6 +-- library/Icingadb/Web/Controller.php | 5 +- 5 files changed, 71 insertions(+), 42 deletions(-) delete mode 100644 library/Icingadb/Hook/CustomVarsRetrieverHook.php create mode 100644 library/Icingadb/Hook/SearchColumnsProviderHook.php diff --git a/library/Icingadb/Common/SearchControls.php b/library/Icingadb/Common/SearchControls.php index a352ed2d7..aeecfd587 100644 --- a/library/Icingadb/Common/SearchControls.php +++ b/library/Icingadb/Common/SearchControls.php @@ -5,6 +5,7 @@ namespace Icinga\Module\Icingadb\Common; +use Icinga\Module\Icingadb\Hook\SearchColumnsProviderHook; use ipl\Html\Html; use ipl\Orm\Query; use ipl\Web\Control\SearchBar; @@ -35,9 +36,21 @@ public function createSearchBar(Query $query, ...$params): SearchBar $searchBar->addWrapper(Html::tag('div', ['class' => 'search-controls'])); } + $model = $query->getModel(); + $defaultColumns = $model->getSearchColumns(); + $columns = SearchColumnsProviderHook::getCustomVarColumns($model, $defaultColumns); + $searchBar->setSearchColumns($columns); + + $searchBar->handleRequest($this->getServerRequest()); + return $searchBar; } + private function callHandleRequest() + { + return false; + } + /** * Create and return a ContinueWith * diff --git a/library/Icingadb/Hook/CustomVarsRetrieverHook.php b/library/Icingadb/Hook/CustomVarsRetrieverHook.php deleted file mode 100644 index 0c2b5eca4..000000000 --- a/library/Icingadb/Hook/CustomVarsRetrieverHook.php +++ /dev/null @@ -1,37 +0,0 @@ -retrieveCustomVars($model); - if (!empty($customVars)) { - $columns = [...$columns, ...$customVars]; - } - } catch (Throwable $e) { - Logger::error( - 'Error retrieving Custom Vars for %s with table name "%s": %s', - get_class($model), - $model->getTableName(), - $e->getMessage() - ); - } - } - - return $columns; - } -} diff --git a/library/Icingadb/Hook/SearchColumnsProviderHook.php b/library/Icingadb/Hook/SearchColumnsProviderHook.php new file mode 100644 index 000000000..615d48a04 --- /dev/null +++ b/library/Icingadb/Hook/SearchColumnsProviderHook.php @@ -0,0 +1,52 @@ + +// SPDX-License-Identifier: GPL-3.0-or-later + +namespace Icinga\Module\Icingadb\Hook; + +use Icinga\Application\Hook; +use Icinga\Application\Logger; +use ipl\Orm\Model; +use Throwable; + +/** + * Hook for providing additional search columns such as custom variables. + * + * This is a first attempt to generalize support for modules to provide additional search columns. + * The end user won't be able to customize the set provided and every global or route search will + * always use them. Any hook implementation must ensure that only columns the user has access to + * and that are valid in the current route are returned. Returning invalid columns may cause errors + * for users. See https://github.com/Icinga/icingadb-web/security/advisories/GHSA-w57j-28jc-8429 + * for an example of what can go wrong. + * + * @deprecated This will not be used by any future version without any further notice. + */ +abstract class SearchColumnsProviderHook +{ + abstract public function retrieveCustomVars(Model $model): array; + + final public static function getCustomVarColumns(Model $model, array $defaultColumns = []): array + { + $columns = $defaultColumns; + + $hooks = Hook::all('icingadb/SearchColumnsProvider'); + foreach ($hooks as $hook) { + try { + $customVars = $hook->retrieveCustomVars($model); + if (! empty($customVars)) { + $columns = [...$columns, ...$customVars]; + } + } catch (Throwable $e) { + Logger::error( + 'Error retrieving Custom Vars for %s with table name "%s": %s', + get_class($model), + $model->getTableName(), + $e->getMessage() + ); + } + } + + return array_unique($columns); + } +} diff --git a/library/Icingadb/Web/Control/SearchBar/ObjectSuggestions.php b/library/Icingadb/Web/Control/SearchBar/ObjectSuggestions.php index 83d9ffd26..1856b489e 100644 --- a/library/Icingadb/Web/Control/SearchBar/ObjectSuggestions.php +++ b/library/Icingadb/Web/Control/SearchBar/ObjectSuggestions.php @@ -9,7 +9,7 @@ use Icinga\Module\Icingadb\Common\Database; use Icinga\Module\Icingadb\Data\QueryColumnsProvider; use Icinga\Module\Icingadb\Data\QueryValuesProvider; -use Icinga\Module\Icingadb\Hook\CustomVarsRetrieverHook; +use Icinga\Module\Icingadb\Hook\SearchColumnsProviderHook; use ipl\Html\HtmlElement; use ipl\Orm\Model; use ipl\Stdlib\BaseFilter; @@ -93,8 +93,8 @@ protected function createQuickSearchFilter($searchTerm) $resolver = $model::on($this->getDb())->getResolver(); $quickFilter = Filter::any(); - $customVarColumns = CustomVarsRetrieverHook::getCustomVarColumns($model); - $columns = [...$model->getSearchColumns(), ...$customVarColumns]; + $defaultColumns = $model->getSearchColumns(); + $columns = SearchColumnsProviderHook::getCustomVarColumns($model, $defaultColumns); foreach ($columns as $column) { if (strpos($column, '.') === false) { diff --git a/library/Icingadb/Web/Controller.php b/library/Icingadb/Web/Controller.php index 32c6159e2..1d07bfe9b 100644 --- a/library/Icingadb/Web/Controller.php +++ b/library/Icingadb/Web/Controller.php @@ -22,6 +22,7 @@ use Icinga\Module\Icingadb\Data\JsonResultSet; use Icinga\Module\Icingadb\Data\QueryColumnsProvider; use Icinga\Module\Icingadb\Web\Control\ColumnChooser; +use Icinga\Module\Icingadb\Hook\SearchColumnsProviderHook; use Icinga\Module\Icingadb\Web\Control\GridViewModeSwitcher; use Icinga\Module\Icingadb\Web\Control\TimestampToggle; use Icinga\Module\Icingadb\Web\Control\ViewModeSwitcher; @@ -349,8 +350,8 @@ public function handleSearchRequest(Query $query, array $additionalColumns = []) protected function prepareSearchFilter(Query $query, string $search, Filter\Any $filter, array $additionalColumns) { $model = $query->getModel(); - $customVarColumns = CustomVarsRetrieverHook::getCustomVarColumns($model); - $columns = array_merge($model->getSearchColumns(), $additionalColumns, $customVarColumns); + $defaultColumns = $model->getSearchColumns(); + $columns = SearchColumnsProviderHook::getCustomVarColumns($model, $defaultColumns); foreach ($columns as $column) { if (strpos($column, '.') === false) { $column = $query->getResolver()->qualifyColumn($column, $query->getModel()->getTableName());