From aebec140d4e56bdd879c8b89b6847e068c24a59b Mon Sep 17 00:00:00 2001 From: Marcin Haba Date: Thu, 11 Jan 2024 13:28:23 +0100 Subject: [PATCH] Add directive filter to config endpoints --- .../protected/API/Modules/BaculaConfig.php | 68 +++++++++++++++++++ .../protected/API/Pages/API/Config.php | 10 +++ .../protected/API/openapi_baculum.json | 36 ++++++++++ 3 files changed, 114 insertions(+) diff --git a/gui/baculum/protected/API/Modules/BaculaConfig.php b/gui/baculum/protected/API/Modules/BaculaConfig.php index 2a029f686..7d4845ee1 100644 --- a/gui/baculum/protected/API/Modules/BaculaConfig.php +++ b/gui/baculum/protected/API/Modules/BaculaConfig.php @@ -112,5 +112,73 @@ class BaculaConfig extends ConfigFileModule { } return $ret; } + + /** + * Filter resources in Bacula configuration output. + * + * @param array $config Bacula configuration + * @param string $key (sub)directive name in dot notation to sepratate sub-resources + * @param string|integer|boolean $value directive value to filter + * @return array filtered configuration output + */ + public static function filterResources(array $config, $key, $value) { + $assoc_keys = array_filter(array_keys($config), 'is_string'); + if (count($config) > 0 && count($assoc_keys) > 0) { + // It works only with list of resources, not with single resource + return $config; + } + $cond = explode('.', $key); + $nest_idx = 0; + $config_new = []; + for ($i = 0; $i < count($config); $i++) { + if (self::findDirective($config[$i], $cond, $value, $nest_idx, false)) { + $config_new[] = $config[$i]; + } + } + return $config_new; + } + + /** + * Find directive with given value in output. + * + * @param array $resource piece of the Bacula configuration + * @param array $cond list with condition sub-directives + * @param integer $nest_idx Bacula configu subresource nest index, as deeper as index bigger + * @param boolean $inc determine if increment nest index (for sub-resources it should be true) + * @return boolean true if searched value was found in Bacula configuration, otherwise false + */ + private static function findDirective(array $resource, array $cond, $value, &$nest_idx, $inc = true) { + if ($inc) { + $nest_idx++; + } + $found = false; + foreach ($resource as $key => $val) { + if (is_string($key) && $key !== $cond[$nest_idx]) { + // skip names that are not included in the condition + continue; + } + if (is_string($key) && is_array($val)) { + // single object, iterate on it + $found = self::findDirective($val, $cond, $value, $nest_idx); + if ($found == true) { + break; + } + } elseif (is_int($key) && is_array($val)) { + // list of objects, itereate on all of them + $found = self::findDirective($val, $cond, $value, $nest_idx, false); + if ($found == true) { + break; + } + } elseif (fnmatch($value, $val)) { + // found scalar key=val directive value + $found = true; + break; + } + } + if ($inc) { + $nest_idx--; + } + return $found; + } } ?> diff --git a/gui/baculum/protected/API/Pages/API/Config.php b/gui/baculum/protected/API/Pages/API/Config.php index 15e3d2c98..f78e2d4d5 100644 --- a/gui/baculum/protected/API/Pages/API/Config.php +++ b/gui/baculum/protected/API/Pages/API/Config.php @@ -20,6 +20,7 @@ * Bacula(R) is a registered trademark of Kern Sibbald. */ +use Baculum\API\Modules\BaculaConfig; use Baculum\API\Modules\BaculumAPIServer; use Baculum\Common\Modules\Errors\AuthorizationError; use Baculum\Common\Modules\Errors\BaculaConfigError; @@ -39,6 +40,8 @@ class Config extends BaculumAPIServer { $resource_type = $this->Request->contains('resource_type') ? $this->Request['resource_type'] : null; $resource_name = $this->Request->contains('resource_name') ? $this->Request['resource_name'] : null; $apply_jobdefs = $this->Request->contains('apply_jobdefs') && $misc->isValidBoolean($this->Request['apply_jobdefs']) ? (bool)$this->Request['apply_jobdefs'] : null; + $filter_directive = $this->Request->contains('filter_directive') && $misc->isValidName($this->Request['filter_directive']) ? $this->Request['filter_directive'] : null; + $filter_value = $this->Request->contains('filter_value') && $this->Request['filter_value'] ? $this->Request['filter_value'] : null; $opts = []; if ($apply_jobdefs) { $opts['apply_jobdefs'] = $apply_jobdefs; @@ -65,6 +68,13 @@ class Config extends BaculumAPIServer { $this->output = BaculaConfigError::MSG_ERROR_CONFIG_DOES_NOT_EXIST; $this->error = BaculaConfigError::ERROR_CONFIG_DOES_NOT_EXIST; } else { + if (is_string($filter_directive) && is_string($filter_value)) { + $config['output'] = BaculaConfig::filterResources( + $config['output'], + $filter_directive, + $filter_value + ); + } $this->output = $config['output']; $this->error = $config['exitcode']; } diff --git a/gui/baculum/protected/API/openapi_baculum.json b/gui/baculum/protected/API/openapi_baculum.json index 32007f368..01dfd9499 100644 --- a/gui/baculum/protected/API/openapi_baculum.json +++ b/gui/baculum/protected/API/openapi_baculum.json @@ -6375,6 +6375,24 @@ }, { "$ref": "#/components/parameters/ApplyJobDefs" + }, + { + "name": "filter_directive", + "in": "query", + "description": "Dot seprated configuration sub-resource names to search, ex. Fileset.Include.Options.Signature or Fileset.Name", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filter_value", + "in": "query", + "description": "Directive value to find. The wildcard pattern is supported.", + "required": false, + "schema": { + "type": "string" + } } ] }, @@ -6462,6 +6480,24 @@ }, { "$ref": "#/components/parameters/ApplyJobDefs" + }, + { + "name": "filter_directive", + "in": "query", + "description": "Dot seprated configuration sub-resource names to search, ex. Fileset.Include.Options.Signature or Fileset.Name", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filter_value", + "in": "query", + "description": "Directive value to find. The wildcard pattern is supported.", + "required": false, + "schema": { + "type": "string" + } } ] }, -- 2.47.3