From f1003939a9b25045bf176201cc62638a877b778c Mon Sep 17 00:00:00 2001 From: axolotle Date: Mon, 3 Oct 2022 16:13:30 +0200 Subject: [PATCH] configpanel: add 'enabled' prop evaluation for button --- locales/en.json | 1 + src/utils/config.py | 35 ++++++++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/locales/en.json b/locales/en.json index 86a7ae770..0a1203b61 100644 --- a/locales/en.json +++ b/locales/en.json @@ -139,6 +139,7 @@ "certmanager_self_ca_conf_file_not_found": "Could not find configuration file for self-signing authority (file: {file})", "certmanager_unable_to_parse_self_CA_name": "Could not parse name of self-signing authority (file: {file})", "certmanager_warning_subdomain_dns_record": "Subdomain '{subdomain}' does not resolve to the same IP address as '{domain}'. Some features will not be available until you fix this and regenerate the certificate.", + "config_action_disabled": "Could not run action '{action}' since it is disabled, make sure to meet its constraints. help: {help}", "config_apply_failed": "Applying the new configuration failed: {error}", "config_cant_set_value_on_section": "You can't set a single value on an entire config section.", "config_forbidden_keyword": "The keyword '{keyword}' is reserved, you can't create or use a config panel with a question with this id.", diff --git a/src/utils/config.py b/src/utils/config.py index 4291e133e..7411b79de 100644 --- a/src/utils/config.py +++ b/src/utils/config.py @@ -356,7 +356,7 @@ class ConfigPanel: self._load_current_values() self._hydrate() Question.operation_logger = operation_logger - self._ask(for_action=True) + self._ask(action=action_id) # FIXME: here, we could want to check constrains on # the action's visibility / requirements wrt to the answer to questions ... @@ -526,6 +526,7 @@ class ConfigPanel: "redact", "filter", "readonly", + "enabled", ], "defaults": {}, }, @@ -661,7 +662,7 @@ class ConfigPanel: return self.values - def _ask(self, for_action=False): + def _ask(self, action=None): logger.debug("Ask unanswered question and prevalidate data") if "i18n" in self.config: @@ -682,7 +683,7 @@ class ConfigPanel: continue # Ugly hack to skip action section ... except when when explicitly running actions - if not for_action: + if not action: if section and section["is_action_section"]: continue @@ -693,6 +694,12 @@ class ConfigPanel: name = _value_for_locale(section["name"]) if name: display_header(f"\n# {name}") + elif section: + # filter action section options in case of multiple buttons + section["options"] = [ + option for option in section["options"] + if option.get("type", "string") != "button" or option["id"] == action + ] if panel == obj: continue @@ -1465,6 +1472,13 @@ class FileQuestion(Question): class ButtonQuestion(Question): argument_type = "button" + enabled = None + + def __init__( + self, question, context: Mapping[str, Any] = {}, hooks: Dict[str, Callable] = {} + ): + super().__init__(question, context, hooks) + self.enabled = question.get("enabled", None) ARGUMENTS_TYPE_PARSERS = { @@ -1529,10 +1543,21 @@ def ask_questions_and_parse_answers( for raw_question in raw_questions: question_class = ARGUMENTS_TYPE_PARSERS[raw_question.get("type", "string")] - if question_class.argument_type == "button": - continue raw_question["value"] = answers.get(raw_question["name"]) question = question_class(raw_question, context=context, hooks=hooks) + if question.type == "button": + if ( + not question.enabled + or evaluate_simple_js_expression(question.enabled, context=context) + ): + continue + else: + raise YunohostValidationError( + "config_action_disabled", + action=question.name, + help=_value_for_locale(question.help) + ) + new_values = question.ask_if_needed() answers.update(new_values) context.update(new_values)