From a631261cfff840604c01fa11c0ba2b32d5152f23 Mon Sep 17 00:00:00 2001 From: yunohost-bot Date: Fri, 17 Sep 2021 03:33:35 +0000 Subject: [PATCH 1/7] [CI] Format code --- src/yunohost/app.py | 2 +- src/yunohost/log.py | 11 ++++++++--- src/yunohost/utils/config.py | 16 +++++++++++----- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 3ba7fd5e4..3145078cc 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -1779,7 +1779,7 @@ ynh_app_config_run $1 "app_id": app_id, "app": self.app, "app_instance_nb": str(app_instance_nb), - "final_path": settings.get("final_path", "") + "final_path": settings.get("final_path", ""), } ) diff --git a/src/yunohost/log.py b/src/yunohost/log.py index 3f25d7a7d..f40470063 100644 --- a/src/yunohost/log.py +++ b/src/yunohost/log.py @@ -75,7 +75,7 @@ def log_list(limit=None, with_details=False, with_suboperations=False): # If we displaying only parent, we are still gonna load up to limit * 5 logs # because many of them are suboperations which are not gonna be kept # Yet we still want to obtain ~limit number of logs - logs = logs[:limit * 5] + logs = logs[: limit * 5] for log in logs: @@ -186,12 +186,17 @@ def log_show( r"DEBUG - \+ exit (1|0)$", ] filters = [re.compile(f) for f in filters] - return [line for line in lines if not any(f.search(line.strip()) for f in filters)] + return [ + line + for line in lines + if not any(f.search(line.strip()) for f in filters) + ] + else: + def _filter(lines): return lines - # Normalize log/metadata paths and filenames abs_path = path log_path = None diff --git a/src/yunohost/utils/config.py b/src/yunohost/utils/config.py index 6b823452b..27681e4d3 100644 --- a/src/yunohost/utils/config.py +++ b/src/yunohost/utils/config.py @@ -478,7 +478,7 @@ class Question(object): self.value = Moulinette.prompt( message=text, is_password=self.hide_user_input_in_prompt, - confirm=False, # We doesn't want to confirm this kind of password like in webadmin + confirm=False, # We doesn't want to confirm this kind of password like in webadmin prefill=prefill, is_multiline=(self.type == "text"), ) @@ -705,11 +705,17 @@ class PasswordQuestion(Question): def _format_text_for_user_input_in_cli(self): need_column = self.current_value or self.optional - text_for_user_input_in_cli = super()._format_text_for_user_input_in_cli(need_column) + text_for_user_input_in_cli = super()._format_text_for_user_input_in_cli( + need_column + ) if self.current_value: - text_for_user_input_in_cli += "\n - " + m18n.n("app_argument_password_help_keep") + text_for_user_input_in_cli += "\n - " + m18n.n( + "app_argument_password_help_keep" + ) if self.optional: - text_for_user_input_in_cli += "\n - " + m18n.n("app_argument_password_help_optional") + text_for_user_input_in_cli += "\n - " + m18n.n( + "app_argument_password_help_optional" + ) return text_for_user_input_in_cli @@ -832,7 +838,7 @@ class UserQuestion(Question): raise YunohostValidationError( "app_argument_invalid", name=self.name, - error="You should create a YunoHost user first." + error="You should create a YunoHost user first.", ) if self.default is None: From 12bc94f76e096202ed15d12015a69054e7095409 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 17 Sep 2021 12:55:23 +0200 Subject: [PATCH 2/7] config/question: broadcast data to redact to all OperationLogger instances --- src/yunohost/app.py | 2 -- src/yunohost/tests/test_questions.py | 49 +++++----------------------- src/yunohost/utils/config.py | 12 +++---- 3 files changed, 12 insertions(+), 51 deletions(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 3145078cc..70e55ceb0 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -1723,8 +1723,6 @@ def app_config_set( config_ = AppConfigPanel(app) - Question.operation_logger = operation_logger - return config_.set(key, value, args, args_file, operation_logger=operation_logger) diff --git a/src/yunohost/tests/test_questions.py b/src/yunohost/tests/test_questions.py index 67b50769b..91372dffa 100644 --- a/src/yunohost/tests/test_questions.py +++ b/src/yunohost/tests/test_questions.py @@ -348,9 +348,7 @@ def test_question_password(): ] answers = {"some_password": "some_value"} expected_result = OrderedDict({"some_password": ("some_value", "password")}) - Question.operation_logger = MagicMock() - with patch.object(Question.operation_logger, "data_to_redact", create=True): - assert parse_args_in_yunohost_format(answers, questions) == expected_result + assert parse_args_in_yunohost_format(answers, questions) == expected_result def test_question_password_no_input(): @@ -375,13 +373,9 @@ def test_question_password_input(): } ] answers = {} - Question.operation_logger = {"data_to_redact": []} expected_result = OrderedDict({"some_password": ("some_value", "password")}) - Question.operation_logger = MagicMock() - with patch.object( - Question.operation_logger, "data_to_redact", create=True - ), patch.object(Moulinette, "prompt", return_value="some_value"), patch.object( + with patch.object(Moulinette, "prompt", return_value="some_value"), patch.object( os, "isatty", return_value=True ): assert parse_args_in_yunohost_format(answers, questions) == expected_result @@ -397,10 +391,7 @@ def test_question_password_input_no_ask(): answers = {} expected_result = OrderedDict({"some_password": ("some_value", "password")}) - Question.operation_logger = MagicMock() - with patch.object( - Question.operation_logger, "data_to_redact", create=True - ), patch.object(Moulinette, "prompt", return_value="some_value"), patch.object( + with patch.object(Moulinette, "prompt", return_value="some_value"), patch.object( os, "isatty", return_value=True ): assert parse_args_in_yunohost_format(answers, questions) == expected_result @@ -417,20 +408,14 @@ def test_question_password_no_input_optional(): answers = {} expected_result = OrderedDict({"some_password": ("", "password")}) - Question.operation_logger = MagicMock() - with patch.object( - Question.operation_logger, "data_to_redact", create=True - ), patch.object(os, "isatty", return_value=False): + with patch.object(os, "isatty", return_value=False): assert parse_args_in_yunohost_format(answers, questions) == expected_result questions = [ {"name": "some_password", "type": "password", "optional": True, "default": ""} ] - Question.operation_logger = MagicMock() - with patch.object( - Question.operation_logger, "data_to_redact", create=True - ), patch.object(os, "isatty", return_value=False): + with patch.object(os, "isatty", return_value=False): assert parse_args_in_yunohost_format(answers, questions) == expected_result @@ -446,10 +431,7 @@ def test_question_password_optional_with_input(): answers = {} expected_result = OrderedDict({"some_password": ("some_value", "password")}) - Question.operation_logger = MagicMock() - with patch.object( - Question.operation_logger, "data_to_redact", create=True - ), patch.object(Moulinette, "prompt", return_value="some_value"), patch.object( + with patch.object(Moulinette, "prompt", return_value="some_value"), patch.object( os, "isatty", return_value=True ): assert parse_args_in_yunohost_format(answers, questions) == expected_result @@ -467,10 +449,7 @@ def test_question_password_optional_with_empty_input(): answers = {} expected_result = OrderedDict({"some_password": ("", "password")}) - Question.operation_logger = MagicMock() - with patch.object( - Question.operation_logger, "data_to_redact", create=True - ), patch.object(Moulinette, "prompt", return_value=""), patch.object( + with patch.object(Moulinette, "prompt", return_value=""), patch.object( os, "isatty", return_value=True ): assert parse_args_in_yunohost_format(answers, questions) == expected_result @@ -487,10 +466,7 @@ def test_question_password_optional_with_input_without_ask(): answers = {} expected_result = OrderedDict({"some_password": ("some_value", "password")}) - Question.operation_logger = MagicMock() - with patch.object( - Question.operation_logger, "data_to_redact", create=True - ), patch.object(Moulinette, "prompt", return_value="some_value"), patch.object( + with patch.object(Moulinette, "prompt", return_value="some_value"), patch.object( os, "isatty", return_value=True ): assert parse_args_in_yunohost_format(answers, questions) == expected_result @@ -540,10 +516,7 @@ def test_question_password_input_test_ask(): ] answers = {} - Question.operation_logger = MagicMock() with patch.object( - Question.operation_logger, "data_to_redact", create=True - ), patch.object( Moulinette, "prompt", return_value="some_value" ) as prompt, patch.object( os, "isatty", return_value=True @@ -572,10 +545,7 @@ def test_question_password_input_test_ask_with_example(): ] answers = {} - Question.operation_logger = MagicMock() with patch.object( - Question.operation_logger, "data_to_redact", create=True - ), patch.object( Moulinette, "prompt", return_value="some_value" ) as prompt, patch.object( os, "isatty", return_value=True @@ -599,10 +569,7 @@ def test_question_password_input_test_ask_with_help(): ] answers = {} - Question.operation_logger = MagicMock() with patch.object( - Question.operation_logger, "data_to_redact", create=True - ), patch.object( Moulinette, "prompt", return_value="some_value" ) as prompt, patch.object( os, "isatty", return_value=True diff --git a/src/yunohost/utils/config.py b/src/yunohost/utils/config.py index 27681e4d3..447540e13 100644 --- a/src/yunohost/utils/config.py +++ b/src/yunohost/utils/config.py @@ -39,6 +39,7 @@ from moulinette.utils.filesystem import ( from yunohost.utils.i18n import _value_for_locale from yunohost.utils.error import YunohostError, YunohostValidationError +from yunohost.log import OperationLogger logger = getActionLogger("yunohost.config") CONFIG_PANEL_VERSION_SUPPORTED = 1.0 @@ -441,7 +442,6 @@ class ConfigPanel: class Question(object): hide_user_input_in_prompt = False - operation_logger = None pattern = None def __init__(self, question, user_answers): @@ -575,13 +575,9 @@ class Question(object): for data in data_to_redact if urllib.parse.quote(data) != data ] - if self.operation_logger: - self.operation_logger.data_to_redact.extend(data_to_redact) - elif data_to_redact: - raise YunohostError( - f"Can't redact {self.name} because no operation logger available in the context", - raw_msg=True, - ) + + for operation_logger in OperationLogger._instances: + operation_logger.data_to_redact.extend(data_to_redact) return self.value From 4503816a88ca2ba1f6ac76dd8cd823e63de748ac Mon Sep 17 00:00:00 2001 From: Kay0u Date: Fri, 17 Sep 2021 14:39:14 +0200 Subject: [PATCH 3/7] Adding an anchor on each helper --- doc/helper_doc_template.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/helper_doc_template.md b/doc/helper_doc_template.md index cf88e10ac..d41c0b6e9 100644 --- a/doc/helper_doc_template.md +++ b/doc/helper_doc_template.md @@ -10,11 +10,10 @@ routes: Doc auto-generated by [this script](https://github.com/YunoHost/yunohost/blob/{{ current_commit }}/doc/generate_helper_doc.py) on {{data.date}} (YunoHost version {{data.version}}) {% for category, helpers in data.helpers %} -### {{ category.upper() }} +## {{ category.upper() }} {% for h in helpers %} -**{{ h.name }}**
+#### {{ h.name }} [details summary="{{ h.brief }}" class="helper-card-subtitle text-muted"] -

**Usage**: `{{ h.usage }}` {%- if h.args %} From c53a6006ce8017c39ea9f2b0f410acf64ef98f7c Mon Sep 17 00:00:00 2001 From: Kay0u Date: Fri, 17 Sep 2021 14:47:12 +0200 Subject: [PATCH 4/7] Remove unused import --- src/yunohost/app.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 70e55ceb0..e7fae9e76 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -56,7 +56,6 @@ from yunohost.utils import packages from yunohost.utils.config import ( ConfigPanel, parse_args_in_yunohost_format, - Question, ) from yunohost.utils.i18n import _value_for_locale from yunohost.utils.error import YunohostError, YunohostValidationError From 4db4338812216a0787c9b5389bdc71756e660af2 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 17 Sep 2021 16:57:51 +0200 Subject: [PATCH 5/7] mypy: read_yaml argument should always be a string --- src/yunohost/utils/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/utils/config.py b/src/yunohost/utils/config.py index 447540e13..e3bbc5299 100644 --- a/src/yunohost/utils/config.py +++ b/src/yunohost/utils/config.py @@ -126,7 +126,7 @@ class ConfigPanel: if args_file: # Import YAML / JSON file but keep --args values - self.args = {**read_yaml(args_file), **self.args} + self.args = {**read_yaml(args_file.name), **self.args} if value is not None: self.args = {self.filter_key.split(".")[-1]: value} From d135b97784cb06fc9a4de51ca4324f92c452d245 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 17 Sep 2021 17:10:07 +0200 Subject: [PATCH 6/7] Revert "mypy: read_yaml argument should always be a string" This reverts commit 4db4338812216a0787c9b5389bdc71756e660af2. --- src/yunohost/utils/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/utils/config.py b/src/yunohost/utils/config.py index e3bbc5299..447540e13 100644 --- a/src/yunohost/utils/config.py +++ b/src/yunohost/utils/config.py @@ -126,7 +126,7 @@ class ConfigPanel: if args_file: # Import YAML / JSON file but keep --args values - self.args = {**read_yaml(args_file.name), **self.args} + self.args = {**read_yaml(args_file), **self.args} if value is not None: self.args = {self.filter_key.split(".")[-1]: value} From 29bb26f24687989334289d7d17e8c4a5413af968 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Fri, 17 Sep 2021 17:51:50 +0200 Subject: [PATCH 7/7] remove created permission if error --- src/yunohost/permission.py | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/yunohost/permission.py b/src/yunohost/permission.py index 01330ad7f..5161430de 100644 --- a/src/yunohost/permission.py +++ b/src/yunohost/permission.py @@ -457,22 +457,26 @@ def permission_create( "permission_creation_failed", permission=permission, error=e ) - permission_url( - permission, - url=url, - add_url=additional_urls, - auth_header=auth_header, - sync_perm=False, - ) + try: + permission_url( + permission, + url=url, + add_url=additional_urls, + auth_header=auth_header, + sync_perm=False, + ) - new_permission = _update_ldap_group_permission( - permission=permission, - allowed=allowed, - label=label, - show_tile=show_tile, - protected=protected, - sync_perm=sync_perm, - ) + new_permission = _update_ldap_group_permission( + permission=permission, + allowed=allowed, + label=label, + show_tile=show_tile, + protected=protected, + sync_perm=sync_perm, + ) + except: + permission_delete(permission, force=True) + raise logger.debug(m18n.n("permission_created", permission=permission)) return new_permission