From b31e2b026e91d9f443624d7273baa5b0adca2c89 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Fri, 4 Dec 2020 16:38:12 +0100 Subject: [PATCH 01/11] format --- moulinette/__init__.py | 1 + moulinette/authenticators/dummy.py | 3 +- moulinette/interfaces/api.py | 9 ++++- moulinette/utils/filesystem.py | 56 +++++++++++++++++----------- test/src/old_slapdtest/_slapdtest.py | 20 ++++++---- test/test_ldap.py | 8 ++-- 6 files changed, 62 insertions(+), 35 deletions(-) diff --git a/moulinette/__init__.py b/moulinette/__init__.py index 1bb9b818..29f9bb98 100755 --- a/moulinette/__init__.py +++ b/moulinette/__init__.py @@ -121,6 +121,7 @@ def cli(args, top_parser, output_as=None, timeout=None): ) except MoulinetteError as e: import logging + logging.getLogger(logging.main_logger).error(e.strerror) return 1 return 0 diff --git a/moulinette/authenticators/dummy.py b/moulinette/authenticators/dummy.py index f5b96fb7..e2978d12 100644 --- a/moulinette/authenticators/dummy.py +++ b/moulinette/authenticators/dummy.py @@ -11,8 +11,7 @@ logger = logging.getLogger("moulinette.authenticator.dummy") class Authenticator(BaseAuthenticator): - """Dummy authenticator used for tests - """ + """Dummy authenticator used for tests""" vendor = "dummy" diff --git a/moulinette/interfaces/api.py b/moulinette/interfaces/api.py index 7f679c7d..033c3f72 100644 --- a/moulinette/interfaces/api.py +++ b/moulinette/interfaces/api.py @@ -288,7 +288,10 @@ class _ActionsMapPlugin(object): # Append messages route app.route( - "/messages", name="messages", callback=self.messages, skip=["actionsmap"], + "/messages", + name="messages", + callback=self.messages, + skip=["actionsmap"], ) # Append routes from the actions map @@ -810,7 +813,9 @@ class Interface(BaseInterface): """ logger.debug( - "starting the server instance in %s:%d", host, port, + "starting the server instance in %s:%d", + host, + port, ) try: diff --git a/moulinette/utils/filesystem.py b/moulinette/utils/filesystem.py index b7580b2c..2ff7ad52 100644 --- a/moulinette/utils/filesystem.py +++ b/moulinette/utils/filesystem.py @@ -22,9 +22,11 @@ def read_file(file_path): Keyword argument: file_path -- Path to the text file """ - assert isinstance(file_path, basestring), ( - "Error: file_path '%s' should be a string but is of type '%s' instead" - % (file_path, type(file_path)) + assert isinstance( + file_path, basestring + ), "Error: file_path '%s' should be a string but is of type '%s' instead" % ( + file_path, + type(file_path), ) # Check file exists @@ -151,24 +153,30 @@ def write_to_file(file_path, data, file_mode="w"): file_mode -- Mode used when writing the file. Option meant to be used by append_to_file to avoid duplicating the code of this function. """ - assert isinstance(data, basestring) or isinstance(data, list), ( - "Error: data '%s' should be either a string or a list but is of type '%s'" - % (data, type(data)) + assert isinstance(data, basestring) or isinstance( + data, list + ), "Error: data '%s' should be either a string or a list but is of type '%s'" % ( + data, + type(data), ) assert not os.path.isdir(file_path), ( "Error: file_path '%s' point to a dir, it should be a file" % file_path ) - assert os.path.isdir(os.path.dirname(file_path)), ( - "Error: the path ('%s') base dir ('%s') is not a dir" - % (file_path, os.path.dirname(file_path)) + assert os.path.isdir( + os.path.dirname(file_path) + ), "Error: the path ('%s') base dir ('%s') is not a dir" % ( + file_path, + os.path.dirname(file_path), ) # If data is a list, check elements are strings and build a single string if not isinstance(data, basestring): for element in data: - assert isinstance(element, basestring), ( - "Error: element '%s' should be a string but is of type '%s' instead" - % (element, type(element)) + assert isinstance( + element, basestring + ), "Error: element '%s' should be a string but is of type '%s' instead" % ( + element, + type(element), ) data = "\n".join(data) @@ -203,20 +211,26 @@ def write_to_json(file_path, data): """ # Assumptions - assert isinstance(file_path, basestring), ( - "Error: file_path '%s' should be a string but is of type '%s' instead" - % (file_path, type(file_path)) + assert isinstance( + file_path, basestring + ), "Error: file_path '%s' should be a string but is of type '%s' instead" % ( + file_path, + type(file_path), ) - assert isinstance(data, dict) or isinstance(data, list), ( - "Error: data '%s' should be a dict or a list but is of type '%s' instead" - % (data, type(data)) + assert isinstance(data, dict) or isinstance( + data, list + ), "Error: data '%s' should be a dict or a list but is of type '%s' instead" % ( + data, + type(data), ) assert not os.path.isdir(file_path), ( "Error: file_path '%s' point to a dir, it should be a file" % file_path ) - assert os.path.isdir(os.path.dirname(file_path)), ( - "Error: the path ('%s') base dir ('%s') is not a dir" - % (file_path, os.path.dirname(file_path)) + assert os.path.isdir( + os.path.dirname(file_path) + ), "Error: the path ('%s') base dir ('%s') is not a dir" % ( + file_path, + os.path.dirname(file_path), ) # Write dict to file diff --git a/test/src/old_slapdtest/_slapdtest.py b/test/src/old_slapdtest/_slapdtest.py index ab40ff55..d65b79f7 100644 --- a/test/src/old_slapdtest/_slapdtest.py +++ b/test/src/old_slapdtest/_slapdtest.py @@ -127,14 +127,12 @@ else: def identity(test_item): - """Identity decorator - """ + """Identity decorator""" return test_item def skip_unless_ci(reason, feature=None): - """Skip test unless test case is executed on CI like Travis CI - """ + """Skip test unless test case is executed on CI like Travis CI""" if not os.environ.get("CI", False): return unittest.skip(reason) elif feature in CI_DISABLED: @@ -201,7 +199,8 @@ def combined_logger( fmt=" ".join((log_name, sys_log_format)) ) my_syslog_handler = logging.handlers.SysLogHandler( - address="/dev/log", facility=SysLogHandler.LOG_DAEMON, + address="/dev/log", + facility=SysLogHandler.LOG_DAEMON, ) my_syslog_handler.setFormatter(my_syslog_formatter) new_logger.addHandler(my_syslog_handler) @@ -373,7 +372,8 @@ class SlapdObject(object): """ include_directives = "\n".join( 'include "{schema_prefix}/{schema_file}"'.format( - schema_prefix=self._schema_prefix, schema_file=schema_file, + schema_prefix=self._schema_prefix, + schema_file=schema_file, ) for schema_file in self.openldap_schema_files ) @@ -563,7 +563,13 @@ class SlapdObject(object): if ldap_uri is None: ldap_uri = self.default_ldap_uri args = ( - [ldapcommand, "-H", ldap_uri,] + self._cli_auth_args() + (extra_args or []) + [ + ldapcommand, + "-H", + ldap_uri, + ] + + self._cli_auth_args() + + (extra_args or []) ) self._log.debug("Run command: %r", " ".join(args)) proc = subprocess.Popen( diff --git a/test/test_ldap.py b/test/test_ldap.py index 13fff019..c55432e3 100644 --- a/test/test_ldap.py +++ b/test/test_ldap.py @@ -58,9 +58,11 @@ class TestLDAP: def test_authenticate_sasl_non_interactive_bind(self, ldap_server): self.ldap_conf["parameters"]["uri"] = ldap_server.uri - self.ldap_conf["parameters"]["user_rdn"] = ( - "gidNumber=%s+uidNumber=%s,cn=peercred,cn=external,cn=auth" - % (os.getgid(), os.getuid()) + self.ldap_conf["parameters"][ + "user_rdn" + ] = "gidNumber=%s+uidNumber=%s,cn=peercred,cn=external,cn=auth" % ( + os.getgid(), + os.getuid(), ) ldap_interface = m_ldap.Authenticator(**self.ldap_conf) From 82bc0e829a15b198035410233d8225d3ec5f7c39 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Thu, 31 Dec 2020 12:30:40 +0100 Subject: [PATCH 02/11] [mod] don't use catchall exceptions --- moulinette/actionsmap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moulinette/actionsmap.py b/moulinette/actionsmap.py index 91750d20..bf5db8eb 100644 --- a/moulinette/actionsmap.py +++ b/moulinette/actionsmap.py @@ -190,7 +190,7 @@ class PatternParameter(_ExtraParameter): # Use temporarly utf-8 encoded value try: v = unicode(arg_value, "utf-8") - except: + except Exception: v = arg_value if v and not re.match(pattern, v or "", re.UNICODE): From 8566eaaa1fb63acbe97ce9fb24b3214bcd04afd4 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Thu, 31 Dec 2020 13:25:05 +0100 Subject: [PATCH 03/11] [mod] don't use catchall exceptions episode 2 --- moulinette/interfaces/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moulinette/interfaces/cli.py b/moulinette/interfaces/cli.py index 441c70d2..28321e5c 100644 --- a/moulinette/interfaces/cli.py +++ b/moulinette/interfaces/cli.py @@ -380,7 +380,7 @@ class ActionsMapParser(BaseActionsMapParser): ret = self._parser.parse_args(args) except SystemExit: raise - except: + except Exception: logger.exception("unable to parse arguments '%s'", " ".join(args)) raise MoulinetteError("error_see_log") @@ -404,7 +404,7 @@ class ActionsMapParser(BaseActionsMapParser): ret = self._parser.parse_args(args) except SystemExit: raise - except: + except Exception: logger.exception("unable to parse arguments '%s'", " ".join(args)) raise MoulinetteError("error_see_log") else: From 2caf1234e88ce336dd1fb33ec3ecc4c8ab5b2f2b Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Thu, 31 Dec 2020 23:44:23 +0100 Subject: [PATCH 04/11] [fix] no catchall exception --- moulinette/interfaces/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moulinette/interfaces/__init__.py b/moulinette/interfaces/__init__.py index ad6f2034..03ee8261 100644 --- a/moulinette/interfaces/__init__.py +++ b/moulinette/interfaces/__init__.py @@ -371,7 +371,7 @@ class _CallbackAction(argparse.Action): try: # Execute callback and get returned value value = self.callback(namespace, values, **self.callback_kwargs) - except: + except Exception: logger.exception( "cannot get value from callback method " "'{0}'".format(self.callback_method) From f9454da5e7960d0410edad28fe22ef4e16bbbb92 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Thu, 31 Dec 2020 23:57:10 +0100 Subject: [PATCH 05/11] [mod] trash this UX madness that is error_see_logs and improve error messages --- locales/en.json | 1 - moulinette/actionsmap.py | 31 ++++++++++++++++++------------- moulinette/interfaces/__init__.py | 30 ++++++++++++++++-------------- moulinette/interfaces/api.py | 26 ++++++++++++++++++-------- moulinette/interfaces/cli.py | 20 ++++++++++++++------ test/conftest.py | 2 +- test/test_actionsmap.py | 4 ++-- 7 files changed, 69 insertions(+), 45 deletions(-) diff --git a/locales/en.json b/locales/en.json index 7558e910..fbc49a55 100644 --- a/locales/en.json +++ b/locales/en.json @@ -7,7 +7,6 @@ "deprecated_command": "'{prog} {command}' is deprecated and will be removed in the future", "deprecated_command_alias": "'{prog} {old}' is deprecated and will be removed in the future, use '{prog} {new}' instead", "error": "Error:", - "error_see_log": "An error occurred. Please see the logs for details, they are located in /var/log/yunohost/.", "file_exists": "File already exists: '{path}'", "file_not_exist": "File does not exist: '{path}'", "folder_exists": "Folder already exists: '{path}'", diff --git a/moulinette/actionsmap.py b/moulinette/actionsmap.py index bf5db8eb..7b7dc53f 100644 --- a/moulinette/actionsmap.py +++ b/moulinette/actionsmap.py @@ -304,14 +304,12 @@ class ExtraArgumentParser(object): # Validate parameter value parameters[p] = klass.validate(v, arg_name) except Exception as e: - logger.error( - "unable to validate extra parameter '%s' " - "for argument '%s': %s", - p, - arg_name, - e, + error_message = ( + "unable to validate extra parameter '%s' for argument '%s': %s" + % (p, arg_name, e) ) - raise MoulinetteError("error_see_log") + logger.error(error_message) + raise MoulinetteError(error_message, raw_msg=True) return parameters @@ -478,10 +476,12 @@ class ActionsMap(object): try: mod = import_module("moulinette.authenticators.%s" % auth_conf["vendor"]) except ImportError: - logger.exception( - "unable to load authenticator vendor '%s'", auth_conf["vendor"] + error_message = ( + "unable to load authenticator vendor module 'moulinette.authenticators.%s'" + % auth_conf["vendor"] ) - raise MoulinetteError("error_see_log") + logger.exception(error_message) + raise MoulinetteError(error_message, raw_msg=True) else: return mod.Authenticator(**auth_conf) @@ -561,12 +561,17 @@ class ActionsMap(object): time() - start, ) func = getattr(mod, func_name) - except (AttributeError, ImportError): + except (AttributeError, ImportError) as e: import traceback traceback.print_exc() - logger.exception("unable to load function %s.%s", namespace, func_name) - raise MoulinetteError("error_see_log") + error_message = "unable to load function %s.%s because: %s" % ( + namespace, + func_name, + e, + ) + logger.exception(error_message) + raise MoulinetteError(error_message, raw_msg=True) else: log_id = start_action_logging() if logger.isEnabledFor(logging.DEBUG): diff --git a/moulinette/interfaces/__init__.py b/moulinette/interfaces/__init__.py index 03ee8261..e8c55c1b 100644 --- a/moulinette/interfaces/__init__.py +++ b/moulinette/interfaces/__init__.py @@ -250,24 +250,24 @@ class BaseActionsMapParser(object): # Store only if authentication is needed conf["authenticate"] = True if self.interface in ifaces else False else: - logger.error( + error_message = ( "expecting 'all', 'False' or a list for " - "configuration 'authenticate', got %r", - ifaces, + "configuration 'authenticate', got %r" % ifaces, ) - raise MoulinetteError("error_see_log") + logger.error(error_message) + raise MoulinetteError(error_message, raw_msg=True) # -- 'authenticator' auth = configuration.get("authenticator", "default") if not is_global and isinstance(auth, str): # Store needed authenticator profile if auth not in self.global_conf["authenticator"]: - logger.error( + error_message = ( "requesting profile '%s' which is undefined in " - "global configuration of 'authenticator'", - auth, + "global configuration of 'authenticator'" % auth, ) - raise MoulinetteError("error_see_log") + logger.error(error_message) + raise MoulinetteError(error_message, raw_msg=True) else: conf["authenticator"] = auth elif is_global and isinstance(auth, dict): @@ -286,12 +286,13 @@ class BaseActionsMapParser(object): } conf["authenticator"] = auths else: - logger.error( + error_message = ( "expecting a dict of profile(s) or a profile name " "for configuration 'authenticator', got %r", auth, ) - raise MoulinetteError("error_see_log") + logger.error(error_message) + raise MoulinetteError(error_message, raw_msg=True) return conf @@ -371,12 +372,13 @@ class _CallbackAction(argparse.Action): try: # Execute callback and get returned value value = self.callback(namespace, values, **self.callback_kwargs) - except Exception: - logger.exception( + except Exception as e: + error_message = ( "cannot get value from callback method " - "'{0}'".format(self.callback_method) + "'{0}': {1}".format(self.callback_method, e) ) - raise MoulinetteError("error_see_log") + logger.exception(error_message) + raise MoulinetteError(error_message, raw_msg=True) else: if value: if self.callback_return: diff --git a/moulinette/interfaces/api.py b/moulinette/interfaces/api.py index 033c3f72..b2d245ef 100644 --- a/moulinette/interfaces/api.py +++ b/moulinette/interfaces/api.py @@ -675,9 +675,13 @@ class ActionsMapParser(BaseActionsMapParser): try: # Retrieve the tid for the route tid, _ = self._parsers[kwargs.get("route")] - except KeyError: - logger.error("no argument parser found for route '%s'", kwargs.get("route")) - raise MoulinetteError("error_see_log") + except KeyError as e: + error_message = "no argument parser found for route '%s': %s" % ( + kwargs.get("route"), + e, + ) + logger.error(error_message) + raise MoulinetteError(error_message, raw_msg=True) if self.get_conf(tid, "authenticate"): authenticator = self.get_conf(tid, "authenticator") @@ -703,9 +707,10 @@ class ActionsMapParser(BaseActionsMapParser): try: # Retrieve the parser for the route _, parser = self._parsers[route] - except KeyError: - logger.error("no argument parser found for route '%s'", route) - raise MoulinetteError("error_see_log") + except KeyError as e: + error_message = "no argument parser found for route '%s': %s" % (route, e) + logger.error(error_message) + raise MoulinetteError(error_message, raw_msg=True) ret = argparse.Namespace() # TODO: Catch errors? @@ -825,10 +830,15 @@ class Interface(BaseInterface): server = WSGIServer((host, port), self._app, handler_class=WebSocketHandler) server.serve_forever() except IOError as e: - logger.exception("unable to start the server instance on %s:%d", host, port) + error_message = "unable to start the server instance on %s:%d: %s" % ( + host, + port, + e, + ) + logger.exception(error_message) if e.args[0] == errno.EADDRINUSE: raise MoulinetteError("server_already_running") - raise MoulinetteError("error_see_log") + raise MoulinetteError(error_message) # Routes handlers diff --git a/moulinette/interfaces/cli.py b/moulinette/interfaces/cli.py index 28321e5c..250e9379 100644 --- a/moulinette/interfaces/cli.py +++ b/moulinette/interfaces/cli.py @@ -380,9 +380,13 @@ class ActionsMapParser(BaseActionsMapParser): ret = self._parser.parse_args(args) except SystemExit: raise - except Exception: - logger.exception("unable to parse arguments '%s'", " ".join(args)) - raise MoulinetteError("error_see_log") + except Exception as e: + error_message = "unable to parse arguments '%s' because: %s" % ( + " ".join(args), + e, + ) + logger.exception(error_message) + raise MoulinetteError(error_message, raw_msg=True) tid = getattr(ret, "_tid", None) if self.get_conf(tid, "authenticate"): @@ -404,9 +408,13 @@ class ActionsMapParser(BaseActionsMapParser): ret = self._parser.parse_args(args) except SystemExit: raise - except Exception: - logger.exception("unable to parse arguments '%s'", " ".join(args)) - raise MoulinetteError("error_see_log") + except Exception as e: + error_message = "unable to parse arguments '%s' because: %s" % ( + " ".join(args), + e, + ) + logger.exception(error_message) + raise MoulinetteError(error_message, raw_msg=True) else: self.prepare_action_namespace(getattr(ret, "_tid", None), ret) self._parser.dequeue_callbacks(ret) diff --git a/test/conftest.py b/test/conftest.py index 793a0703..9008924b 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -27,7 +27,7 @@ def patch_translate(moulinette): def new_translate(self, key, *args, **kwargs): if key not in self._translations[self.default_locale].keys(): - message = "Unable to retrieve key %s for default locale!" % key + message = "Unable to retrieve key '%s' for default locale!" % key raise KeyError(message) return old_translate(self, key, *args, **kwargs) diff --git a/test/test_actionsmap.py b/test/test_actionsmap.py index 9055b89f..7614520d 100644 --- a/test/test_actionsmap.py +++ b/test/test_actionsmap.py @@ -188,7 +188,7 @@ def test_extra_argument_parser_add_argument_bad_arg(iface): with pytest.raises(MoulinetteError) as exception: extra_argument_parse.add_argument(GLOBAL_SECTION, "foo", {"ask": 1}) - translation = m18n.g("error_see_log") + translation = m18n.g("error") expected_msg = translation.format() assert expected_msg in str(exception) @@ -265,7 +265,7 @@ def test_actions_map_import_error(mocker): with pytest.raises(MoulinetteError) as exception: amap.process({}, timeout=30, route=("GET", "/test-auth/none")) - translation = m18n.g("error_see_log") + translation = m18n.g("error") expected_msg = translation.format() assert expected_msg in str(exception) From 92367275618e48f7f3ebbeaa9a32a41dc3e53d9c Mon Sep 17 00:00:00 2001 From: Kay0u Date: Wed, 6 Jan 2021 01:29:33 +0100 Subject: [PATCH 06/11] Fix https://github.com/YunoHost/yunohost/pull/1075#discussion_r551045491 --- moulinette/actionsmap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moulinette/actionsmap.py b/moulinette/actionsmap.py index 7b7dc53f..40189335 100644 --- a/moulinette/actionsmap.py +++ b/moulinette/actionsmap.py @@ -90,7 +90,7 @@ class CommentParameter(_ExtraParameter): skipped_iface = ["api"] def __call__(self, message, arg_name, arg_value): - if arg_value: + if arg_value is None: return return msignals.display(m18n.n(message)) From bc6287d330df95c8a0ad454f5500d2751491e365 Mon Sep 17 00:00:00 2001 From: ppr Date: Sat, 2 Jan 2021 16:07:24 +0000 Subject: [PATCH 07/11] Translated using Weblate (French) Currently translated at 100.0% (56 of 56 strings) Translation: YunoHost/moulinette Translate-URL: https://translate.yunohost.org/projects/yunohost/moulinette/fr/ --- locales/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/fr.json b/locales/fr.json index 2719373e..2fa0b763 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -56,6 +56,6 @@ "warn_the_user_about_waiting_lock_again": "Toujours en attente...", "warn_the_user_that_lock_is_acquired": "La commande précédente vient de se terminer, lancement de cette nouvelle commande", "invalid_token": "Jeton non valide - veuillez vous authentifier", - "ldap_server_is_down_restart_it": "Le service LDAP est arrêté, nous tentons de le redémarrer...", + "ldap_server_is_down_restart_it": "Le service LDAP s'est arrêté, une tentative de redémarrage est en cours ...", "session_expired": "La session a expiré. Merci de vous ré-authentifier." } From 04890c4a618f4c681ba8a3aa94f13f11f73c7995 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 7 Jan 2021 00:26:05 +0100 Subject: [PATCH 08/11] Update changelog for 4.1.2 --- debian/changelog | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/debian/changelog b/debian/changelog index 131c812e..586e1b92 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,14 @@ +moulinette (4.1.2) testing; urgency=low + + - [mod] Misc code cleanup ([#259](https://github.com/YunoHost/moulinette/pull/259), 82bc0e82, 8566eaaa, 2caf1234) + - [mod] Improve error messages ([#264](https://github.com/YunoHost/moulinette/pull/264)) + - [fix] Minor issue about 'comment' in actionmaps ([#266](https://github.com/YunoHost/moulinette/pull/266)) + - [i18n] Improve translation for French + + Thanks to all contributors <3 ! (Kay0u, Bram, ppr) + + -- Alexandre Aubin Thu, 07 Jan 2021 00:23:44 +0100 + moulinette (4.1.1) testing; urgency=low - [enh] Add options to write_to_json ([#261](https://github.com/YunoHost/moulinette/pull/261)) From 7333b6a342a811339b61454373b30a5169693c28 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 8 Jan 2021 03:15:32 +0100 Subject: [PATCH 09/11] Update changelog for 4.1.3 --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index 586e1b92..e2245b50 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +moulinette (4.1.3) stable; urgency=low + + - Stable release + + -- Alexandre Aubin Fri, 08 Jan 2021 03:15:05 +0100 + moulinette (4.1.2) testing; urgency=low - [mod] Misc code cleanup ([#259](https://github.com/YunoHost/moulinette/pull/259), 82bc0e82, 8566eaaa, 2caf1234) From 755a475e5d21835d8ca275f92464a853f8b5e94a Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 13 Jan 2021 02:30:39 +0100 Subject: [PATCH 10/11] We don't really care that there's 'nothing to update in ldap' --- moulinette/authenticators/ldap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moulinette/authenticators/ldap.py b/moulinette/authenticators/ldap.py index 860a45c9..3f44e321 100644 --- a/moulinette/authenticators/ldap.py +++ b/moulinette/authenticators/ldap.py @@ -218,7 +218,7 @@ class Authenticator(BaseAuthenticator): ldif = modlist.modifyModlist(actual_entry[0], attr_dict, ignore_oldexistent=1) if ldif == []: - logger.warning("Nothing to update in LDAP") + logger.debug("Nothing to update in LDAP") return True try: From 1dac904e31ac26c2723bc45365bccc183ad63249 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Thu, 14 Jan 2021 21:50:33 +0100 Subject: [PATCH 11/11] Update changelog for 4.1.4 --- debian/changelog | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/debian/changelog b/debian/changelog index e2245b50..c6a67e7f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +moulinette (4.1.4) stable; urgency=low + + - [enh] Remove useless warning + - Stable release + + Thanks to all contributors <3 ! (Aleks) + + -- Kayou Thu, 14 Jan 2021 21:49:37 +0100 + moulinette (4.1.3) stable; urgency=low - Stable release