From b67105f04bf0d7e52649040ccca277b40ae21bc0 Mon Sep 17 00:00:00 2001 From: Maniack Crudelis Date: Tue, 6 Nov 2018 01:00:57 +0100 Subject: [PATCH 01/49] [enh] Wait for dpkg lock to be free --- data/helpers.d/package | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/data/helpers.d/package b/data/helpers.d/package index db3b50e0e..3ac93a9db 100644 --- a/data/helpers.d/package +++ b/data/helpers.d/package @@ -1,3 +1,26 @@ +# Check if apt is free to use, or wait, until timeout. +# +# [internal] +# +# usage: ynh_is_dpkg_free +ynh_is_dpkg_free() { + local try + # With seq 1 17, timeout will be almost 30 minutes + for try in `seq 1 17` + do + # Check if /var/lib/dpkg/lock is used by another process + if sudo lsof /var/lib/dpkg/lock > /dev/null + then + echo "apt is already in use..." + # Sleep an exponential time at each round + sleep $(( try * try )) + else + break + fi + done + echo "apt still used, but timeout reached !" +} + # Check either a package is installed or not # # example: ynh_package_is_installed 'yunohost' && echo "ok" @@ -5,6 +28,7 @@ # usage: ynh_package_is_installed name # | arg: name - the package name to check ynh_package_is_installed() { + ynh_is_dpkg_free dpkg-query -W -f '${Status}' "$1" 2>/dev/null \ | grep -c "ok installed" &>/dev/null } @@ -30,6 +54,7 @@ ynh_package_version() { # # usage: ynh_apt update ynh_apt() { + ynh_is_dpkg_free DEBIAN_FRONTEND=noninteractive sudo apt-get -y $@ } @@ -105,6 +130,7 @@ ynh_package_install_from_equivs () { # Create a fake deb package with equivs-build and the given control file # Install the fake package without its dependencies with dpkg # Install missing dependencies with ynh_package_install + ynh_is_dpkg_free (cp "$controlfile" "${TMPDIR}/control" && cd "$TMPDIR" \ && equivs-build ./control 1>/dev/null \ && sudo dpkg --force-depends \ From 4d0deea5638d699491f8f2b0955698a00b60592a Mon Sep 17 00:00:00 2001 From: airwoodix Date: Sat, 17 Nov 2018 23:27:33 +0100 Subject: [PATCH 02/49] Fix app_addaccess behaviour when 'allowed_users' is initially empty --- src/yunohost/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 8b3ffecdc..e26700c49 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -965,7 +965,7 @@ def app_addaccess(auth, apps, users=[]): operation_logger.start() allowed_users = set() - if 'allowed_users' in app_settings: + if 'allowed_users' in app_settings and app_settings['allowed_users']: allowed_users = set(app_settings['allowed_users'].split(',')) for allowed_user in users: From eb8792376c1ec41a894b4f0963f0477bf2312354 Mon Sep 17 00:00:00 2001 From: "ljf (zamentur)" Date: Tue, 20 Nov 2018 20:47:36 +0100 Subject: [PATCH 03/49] [enh] Better name ynh_wait_dpkg_free --- data/helpers.d/package | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/data/helpers.d/package b/data/helpers.d/package index 3ac93a9db..22adb9b15 100644 --- a/data/helpers.d/package +++ b/data/helpers.d/package @@ -2,8 +2,8 @@ # # [internal] # -# usage: ynh_is_dpkg_free -ynh_is_dpkg_free() { +# usage: ynh_wait_dpkg_free +ynh_wait_dpkg_free() { local try # With seq 1 17, timeout will be almost 30 minutes for try in `seq 1 17` @@ -28,7 +28,7 @@ ynh_is_dpkg_free() { # usage: ynh_package_is_installed name # | arg: name - the package name to check ynh_package_is_installed() { - ynh_is_dpkg_free + ynh_wait_dpkg_free dpkg-query -W -f '${Status}' "$1" 2>/dev/null \ | grep -c "ok installed" &>/dev/null } @@ -54,7 +54,7 @@ ynh_package_version() { # # usage: ynh_apt update ynh_apt() { - ynh_is_dpkg_free + ynh_wait_dpkg_free DEBIAN_FRONTEND=noninteractive sudo apt-get -y $@ } @@ -130,7 +130,7 @@ ynh_package_install_from_equivs () { # Create a fake deb package with equivs-build and the given control file # Install the fake package without its dependencies with dpkg # Install missing dependencies with ynh_package_install - ynh_is_dpkg_free + ynh_wait_dpkg_free (cp "$controlfile" "${TMPDIR}/control" && cd "$TMPDIR" \ && equivs-build ./control 1>/dev/null \ && sudo dpkg --force-depends \ From 98ae285c91ac1309e9963362c59e107c1d0b7fb5 Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 20 Nov 2018 22:48:35 +0100 Subject: [PATCH 04/49] [enh] Add lsof dependencies in case we decide to remove mariadb --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index be63436da..1f4995195 100644 --- a/debian/control +++ b/debian/control @@ -26,7 +26,7 @@ Depends: ${python:Depends}, ${misc:Depends} , metronome , rspamd (>= 1.6.0), redis-server, opendkim-tools , haveged, fake-hwclock - , equivs + , equivs, lsof Recommends: yunohost-admin , openssh-server, ntp, inetutils-ping | iputils-ping , bash-completion, rsyslog, etckeeper From 5a22b400eb0f2e49199e9161eabaa7fd4e13dda1 Mon Sep 17 00:00:00 2001 From: "ljf (zamentur)" Date: Wed, 21 Nov 2018 18:37:08 +0100 Subject: [PATCH 05/49] [fix] Unknown variable password in user_update --- src/yunohost/user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/user.py b/src/yunohost/user.py index baf52eb2f..bb39dd58e 100644 --- a/src/yunohost/user.py +++ b/src/yunohost/user.py @@ -313,7 +313,7 @@ def user_update(operation_logger, auth, username, firstname=None, lastname=None, if change_password: # Ensure sufficiently complex password - assert_password_is_strong_enough("user", password) + assert_password_is_strong_enough("user", change_password) new_attr_dict['userPassword'] = _hash_user_password(change_password) From 8ba552c0ff9a8f9c4579f68a6c6aecab2d5334f5 Mon Sep 17 00:00:00 2001 From: Syed Faraaz Ahmad Date: Fri, 23 Nov 2018 15:26:10 +0530 Subject: [PATCH 06/49] Fix typo in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4033bd6fb..4bd070bea 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ This repository is the core of YunoHost code. - [Modules for the XMPP server Metronome](https://github.com/YunoHost/yunohost/tree/stable/lib/metronome/modules). - [Debian files](https://github.com/YunoHost/yunohost/tree/stable/debian) for package creation. -## How does it works? +## How does it work? - Python core scripts are accessible through two interfaces thanks to the [moulinette framework](https://github.com/YunoHost/moulinette): - [CLI](https://en.wikipedia.org/wiki/Command-line_interface) for `yunohost` command. - [API](https://en.wikipedia.org/wiki/Application_programming_interface) for [web administration module](https://github.com/YunoHost/yunohost-admin) (other modules could be implemented). From 6bfcedfe1d30d1579dd093b983545017d971651d Mon Sep 17 00:00:00 2001 From: Maniack Crudelis Date: Fri, 23 Nov 2018 13:21:37 +0100 Subject: [PATCH 07/49] Do not fail on missing fail2ban config during the backup (#558) * Do not fail on missing file during the backup * Fix for allow to backup without a fail2ban config file * Tab -> space consistency --- data/helpers.d/filesystem | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/data/helpers.d/filesystem b/data/helpers.d/filesystem index c07de2ece..badc0e997 100644 --- a/data/helpers.d/filesystem +++ b/data/helpers.d/filesystem @@ -60,8 +60,16 @@ ynh_backup() { # ============================================================================== # Be sure the source path is not empty [[ -e "${SRC_PATH}" ]] || { - echo "Source path '${SRC_PATH}' does not exist" >&2 - return 1 + echo "!!! Source path '${SRC_PATH}' does not exist !!!" >&2 + + # This is a temporary fix for fail2ban config files missing after the migration to stretch. + if echo "${SRC_PATH}" | grep --quiet "/etc/fail2ban" + then + touch "${SRC_PATH}" + echo "The missing file will be replaced by a dummy one for the backup !!!" >&2 + else + return 1 + fi } # Transform the source path as an absolute path From ae0497b4f06f91e106239757da25f78e00099c02 Mon Sep 17 00:00:00 2001 From: Sylke Vicious Date: Thu, 8 Nov 2018 15:21:37 +0000 Subject: [PATCH 08/49] Translated using Weblate (Italian) Currently translated at 56.3% (262 of 465 strings) --- locales/it.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/locales/it.json b/locales/it.json index f0597d3a5..2fb843fc0 100644 --- a/locales/it.json +++ b/locales/it.json @@ -260,5 +260,7 @@ "app_change_url_success": "URL dell'applicazione {app:s} cambiato con successo in {domain:s}{path:s}", "app_make_default_location_already_used": "Impostazione dell'applicazione '{app}' come predefinita del dominio {domain} non riuscita perchè è già stata impostata per l'altra applicazione '{other_app}'", "app_location_unavailable": "Questo URL non è disponibile o va in conflitto con la/le applicazione/i già installata/e:\n{apps:s}", - "app_upgrade_app_name": "Aggiornando l'applicazione {app}..." + "app_upgrade_app_name": "Aggiornando l'applicazione {app}...", + "app_upgrade_some_app_failed": "Impossibile aggiornare alcune applicazioni", + "appslist_corrupted_json": "Caricamento della lista delle applicazioni non riuscita. Sembra che {filename:s} sia corrotto." } From b6c51b39fafa8670f5cb1b496e44ff582b3c3f75 Mon Sep 17 00:00:00 2001 From: Sylke Vicious Date: Thu, 8 Nov 2018 15:34:09 +0000 Subject: [PATCH 09/49] Translated using Weblate (Italian) Currently translated at 59.1% (275 of 465 strings) --- locales/it.json | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/locales/it.json b/locales/it.json index 2fb843fc0..69be4e394 100644 --- a/locales/it.json +++ b/locales/it.json @@ -262,5 +262,18 @@ "app_location_unavailable": "Questo URL non è disponibile o va in conflitto con la/le applicazione/i già installata/e:\n{apps:s}", "app_upgrade_app_name": "Aggiornando l'applicazione {app}...", "app_upgrade_some_app_failed": "Impossibile aggiornare alcune applicazioni", - "appslist_corrupted_json": "Caricamento della lista delle applicazioni non riuscita. Sembra che {filename:s} sia corrotto." + "appslist_corrupted_json": "Caricamento della lista delle applicazioni non riuscita. Sembra che {filename:s} sia corrotto.", + "appslist_could_not_migrate": "Migrazione della lista delle applicazioni {appslist:s} non riuscita! Impossibile analizzare l'URL... La vecchia operazione pianificata è stata tenuta in {bkp_file:s}.", + "appslist_migrating": "Migrando la lista di applicazioni {appslist:s} ...", + "appslist_name_already_tracked": "C'è già una lista di applicazioni registrata con il nome {name:s}.", + "appslist_url_already_tracked": "C'è già una lista di applicazioni registrata con URL {url:s}.", + "ask_path": "Percorso", + "backup_abstract_method": "Questo metodo di backup non è ancora stato implementato", + "backup_applying_method_borg": "Inviando tutti i file da salvare nel backup nel deposito borg-backup...", + "backup_applying_method_copy": "Copiando tutti i files nel backup...", + "backup_applying_method_custom": "Chiamando il metodo di backup personalizzato '{method:s}'...", + "backup_applying_method_tar": "Creando l'archivio tar del backup...", + "backup_archive_mount_failed": "Montaggio dell'archivio del backup non riuscito", + "backup_archive_system_part_not_available": "La parte di sistema '{part:s}' non è disponibile in questo backup", + "backup_archive_writing_error": "Impossibile aggiungere i file al backup nell'archivio compresso" } From 0b9eab786197ba0fc3eaf46f0492c440686c3f14 Mon Sep 17 00:00:00 2001 From: Quenti Date: Sat, 10 Nov 2018 15:43:24 +0000 Subject: [PATCH 10/49] Translated using Weblate (Occitan) Currently translated at 100.0% (465 of 465 strings) --- locales/oc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/oc.json b/locales/oc.json index 7a4814389..91b455210 100644 --- a/locales/oc.json +++ b/locales/oc.json @@ -451,7 +451,7 @@ "migration_description_0004_php5_to_php7_pools": "Tornar configurar lo pools PHP per utilizar PHP 7 allòc del 5", "migration_description_0005_postgresql_9p4_to_9p6": "Migracion de las basas de donadas de postgresql 9.4 cap a 9.6", "migration_0005_postgresql_94_not_installed": "Postgresql es pas installat sul sistèma. Pas res de far !", - "migration_0005_postgresql_96_not_installed": "Avèm trobat que Postgresql 9.4 es installat, mas cap de version de Postgresql 9.6 pas trobada ! Quicòm d’estranh a degut arribar a vòstre sistèma :( ...", + "migration_0005_postgresql_96_not_installed": "Avèm trobat que Postgresql 9.4 es installat, mas cap de version de Postgresql 9.6 pas trobada !? Quicòm d’estranh a degut arribar a vòstre sistèma :( …", "migration_0005_not_enough_space": "I a pas pro d’espaci disponible sus {path} per lançar la migracion d’aquela passa :(.", "recommend_to_add_first_user": "La post installacion es acabada, mas YunoHost fa besonh d’almens un utilizaire per foncionar coma cal. Vos cal n’ajustar un en utilizant la comanda « yunohost user create » o ben l’interfàcia d’administracion.", "service_description_php7.0-fpm": "executa d’aplicacions escrichas en PHP amb nginx", From ae56546c94124a0a9ada9c6b5b740fa7c2257652 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Holcroft Date: Sat, 17 Nov 2018 22:54:10 +0000 Subject: [PATCH 11/49] Translated using Weblate (French) Currently translated at 99.3% (462 of 465 strings) --- locales/fr.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/locales/fr.json b/locales/fr.json index 814f3acd4..70ba9f47b 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -469,5 +469,13 @@ "migration_0005_not_enough_space": "Il n’y a pas assez d’espace libre de disponible sur {path} pour lancer maintenant la migration :(.", "recommend_to_add_first_user": "La post-installation est terminée, mais YunoHost a besoin d'au moins un utilisateur pour fonctionner correctement. Vous devez en ajouter un en utilisant 'yunohost user create' ou l'interface d'administration.", "service_description_php7.0-fpm": "exécute des applications écrites en PHP avec nginx", - "users_available": "Liste des utilisateurs disponibles :" + "users_available": "Liste des utilisateurs disponibles :", + "good_practices_about_admin_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe d’administration. Le mot de passe doit comporter au moins 8 caractères – bien qu’il soit recommandé d’utiliser un mot de passe plus long (c’est-à-dire une phrase de chiffrement) et/ou d’utiliser différents types de caractères (majuscules, minuscules, chiffres et caractères spéciaux).", + "good_practices_about_user_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe utilisateur. Le mot de passe doit comporter au moins 8 caractères – bien qu’il soit recommandé d’utiliser un mot de passe plus long (c’est-à-dire une phrase de chiffrement) et/ou d’utiliser différents types de caractères (majuscules, minuscules, chiffres et caractères spéciaux).", + "migration_description_0006_sync_admin_and_root_passwords": "Synchroniser les mots de passe admin et root", + "migration_0006_disclaimer": "Yunohost s'attend maintenant à ce que les mots de passe admin et root soient synchronisés. En exécutant cette migration, votre mot de passe root sera remplacé par le mot de passe administrateur.", + "migration_0006_done": "Votre mot de passe root a été remplacé par celui de votre adminitrateur.", + "password_listed": "Ce mot de passe est l’un des mots de passe les plus utilisés dans le monde. Veuillez choisir quelque chose d’un peu plus unique.", + "password_too_simple_1": "Le mot de passe doit comporter au moins 8 caractères", + "password_too_simple_2": "Le mot de passe doit comporter au moins 8 caractères et contenir des chiffres, des caractères majuscules et minuscules." } From 06e7485958e758388bcfaaf884b4c16cb53bf594 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Holcroft Date: Sat, 17 Nov 2018 22:58:02 +0000 Subject: [PATCH 12/49] Translated using Weblate (French) Currently translated at 99.5% (463 of 465 strings) --- locales/fr.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/locales/fr.json b/locales/fr.json index 70ba9f47b..b2ad1b04b 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -477,5 +477,6 @@ "migration_0006_done": "Votre mot de passe root a été remplacé par celui de votre adminitrateur.", "password_listed": "Ce mot de passe est l’un des mots de passe les plus utilisés dans le monde. Veuillez choisir quelque chose d’un peu plus unique.", "password_too_simple_1": "Le mot de passe doit comporter au moins 8 caractères", - "password_too_simple_2": "Le mot de passe doit comporter au moins 8 caractères et contenir des chiffres, des caractères majuscules et minuscules." + "password_too_simple_2": "Le mot de passe doit comporter au moins 8 caractères et contenir des chiffres, des caractères majuscules et minuscules", + "password_too_simple_3": "Le mot de passe doit comporter au moins 8 caractères et contenir des chiffres, des caractères majuscules, minuscules et spéciaux." } From 3d2053c9675561a0ae0b06c8a616a2370bd83edc Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Holcroft Date: Sat, 17 Nov 2018 22:58:26 +0000 Subject: [PATCH 13/49] Translated using Weblate (French) Currently translated at 100.0% (465 of 465 strings) --- locales/fr.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/locales/fr.json b/locales/fr.json index b2ad1b04b..ae3ac4988 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -478,5 +478,7 @@ "password_listed": "Ce mot de passe est l’un des mots de passe les plus utilisés dans le monde. Veuillez choisir quelque chose d’un peu plus unique.", "password_too_simple_1": "Le mot de passe doit comporter au moins 8 caractères", "password_too_simple_2": "Le mot de passe doit comporter au moins 8 caractères et contenir des chiffres, des caractères majuscules et minuscules", - "password_too_simple_3": "Le mot de passe doit comporter au moins 8 caractères et contenir des chiffres, des caractères majuscules, minuscules et spéciaux." + "password_too_simple_3": "Le mot de passe doit comporter au moins 8 caractères et contenir des chiffres, des caractères majuscules, minuscules et spéciaux", + "password_too_simple_4": "Le mot de passe doit comporter au moins 12 caractères et contenir des chiffres, des caractères majuscules, minuscules et spéciaux", + "root_password_desynchronized": "Le mot de passe administrateur a été changé, mais YunoHost n’a pas pu le propager sur le mot de passe root !" } From 52679e1ee32255891210258d009f272d88a71d5f Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Holcroft Date: Sat, 17 Nov 2018 23:07:18 +0000 Subject: [PATCH 14/49] Translated using Weblate (French) Currently translated at 100.0% (465 of 465 strings) --- locales/fr.json | 240 ++++++++++++++++++++++++------------------------ 1 file changed, 120 insertions(+), 120 deletions(-) diff --git a/locales/fr.json b/locales/fr.json index ae3ac4988..7119039db 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -1,25 +1,25 @@ { "action_invalid": "Action « {action:s} » incorrecte", - "admin_password": "Mot de passe d'administration", + "admin_password": "Mot de passe d’administration", "admin_password_change_failed": "Impossible de changer le mot de passe", - "admin_password_changed": "Le mot de passe d'administration a été modifié", + "admin_password_changed": "Le mot de passe d’administration a été modifié", "app_already_installed": "{app:s} est déjà installé", - "app_argument_choice_invalid": "Choix invalide pour le paramètre « {name:s} », il doit être l'un de {choices:s}", + "app_argument_choice_invalid": "Choix invalide pour le paramètre « {name:s} », il doit être l’un de {choices:s}", "app_argument_invalid": "Valeur invalide pour le paramètre « {name:s} » : {error:s}", "app_argument_missing": "Paramètre manquant « {:s} »", "app_argument_required": "Le paramètre « {name:s} » est requis", - "app_extraction_failed": "Impossible d'extraire les fichiers d'installation", - "app_id_invalid": "Id d'application incorrect", - "app_incompatible": "L'application {app} est incompatible avec votre version de YunoHost", - "app_install_files_invalid": "Fichiers d'installation incorrects", - "app_location_already_used": "L'application '{app}' est déjà installée à cet emplacement ({path})", - "app_location_install_failed": "Impossible d'installer l'application à cet emplacement pour cause de conflit avec l'app '{other_app}' déjà installée sur '{other_path}'", - "app_manifest_invalid": "Manifeste d'application incorrect : {error}", + "app_extraction_failed": "Impossible d’extraire les fichiers d’installation", + "app_id_invalid": "Id d’application incorrect", + "app_incompatible": "L’application {app} est incompatible avec votre version de YunoHost", + "app_install_files_invalid": "Fichiers d’installation incorrects", + "app_location_already_used": "L’application « {app} » est déjà installée à cet emplacement ({path})", + "app_location_install_failed": "Impossible d’installer l’application à cet emplacement pour cause de conflit avec l’app « {other_app} » déjà installée sur « {other_path} »", + "app_manifest_invalid": "Manifeste d’application incorrect : {error}", "app_no_upgrade": "Aucune application à mettre à jour", "app_not_correctly_installed": "{app:s} semble être mal installé", - "app_not_installed": "{app:s} n'est pas installé", - "app_not_properly_removed": "{app:s} n'a pas été supprimé correctement", - "app_package_need_update": "Le paquet de l'application {app} doit être mis à jour pour suivre les changements de YunoHost", + "app_not_installed": "{app:s} n’est pas installé", + "app_not_properly_removed": "{app:s} n’a pas été supprimé correctement", + "app_package_need_update": "Le paquet de l’application {app} doit être mis à jour pour suivre les changements de YunoHost", "app_recent_version_required": "{app:s} nécessite une version plus récente de YunoHost", "app_removed": "{app:s} a été supprimé", "app_requirements_checking": "Vérification des paquets requis pour {app}...", @@ -27,45 +27,45 @@ "app_requirements_unmeet": "Les pré-requis de {app} ne sont pas satisfaits, le paquet {pkgname} ({version}) doit être {spec}", "app_sources_fetch_failed": "Impossible de récupérer les fichiers sources", "app_unknown": "Application inconnue", - "app_unsupported_remote_type": "Le type distant utilisé par l'application n'est pas supporté", + "app_unsupported_remote_type": "Le type distant utilisé par l’application n’est pas pris en charge", "app_upgrade_failed": "Impossible de mettre à jour {app:s}", "app_upgraded": "{app:s} a été mis à jour", "appslist_fetched": "La liste d’applications {appslist:s} a été récupérée", "appslist_removed": "La liste d’applications {appslist:s} a été supprimée", "appslist_retrieve_error": "Impossible de récupérer la liste d’applications distante {appslist:s} : {error:s}", "appslist_unknown": "La liste d’applications {appslist:s} est inconnue.", - "ask_current_admin_password": "Mot de passe d'administration actuel", + "ask_current_admin_password": "Mot de passe d’administration actuel", "ask_email": "Adresse courriel", "ask_firstname": "Prénom", "ask_lastname": "Nom", "ask_list_to_remove": "Liste à supprimer", "ask_main_domain": "Domaine principal", - "ask_new_admin_password": "Nouveau mot de passe d'administration", + "ask_new_admin_password": "Nouveau mot de passe d’administration", "ask_password": "Mot de passe", "backup_action_required": "Vous devez préciser ce qui est à sauvegarder", - "backup_app_failed": "Impossible de sauvegarder l'application « {app:s} »", - "backup_archive_app_not_found": "L'application « {app:s} » n'a pas été trouvée dans l'archive de la sauvegarde", + "backup_app_failed": "Impossible de sauvegarder l’application « {app:s} »", + "backup_archive_app_not_found": "L’application « {app:s} » n’a pas été trouvée dans l’archive de la sauvegarde", "backup_archive_hook_not_exec": "Le script « {hook:s} » n'a pas été exécuté dans cette sauvegarde", "backup_archive_name_exists": "Une archive de sauvegarde avec ce nom existe déjà", - "backup_archive_name_unknown": "L'archive locale de sauvegarde nommée « {name:s} » est inconnue", - "backup_archive_open_failed": "Impossible d'ouvrir l'archive de sauvegarde", + "backup_archive_name_unknown": "L’archive locale de sauvegarde nommée « {name:s} » est inconnue", + "backup_archive_open_failed": "Impossible d’ouvrir l’archive de sauvegarde", "backup_cleaning_failed": "Impossible de nettoyer le dossier temporaire de sauvegarde", "backup_created": "Sauvegarde terminée", - "backup_creating_archive": "Création de l'archive de sauvegarde...", + "backup_creating_archive": "Création de l’archive de sauvegarde...", "backup_creation_failed": "Impossible de créer la sauvegarde", "backup_delete_error": "Impossible de supprimer « {path:s} »", "backup_deleted": "La sauvegarde a été supprimée", - "backup_extracting_archive": "Extraction de l'archive de sauvegarde...", + "backup_extracting_archive": "Extraction de l’archive de sauvegarde...", "backup_hook_unknown": "Script de sauvegarde « {hook:s} » inconnu", "backup_invalid_archive": "Archive de sauvegarde incorrecte", - "backup_nothings_done": "Il n'y a rien à sauvegarder", + "backup_nothings_done": "Il n’y a rien à sauvegarder", "backup_output_directory_forbidden": "Dossier de destination interdit. Les sauvegardes ne peuvent être créées dans les dossiers /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var ou /home/yunohost.backup/archives", - "backup_output_directory_not_empty": "Le dossier de sortie n'est pas vide", + "backup_output_directory_not_empty": "Le dossier de sortie n’est pas vide", "backup_output_directory_required": "Vous devez spécifier un dossier de sortie pour la sauvegarde", - "backup_running_app_script": "Lancement du script de sauvegarde de l'application « {app:s} »...", + "backup_running_app_script": "Lancement du script de sauvegarde de l’application « {app:s} »...", "backup_running_hooks": "Exécution des scripts de sauvegarde...", "custom_app_url_required": "Vous devez spécifier une URL pour mettre à jour votre application locale {app:s}", - "custom_appslist_name_required": "Vous devez spécifier un nom pour votre liste d'applications personnalisée", + "custom_appslist_name_required": "Vous devez spécifier un nom pour votre liste d’applications personnalisée", "diagnosis_debian_version_error": "Impossible de déterminer la version de Debian : {error}", "diagnosis_kernel_version_error": "Impossible de récupérer la version du noyau : {error}", "diagnosis_monitor_disk_error": "Impossible de superviser les disques : {error}", @@ -82,22 +82,22 @@ "domain_dyndns_invalid": "Domaine incorrect pour un usage avec DynDNS", "domain_dyndns_root_unknown": "Domaine DynDNS principal inconnu", "domain_exists": "Le domaine existe déjà", - "domain_uninstall_app_first": "Une ou plusieurs applications sont installées sur ce domaine. Veuillez d'abord les désinstaller avant de supprimer ce domaine", + "domain_uninstall_app_first": "Une ou plusieurs applications sont installées sur ce domaine. Veuillez d’abord les désinstaller avant de supprimer ce domaine", "domain_unknown": "Domaine inconnu", "domain_zone_exists": "Le fichier de zone DNS existe déjà", "domain_zone_not_found": "Fichier de zone DNS introuvable pour le domaine {:s}", "done": "Terminé", "downloading": "Téléchargement...", "dyndns_cron_installed": "La tâche cron pour le domaine DynDNS a été installée", - "dyndns_cron_remove_failed": "Impossible d'enlever la tâche cron pour le domaine DynDNS", + "dyndns_cron_remove_failed": "Impossible d’enlever la tâche cron pour le domaine DynDNS", "dyndns_cron_removed": "La tâche cron pour le domaine DynDNS a été enlevée", - "dyndns_ip_update_failed": "Impossible de mettre à jour l'adresse IP sur le domaine DynDNS", + "dyndns_ip_update_failed": "Impossible de mettre à jour l’adresse IP sur le domaine DynDNS", "dyndns_ip_updated": "Votre adresse IP a été mise à jour pour le domaine DynDNS", "dyndns_key_generating": "La clé DNS est en cours de génération, cela peut prendre du temps...", "dyndns_key_not_found": "Clé DNS introuvable pour le domaine", - "dyndns_no_domain_registered": "Aucun domaine n'a été enregistré avec DynDNS", + "dyndns_no_domain_registered": "Aucun domaine n’a été enregistré avec DynDNS", "dyndns_registered": "Le domaine DynDNS a été enregistré", - "dyndns_registration_failed": "Impossible d'enregistrer le domaine DynDNS : {error:s}", + "dyndns_registration_failed": "Impossible d’enregistrer le domaine DynDNS : {error:s}", "dyndns_unavailable": "Le domaine {domain:s} est indisponible.", "executing_command": "Exécution de la commande « {command:s} »...", "executing_script": "Exécution du script « {script:s} »...", @@ -105,7 +105,7 @@ "field_invalid": "Champ incorrect : « {:s} »", "firewall_reload_failed": "Impossible de recharger le pare-feu", "firewall_reloaded": "Le pare-feu a été rechargé", - "firewall_rules_cmd_failed": "Certaines règles du pare-feu n'ont pas pu être appliquées. Pour plus d'informations, consultez le journal.", + "firewall_rules_cmd_failed": "Certaines règles du pare-feu n’ont pas pu être appliquées. Pour plus d’informations, consultez le journal.", "format_datetime_short": "%d/%m/%Y %H:%M", "hook_argument_missing": "Argument manquant : '{:s}'", "hook_choice_invalid": "Choix incorrect : '{:s}'", @@ -114,12 +114,12 @@ "hook_list_by_invalid": "La propriété de tri des actions est invalide", "hook_name_unknown": "Nom de script « {name:s} » inconnu", "installation_complete": "Installation terminée", - "installation_failed": "Échec de l'installation", - "ip6tables_unavailable": "Vous ne pouvez pas jouer avec ip6tables ici. Vous êtes soit dans un conteneur, soit votre noyau ne le supporte pas", - "iptables_unavailable": "Vous ne pouvez pas jouer avec iptables ici. Vous êtes soit dans un conteneur, soit votre noyau ne le supporte pas", - "ldap_initialized": "L'annuaire LDAP a été initialisé", + "installation_failed": "Échec de l’installation", + "ip6tables_unavailable": "Vous ne pouvez pas jouer avec ip6tables ici. Vous êtes soit dans un conteneur, soit votre noyau ne le prend pas en charge", + "iptables_unavailable": "Vous ne pouvez pas jouer avec iptables ici. Vous êtes soit dans un conteneur, soit votre noyau ne le prend pas en charge", + "ldap_initialized": "L’annuaire LDAP a été initialisé", "license_undefined": "indéfinie", - "mail_alias_remove_failed": "Impossible de supprimer l'alias courriel « {mail:s} »", + "mail_alias_remove_failed": "Impossible de supprimer l’alias courriel « {mail:s} »", "mail_domain_unknown": "Le domaine « {domain:s} » du courriel est inconnu", "mail_forward_remove_failed": "Impossible de supprimer le courriel de transfert « {mail:s} »", "maindomain_change_failed": "Impossible de modifier le domaine principal", @@ -127,29 +127,29 @@ "monitor_disabled": "La supervision du serveur a été désactivé", "monitor_enabled": "La supervision du serveur a été activé", "monitor_glances_con_failed": "Impossible de se connecter au serveur Glances", - "monitor_not_enabled": "Le suivi de l'état du serveur n'est pas activé", + "monitor_not_enabled": "Le suivi de l’état du serveur n’est pas activé", "monitor_period_invalid": "Période de temps incorrecte", "monitor_stats_file_not_found": "Le fichier de statistiques est introuvable", - "monitor_stats_no_update": "Aucune donnée de l'état du serveur à mettre à jour", - "monitor_stats_period_unavailable": "Aucune statistique n'est disponible pour la période", + "monitor_stats_no_update": "Aucune donnée de l’état du serveur à mettre à jour", + "monitor_stats_period_unavailable": "Aucune statistique n’est disponible pour la période", "mountpoint_unknown": "Point de montage inconnu", "mysql_db_creation_failed": "Impossible de créer la base de données MySQL", - "mysql_db_init_failed": "Impossible d'initialiser la base de données MySQL", + "mysql_db_init_failed": "Impossible d’initialiser la base de données MySQL", "mysql_db_initialized": "La base de données MySQL a été initialisée", - "network_check_mx_ko": "L'enregistrement DNS MX n'est pas précisé", + "network_check_mx_ko": "L’enregistrement DNS MX n’est pas précisé", "network_check_smtp_ko": "Le trafic courriel sortant (port 25 SMTP) semble bloqué par votre réseau", - "network_check_smtp_ok": "Le trafic courriel sortant (port 25 SMTP) n'est pas bloqué", + "network_check_smtp_ok": "Le trafic courriel sortant (port 25 SMTP) n’est pas bloqué", "new_domain_required": "Vous devez spécifier le nouveau domaine principal", "no_appslist_found": "Aucune liste d’applications n’a été trouvée", - "no_internet_connection": "Le serveur n'est pas connecté à Internet", - "no_ipv6_connectivity": "La connectivité IPv6 n'est pas disponible", - "no_restore_script": "Le script de sauvegarde n'a pas été trouvé pour l'application « {app:s} »", + "no_internet_connection": "Le serveur n’est pas connecté à Internet", + "no_ipv6_connectivity": "La connectivité IPv6 n’est pas disponible", + "no_restore_script": "Le script de sauvegarde n’a pas été trouvé pour l’application « {app:s} »", "no_such_conf_file": "Le fichier {file:s} n’existe pas, il ne peut pas être copié", - "not_enough_disk_space": "L'espace disque est insuffisant sur « {path:s} »", - "package_not_installed": "Le paquet « {pkgname} » n'est pas installé", + "not_enough_disk_space": "L’espace disque est insuffisant sur « {path:s} »", + "package_not_installed": "Le paquet « {pkgname} » n’est pas installé", "package_unexpected_error": "Une erreur inattendue est survenue avec le paquet « {pkgname} »", "package_unknown": "Paquet « {pkgname} » inconnu", - "packages_no_upgrade": "Il n'y a aucun paquet à mettre à jour", + "packages_no_upgrade": "Il n’y a aucun paquet à mettre à jour", "packages_upgrade_critical_later": "Les paquets critiques ({packages:s}) seront mis à jour ultérieurement", "packages_upgrade_failed": "Impossible de mettre à jour tous les paquets", "path_removal_failed": "Impossible de supprimer le chemin {:s}", @@ -160,7 +160,7 @@ "pattern_lastname": "Doit être un nom valide", "pattern_listname": "Doit être composé uniquement de caractères alphanumériques et de tirets bas", "pattern_mailbox_quota": "Doit être une taille avec le suffixe b/k/M/G/T ou 0 pour désactiver le quota", - "pattern_password": "Doit être composé d'au moins 3 caractères", + "pattern_password": "Doit être composé d’au moins 3 caractères", "pattern_port": "Doit être un numéro de port valide (ex. : 0-65535)", "pattern_port_or_range": "Doit être un numéro de port valide (ex. : 0-65535) ou une gamme de ports (ex. : 100:200)", "pattern_positive_number": "Doit être un nombre positif", @@ -168,24 +168,24 @@ "port_already_closed": "Le port {port:d} est déjà fermé pour les connexions {ip_version:s}", "port_already_opened": "Le port {port:d} est déjà ouvert pour les connexions {ip_version:s}", "port_available": "Le port {port:d} est disponible", - "port_unavailable": "Le port {port:d} n'est pas disponible", + "port_unavailable": "Le port {port:d} n’est pas disponible", "restore_action_required": "Vous devez préciser ce qui est à restaurer", - "restore_already_installed_app": "Une application est déjà installée avec l'id « {app:s} »", - "restore_app_failed": "Impossible de restaurer l'application « {app:s} »", + "restore_already_installed_app": "Une application est déjà installée avec l’id « {app:s} »", + "restore_app_failed": "Impossible de restaurer l’application « {app:s} »", "restore_cleaning_failed": "Impossible de nettoyer le dossier temporaire de restauration", "restore_complete": "Restauration terminée", "restore_confirm_yunohost_installed": "Voulez-vous vraiment restaurer un système déjà installé ? [{answers:s}]", "restore_failed": "Impossible de restaurer le système", - "restore_hook_unavailable": "Le script de restauration « {part:s} » n'est pas disponible sur votre système, et n’est pas non plus dans l’archive", - "restore_nothings_done": "Rien n'a été restauré", - "restore_running_app_script": "Lancement du script de restauration pour l'application « {app:s} »...", + "restore_hook_unavailable": "Le script de restauration « {part:s} » n’est pas disponible sur votre système, et n’est pas non plus dans l’archive", + "restore_nothings_done": "Rien n’a été restauré", + "restore_running_app_script": "Lancement du script de restauration pour l’application « {app:s} »...", "restore_running_hooks": "Exécution des scripts de restauration...", "service_add_configuration": "Ajout du fichier de configuration {file:s}", - "service_add_failed": "Impossible d'ajouter le service « {service:s} »", + "service_add_failed": "Impossible d’ajouter le service « {service:s} »", "service_added": "Le service « {service:s} » a été ajouté", "service_already_started": "Le service « {service:s} » est déjà démarré", "service_already_stopped": "Le service « {service:s} » est déjà arrêté", - "service_cmd_exec_failed": "Impossible d'exécuter la commande « {command:s} »", + "service_cmd_exec_failed": "Impossible d’exécuter la commande « {command:s} »", "service_conf_file_backed_up": "Le fichier de configuration « {conf} » a été sauvegardé dans « {backup} »", "service_conf_file_copy_failed": "Impossible de copier le nouveau fichier de configuration « {new} » vers « {conf} »", "service_conf_file_manually_modified": "Le fichier de configuration « {conf} » a été modifié manuellement et ne sera pas mis à jour", @@ -208,7 +208,7 @@ "service_regenconf_dry_pending_applying": "Vérification des configurations en attentes qui pourraient être appliquées pour le service « {service} »…", "service_regenconf_failed": "Impossible de régénérer la configuration pour les services : {services}", "service_regenconf_pending_applying": "Application des configurations en attentes pour le service « {service} »…", - "service_remove_failed": "Impossible d'enlever le service « {service:s} »", + "service_remove_failed": "Impossible d’enlever le service « {service:s} »", "service_removed": "Le service « {service:s} » a été enlevé", "service_start_failed": "Impossible de démarrer le service « {service:s} »\n\nJournaux récents : {logs:s}", "service_started": "Le service « {service:s} » a été démarré", @@ -221,38 +221,38 @@ "ssowat_conf_generated": "La configuration de SSOwat a été générée", "ssowat_conf_updated": "La configuration de SSOwat a été mise à jour", "system_upgraded": "Le système a été mis à jour", - "system_username_exists": "Le nom d'utilisateur existe déjà dans les utilisateurs système", - "unbackup_app": "L'application « {app:s} » ne sera pas sauvegardée", + "system_username_exists": "Le nom d’utilisateur existe déjà dans les utilisateurs système", + "unbackup_app": "L’application « {app:s} » ne sera pas sauvegardée", "unexpected_error": "Une erreur inattendue est survenue", "unit_unknown": "Unité « {unit:s} » inconnue", "unlimit": "Pas de quota", - "unrestore_app": "L'application « {app:s} » ne sera pas restaurée", - "update_cache_failed": "Impossible de mettre à jour le cache de l'APT", + "unrestore_app": "L’application « {app:s} » ne sera pas restaurée", + "update_cache_failed": "Impossible de mettre à jour le cache de l’APT", "updating_apt_cache": "Mise à jour de la liste des paquets disponibles...", "upgrade_complete": "Mise à jour terminée", "upgrading_packages": "Mise à jour des paquets...", - "upnp_dev_not_found": "Aucun périphérique compatible UPnP n'a été trouvé", + "upnp_dev_not_found": "Aucun périphérique compatible UPnP n’a été trouvé", "upnp_disabled": "UPnP a été désactivé", "upnp_enabled": "UPnP a été activé", - "upnp_port_open_failed": "Impossible d'ouvrir les ports avec UPnP", - "user_created": "L'utilisateur a été créé", - "user_creation_failed": "Impossible de créer l'utilisateur", - "user_deleted": "L'utilisateur a été supprimé", - "user_deletion_failed": "Impossible de supprimer l'utilisateur", - "user_home_creation_failed": "Impossible de créer le dossier personnel de l'utilisateur", - "user_info_failed": "Impossible de récupérer les informations de l'utilisateur", + "upnp_port_open_failed": "Impossible d’ouvrir les ports avec UPnP", + "user_created": "L’utilisateur a été créé", + "user_creation_failed": "Impossible de créer l’utilisateur", + "user_deleted": "L’utilisateur a été supprimé", + "user_deletion_failed": "Impossible de supprimer l’utilisateur", + "user_home_creation_failed": "Impossible de créer le dossier personnel de l’utilisateur", + "user_info_failed": "Impossible de récupérer les informations de l’utilisateur", "user_unknown": "Utilisateur « {user:s} » inconnu", - "user_update_failed": "Impossible de modifier l'utilisateur", - "user_updated": "L'utilisateur a été modifié", + "user_update_failed": "Impossible de modifier l’utilisateur", + "user_updated": "L’utilisateur a été modifié", "yunohost_already_installed": "YunoHost est déjà installé", - "yunohost_ca_creation_failed": "Impossible de créer l'autorité de certification", + "yunohost_ca_creation_failed": "Impossible de créer l’autorité de certification", "yunohost_configured": "YunoHost a été configuré", "yunohost_installing": "Installation de YunoHost...", - "yunohost_not_installed": "YunoHost n'est pas ou pas correctement installé. Veuillez exécuter « yunohost tools postinstall »", + "yunohost_not_installed": "YunoHost n’est pas ou pas correctement installé. Veuillez exécuter « yunohost tools postinstall »", "certmanager_attempt_to_replace_valid_cert": "Vous êtes en train de remplacer un certificat correct et valide pour le domaine {domain:s} ! (Utilisez --force pour contourner)", "certmanager_domain_unknown": "Domaine inconnu {domain:s}", "certmanager_domain_cert_not_selfsigned": "Le certificat du domaine {domain:s} n’est pas auto-signé. Voulez-vous vraiment le remplacer ? (Utilisez --force)", - "certmanager_certificate_fetching_or_enabling_failed": "Il semble que l'activation du nouveau certificat pour {domain:s} a échoué…", + "certmanager_certificate_fetching_or_enabling_failed": "Il semble que l’activation du nouveau certificat pour {domain:s} a échoué…", "certmanager_attempt_to_renew_nonLE_cert": "Le certificat pour le domaine {domain:s} n’est pas fourni par Let’s Encrypt. Impossible de le renouveler automatiquement !", "certmanager_attempt_to_renew_valid_cert": "Le certificat pour le domaine {domain:s} est sur le point d’expirer ! Utilisez --force pour contourner", "certmanager_domain_http_not_working": "Il semble que le domaine {domain:s} n’est pas accessible via HTTP. Veuillez vérifier que vos configuration DNS et nginx sont correctes", @@ -273,15 +273,15 @@ "domain_cannot_remove_main": "Impossible de retirer le domaine principal. Définissez un nouveau domaine principal au préalable.", "certmanager_self_ca_conf_file_not_found": "Le fichier de configuration pour l’autorité du certificat auto-signé est introuvable (fichier : {file:s})", "certmanager_unable_to_parse_self_CA_name": "Impossible d’analyser le nom de l’autorité du certificat auto-signé (fichier : {file:s})", - "mailbox_used_space_dovecot_down": "Le service de mail Dovecot doit être démarré, si vous souhaitez voir l'espace disque occupé par la messagerie", + "mailbox_used_space_dovecot_down": "Le service de mail Dovecot doit être démarré, si vous souhaitez voir l’espace disque occupé par la messagerie", "domains_available": "Domaines disponibles :", - "backup_archive_broken_link": "Impossible d'accéder à l'archive de sauvegarde (lien invalide vers {path:s})", + "backup_archive_broken_link": "Impossible d’accéder à l’archive de sauvegarde (lien invalide vers {path:s})", "certmanager_acme_not_configured_for_domain": "Le certificat du domaine {domain:s} ne semble pas être correctement installé. Veuillez préalablement exécuter cert-install pour ce domaine.", "certmanager_domain_not_resolved_locally": "Le domaine {domain:s} ne peut être déterminé depuis votre serveur YunoHost. Cela peut arriver si vous avez récemment modifié votre enregistrement DNS. Auquel cas, merci d’attendre quelques heures qu’il se propage. Si le problème persiste, envisager d’ajouter {domain:s} au fichier /etc/hosts. (Si vous savez ce que vous faites, utilisez --no-checks pour désactiver ces vérifications.)", "certmanager_http_check_timeout": "Expiration du délai lors de la tentative du serveur de se contacter via HTTP en utilisant son adresse IP publique (domaine {domain:s} avec l’IP {ip:s}). Vous rencontrez peut-être un problème d’hairpinning ou alors le pare-feu/routeur en amont de votre serveur est mal configuré.", "certmanager_couldnt_fetch_intermediate_cert": "Expiration du délai lors de la tentative de récupération du certificat intermédiaire depuis Let’s Encrypt. L’installation/le renouvellement du certificat a été interrompu - veuillez réessayer prochainement.", "appslist_retrieve_bad_format": "Le fichier récupéré pour la liste d’applications {appslist:s} n’est pas valide", - "domain_hostname_failed": "Échec de la création d'un nouveau nom d'hôte", + "domain_hostname_failed": "Échec de la création d’un nouveau nom d’hôte", "yunohost_ca_creation_success": "L’autorité de certification locale a été créée.", "appslist_name_already_tracked": "Il y a déjà une liste d’applications enregistrée avec le nom {name:s}.", "appslist_url_already_tracked": "Il y a déjà une liste d’applications enregistrée avec l’URL {url:s}.", @@ -368,8 +368,8 @@ "ask_path": "Chemin", "dyndns_could_not_check_provide": "Impossible de vérifier si {provider:s} peut fournir {domain:s}.", "dyndns_domain_not_provided": "Le fournisseur Dyndns {provider:s} ne peut pas fournir le domaine {domain:s}.", - "app_make_default_location_already_used": "Impossible de configurer l'app '{app}' par défaut pour le domaine {domain}, déjà utilisé par l'autre app '{other_app}'", - "app_upgrade_app_name": "Mise à jour de l'application {app}...", + "app_make_default_location_already_used": "Impossible de configurer l’app « {app} » par défaut pour le domaine {domain}, déjà utilisé par l’autre app « {other_app} »", + "app_upgrade_app_name": "Mise à jour de l’application {app}...", "backup_output_symlink_dir_broken": "Vous avez un lien symbolique cassé à la place de votre dossier d’archives « {path:s} ». Vous pourriez avoir une configuration personnalisée pour sauvegarder vos données sur un autre système de fichiers, dans ce cas, vous avez probablement oublié de monter ou de connecter votre disque / clef USB.", "migrate_tsig_end": "La migration à hmac-sha512 est terminée", "migrate_tsig_failed": "La migration du domaine dyndns {domain} à hmac-sha512 a échoué, annulation des modifications. Erreur : {error_code} - {error}", @@ -393,7 +393,7 @@ "migration_0003_not_jessie": "La distribution Debian actuelle n’est pas Jessie !", "migration_0003_system_not_fully_up_to_date": "Votre système n’est pas complètement à jour. Veuillez mener une mise à jour classique avant de lancer à migration à Stretch.", "migration_0003_still_on_jessie_after_main_upgrade": "Quelque chose s’est ma passé pendant la mise à niveau principale : le système est toujours sur Jessie ?!? Pour investiguer le problème, veuillez regarder {log} 🙁…", - "migration_0003_general_warning": "Veuillez noter que cette migration est une opération délicate. Si l’équipe YunoHost a fait de son mieux pour la relire et la tester, la migration pourrait tout de même casser des parties de votre système ou de vos applications.\n\nEn conséquence, nous vous recommandons :\n - de lancer une sauvegarde de vos données ou applications critiques. Plus d’informations sur https://yunohost.org/backup ;\n - d’être patient après avoir lancé la migration : selon votre connexion internet et matériel, cela pourrait prendre jusqu'à quelques heures pour que tout soit à niveau.\n\nDe plus, le port SMTP utilisé par les clients de messagerie externes comme (Thunderbird ou K9-Mail) a été changé de 465 (SSL/TLS) à 587 (STARTTLS). L’ancien port 465 sera automatiquement fermé et le nouveau port 587 sera ouvert dans le pare-feu. Vous et vos utilisateurs *devront* adapter la configuration de vos clients de messagerie en conséquence !", + "migration_0003_general_warning": "Veuillez noter que cette migration est une opération délicate. Si l’équipe YunoHost a fait de son mieux pour la relire et la tester, la migration pourrait tout de même casser des parties de votre système ou de vos applications.\n\nEn conséquence, nous vous recommandons :\n - de lancer une sauvegarde de vos données ou applications critiques. Plus d’informations sur https://yunohost.org/backup ;\n - d’être patient après avoir lancé la migration : selon votre connexion internet et matériel, cela pourrait prendre jusqu’à quelques heures pour que tout soit à niveau.\n\nDe plus, le port SMTP utilisé par les clients de messagerie externes comme (Thunderbird ou K9-Mail) a été changé de 465 (SSL/TLS) à 587 (STARTTLS). L’ancien port 465 sera automatiquement fermé et le nouveau port 587 sera ouvert dans le pare-feu. Vous et vos utilisateurs *devront* adapter la configuration de vos clients de messagerie en conséquence !", "migration_0003_problematic_apps_warning": "Veuillez noter que les applications suivantes, éventuellement problématiques, ont été détectées. Il semble qu’elles n’aient pas été installées depuis une liste d’application ou qu’elles ne soit pas marquées «working ». En conséquence, nous ne pouvons pas garantir qu’elles fonctionneront après la mise à niveau : {problematic_apps}", "migration_0003_modified_files": "Veuillez noter que les fichiers suivants ont été détectés comme modifiés manuellement et pourraient être écrasés à la fin de la mise à niveau : {manually_modified_files}", "migrations_list_conflict_pending_done": "Vous ne pouvez pas utiliser --previous et --done simultanément.", @@ -417,44 +417,44 @@ "service_description_ssh": "vous permet de vous connecter à distance à votre serveur via un terminal (protocole SSH)", "service_description_yunohost-api": "permet les interactions entre l’interface web de YunoHost et le système", "service_description_yunohost-firewall": "gère les ports de connexion ouverts et fermés aux services", - "experimental_feature": "Attention : cette fonctionnalité est expérimentale et ne doit pas être considérée comme stable, vous ne devriez pas l'utiliser à moins que vous ne sachiez ce que vous faîtes.", - "log_corrupted_md_file": "Le fichier yaml de metadata associé aux logs est corrompu : '{md_file}'", - "log_category_404": "La catégorie de log '{category}' n'existe pas", - "log_link_to_log": "Log complet de cette opération : ' {desc} '", - "log_help_to_get_log": "Pour voir le log de cette opération '{desc}', utiliser la commande 'yunohost log display {name}'", - "log_link_to_failed_log": "L'opération '{desc}' a échouée ! Pour avoir de l'aide, merci de fournir le log complet de l'opération", + "experimental_feature": "Attention : cette fonctionnalité est expérimentale et ne doit pas être considérée comme stable, vous ne devriez pas l’utiliser à moins que vous ne sachiez ce que vous faîtes.", + "log_corrupted_md_file": "Le fichier yaml de metadata associé aux logs est corrompu : {md_file}", + "log_category_404": "La catégorie de log « {category} » n’existe pas", + "log_link_to_log": "Log complet de cette opération : « {desc} »", + "log_help_to_get_log": "Pour voir le log de cette opération « {desc} », utiliser la commande « yunohost log display {name} »", + "log_link_to_failed_log": "L’opération « {desc} » a échouée ! Pour avoir de l’aide, merci de fournir le log complet de l’opération", "backup_php5_to_php7_migration_may_fail": "Impossible de convertir votre archive pour prendre en charge php7, la restauration de vos applications php peut ne pas aboutir (reason: {error:s})", - "log_help_to_get_failed_log": "L'opération '{desc}' a échouée ! Pour avoir de l'aide, merci de partager le log de cette opération en utilisant la commande 'yunohost log display {name} --share'", - "log_does_exists": "Il n'existe pas de log de l'opération ayant pour nom '{log}', utiliser 'yunohost log list pour voir tous les fichiers de logs disponibles'", - "log_operation_unit_unclosed_properly": "L'opération ne s'est pas terminée correctement", - "log_app_addaccess": "Ajouter l'accès à '{}'", - "log_app_removeaccess": "Enlever l'accès à '{}'", - "log_app_clearaccess": "Retirer tous les accès à '{}'", - "log_app_fetchlist": "Ajouter une liste d'application", - "log_app_removelist": "Enlever une liste d'application", - "log_app_change_url": "Changer l'url de l'application '{}'", - "log_app_install": "Installer l'application '{}'", - "log_app_remove": "Enlever l'application '{}'", - "log_app_upgrade": "Mettre à jour l'application '{}'", - "log_app_makedefault": "Faire de '{}' l'application par défaut", + "log_help_to_get_failed_log": "L’opération « {desc} » a échouée ! Pour avoir de l’aide, merci de partager le log de cette opération en utilisant la commande « yunohost log display {name} --share »", + "log_does_exists": "Il n’existe pas de log de l’opération ayant pour nom « {log} », utiliser « yunohost log list pour voir tous les fichiers de logs disponibles »", + "log_operation_unit_unclosed_properly": "L’opération ne s’est pas terminée correctement", + "log_app_addaccess": "Ajouter l’accès à « {} »", + "log_app_removeaccess": "Enlever l’accès à « {} »", + "log_app_clearaccess": "Retirer tous les accès à « {} »", + "log_app_fetchlist": "Ajouter une liste d’application", + "log_app_removelist": "Enlever une liste d’application", + "log_app_change_url": "Changer l’url de l’application « {} »", + "log_app_install": "Installer l’application « {} »", + "log_app_remove": "Enlever l’application « {} »", + "log_app_upgrade": "Mettre à jour l’application « {} »", + "log_app_makedefault": "Faire de « {} » l’application par défaut", "log_available_on_yunopaste": "Le log est désormais disponible via {url}", "log_backup_restore_system": "Restaurer le système depuis une sauvegarde", - "log_backup_restore_app": "Restaurer '{}' depuis une sauvegarde", - "log_remove_on_failed_restore": "Retirer '{}' après la restauration depuis une sauvegarde qui a échouée", - "log_remove_on_failed_install": "Enlever '{}' après une installation échouée", - "log_domain_add": "Ajouter le domaine '{}' dans la configuration du système", - "log_domain_remove": "Enlever le domaine '{}' de la configuration du système", - "log_dyndns_subscribe": "Souscrire au sous-domaine '{}' de Yunohost", - "log_dyndns_update": "Mettre à jour l'adresse ip associée à votre sous-domaine Yunohost '{}'", - "log_letsencrypt_cert_install": "Installer le certificat Let's encryt sur le domaine '{}'", - "log_selfsigned_cert_install": "Installer le certificat auto-signé sur le domaine '{}'", - "log_letsencrypt_cert_renew": "Renouveler le certificat Let's encrypt de '{}'", - "log_service_enable": "Activer le service '{}'", - "log_service_regen_conf": "Régénérer la configuration système de '{}'", - "log_user_create": "Ajouter l'utilisateur '{}'", - "log_user_delete": "Enlever l'utilisateur '{}'", - "log_user_update": "Mettre à jour les informations de l'utilisateur '{}'", - "log_tools_maindomain": "Faire de '{} 1' le domaine principal", + "log_backup_restore_app": "Restaurer « {} » depuis une sauvegarde", + "log_remove_on_failed_restore": "Retirer « {} » après la restauration depuis une sauvegarde qui a échouée", + "log_remove_on_failed_install": "Enlever « {} » après une installation échouée", + "log_domain_add": "Ajouter le domaine « {} » dans la configuration du système", + "log_domain_remove": "Enlever le domaine « {} » de la configuration du système", + "log_dyndns_subscribe": "Souscrire au sous-domaine « {} » de Yunohost", + "log_dyndns_update": "Mettre à jour l’adresse ip associée à votre sous-domaine Yunohost « {} »", + "log_letsencrypt_cert_install": "Installer le certificat Let’s encryt sur le domaine « {} »", + "log_selfsigned_cert_install": "Installer le certificat auto-signé sur le domaine « {} »", + "log_letsencrypt_cert_renew": "Renouveler le certificat Let’s encrypt de « {} »", + "log_service_enable": "Activer le service « {} »", + "log_service_regen_conf": "Régénérer la configuration système de « {} »", + "log_user_create": "Ajouter l’utilisateur « {} »", + "log_user_delete": "Enlever l’utilisateur « {} »", + "log_user_update": "Mettre à jour les informations de l’utilisateur « {} »", + "log_tools_maindomain": "Faire de « {} » le domaine principal", "log_tools_migrations_migrate_forward": "Migrer", "log_tools_migrations_migrate_backward": "Revenir en arrière", "log_tools_postinstall": "Faire la post-installation du serveur Yunohost", @@ -464,16 +464,16 @@ "mail_unavailable": "Cette adresse mail est réservée et doit être automatiquement attribuée au tout premier utilisateur", "migration_description_0004_php5_to_php7_pools": "Reconfigurez le pool PHP pour utiliser PHP 7 au lieu de 5", "migration_description_0005_postgresql_9p4_to_9p6": "Migration des bases de données de postgresql 9.4 vers 9.6", - "migration_0005_postgresql_94_not_installed": "Postgresql n'a pas été installé sur votre système. Rien à faire !", + "migration_0005_postgresql_94_not_installed": "Postgresql n’a pas été installé sur votre système. Rien à faire !", "migration_0005_postgresql_96_not_installed": "Postgresql 9.4 a été trouvé et installé, mais pas Postgresql 9.6 !? Quelque chose d’étrange a dû arriver à votre système :( …", "migration_0005_not_enough_space": "Il n’y a pas assez d’espace libre de disponible sur {path} pour lancer maintenant la migration :(.", - "recommend_to_add_first_user": "La post-installation est terminée, mais YunoHost a besoin d'au moins un utilisateur pour fonctionner correctement. Vous devez en ajouter un en utilisant 'yunohost user create' ou l'interface d'administration.", + "recommend_to_add_first_user": "La post-installation est terminée, mais YunoHost a besoin d’au moins un utilisateur pour fonctionner correctement. Vous devez en ajouter un en utilisant « yunohost user create » ou l’interface d’administration.", "service_description_php7.0-fpm": "exécute des applications écrites en PHP avec nginx", "users_available": "Liste des utilisateurs disponibles :", "good_practices_about_admin_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe d’administration. Le mot de passe doit comporter au moins 8 caractères – bien qu’il soit recommandé d’utiliser un mot de passe plus long (c’est-à-dire une phrase de chiffrement) et/ou d’utiliser différents types de caractères (majuscules, minuscules, chiffres et caractères spéciaux).", "good_practices_about_user_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe utilisateur. Le mot de passe doit comporter au moins 8 caractères – bien qu’il soit recommandé d’utiliser un mot de passe plus long (c’est-à-dire une phrase de chiffrement) et/ou d’utiliser différents types de caractères (majuscules, minuscules, chiffres et caractères spéciaux).", "migration_description_0006_sync_admin_and_root_passwords": "Synchroniser les mots de passe admin et root", - "migration_0006_disclaimer": "Yunohost s'attend maintenant à ce que les mots de passe admin et root soient synchronisés. En exécutant cette migration, votre mot de passe root sera remplacé par le mot de passe administrateur.", + "migration_0006_disclaimer": "Yunohost s’attend maintenant à ce que les mots de passe admin et root soient synchronisés. En exécutant cette migration, votre mot de passe root sera remplacé par le mot de passe administrateur.", "migration_0006_done": "Votre mot de passe root a été remplacé par celui de votre adminitrateur.", "password_listed": "Ce mot de passe est l’un des mots de passe les plus utilisés dans le monde. Veuillez choisir quelque chose d’un peu plus unique.", "password_too_simple_1": "Le mot de passe doit comporter au moins 8 caractères", From 5126b3e450b3e4eb5208653e8b6e15649b76aeb2 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 23 Nov 2018 14:58:44 +0000 Subject: [PATCH 15/49] Update changelog for 3.3.1 --- debian/changelog | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/debian/changelog b/debian/changelog index 83e9e9269..ca4d8d928 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,17 @@ +yunohost (3.3.1) stable; urgency=low + + * [fix] Wait for dpkg lock to be free in apt helpers (#571) + * [fix] app_removeaccess call set.add (#573) + * [fix] Fix app_addaccess behaviour when 'allowed_users' is initially empty (#575) + * [fix] Typo in user_update when update password (#577) + * [fix] Do not fail on missing fail2ban config during the backup (#558) + * [fix] Generate a random serial for local certification auth (followup of #557) + * [i18n] Update Italian, Occitan, French translations + + Thanks to all contributors (Maniack, airwoodix, Aleks, ljf, silkevicious, Quent-in, Jibec) <3 ! + + -- Alexandre Aubin Fri, 23 Nov 2018 15:58:00 +0000 + yunohost (3.3.0) testing; urgency=low Highlights From a455cae3bf213067f875fa00f55a4244a48f92d2 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 26 Nov 2018 14:56:47 +0000 Subject: [PATCH 16/49] Typo + fixes for helper doc generation --- data/helpers.d/print | 2 +- doc/generate_helper_doc.py | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/data/helpers.d/print b/data/helpers.d/print index 93d402e64..2f451bc24 100644 --- a/data/helpers.d/print +++ b/data/helpers.d/print @@ -7,7 +7,7 @@ ynh_die() { # Display a message in the 'INFO' logging category # -# usage: ynh_info "Some message" +# usage: ynh_print_info "Some message" ynh_print_info() { echo "$1" >> "$YNH_STDINFO" } diff --git a/doc/generate_helper_doc.py b/doc/generate_helper_doc.py index 20022e253..7d8c489b7 100644 --- a/doc/generate_helper_doc.py +++ b/doc/generate_helper_doc.py @@ -11,7 +11,7 @@ def render(data): from ansi2html.style import get_styles conv = Ansi2HTMLConverter() - shell_css = "\n".join(map(str, get_styles(conv.dark_bg, conv.scheme))) + shell_css = "\n".join(map(str, get_styles(conv.dark_bg))) def shell_to_html(shell): return conv.convert(shell, False) @@ -28,6 +28,7 @@ class Parser(): def __init__(self, filename): + self.filename = filename self.file = open(filename, "r").readlines() self.blocks = None @@ -42,6 +43,9 @@ class Parser(): "code": [] } for i, line in enumerate(self.file): + + if line.startswith("#!/bin/bash"): + continue line = line.rstrip().replace("\t", " ") @@ -64,7 +68,7 @@ class Parser(): else: # We're getting out of a comment bloc, we should find # the name of the function - assert len(line.split()) >= 1 + assert len(line.split()) >= 1, "Malformed line %s in %s" % (i, self.filename) current_block["line"] = i current_block["name"] = line.split()[0].strip("(){") # Then we expect to read the function @@ -143,11 +147,11 @@ class Parser(): b["usage"] = b["usage"].strip() + def is_global_comment(line): return line.startswith('#') def malformed_error(line_number): - import pdb; pdb.set_trace() return "Malformed file line {} ?".format(line_number) def main(): From 76121ea0847f2ce3be0db4605bbef67360d28862 Mon Sep 17 00:00:00 2001 From: liberodark Date: Tue, 27 Nov 2018 18:27:01 +0100 Subject: [PATCH 17/49] HTTP2 On (#580) * HTTP2 On for better security * Remove old lines --- data/templates/nginx/server.tpl.conf | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/data/templates/nginx/server.tpl.conf b/data/templates/nginx/server.tpl.conf index 9acc641ae..db42a8e65 100644 --- a/data/templates/nginx/server.tpl.conf +++ b/data/templates/nginx/server.tpl.conf @@ -20,11 +20,8 @@ server { } server { - # Disabling http2 for now as it's causing weird issues with curl - #listen 443 ssl http2; - #listen [::]:443 ssl http2; - listen 443 ssl; - listen [::]:443 ssl; + listen 443 ssl http2; + listen [::]:443 ssl http2; server_name {{ domain }}; ssl_certificate /etc/yunohost/certs/{{ domain }}/crt.pem; From 190669228936aafa538bd80fe91229d595e30724 Mon Sep 17 00:00:00 2001 From: liberodark Date: Tue, 27 Nov 2018 18:30:39 +0100 Subject: [PATCH 18/49] Remove ECDH curve or change it ? (#579) Update ECDH curves recommended by Mozilla, now that we are on stretch --- data/templates/nginx/server.tpl.conf | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/data/templates/nginx/server.tpl.conf b/data/templates/nginx/server.tpl.conf index db42a8e65..464639952 100644 --- a/data/templates/nginx/server.tpl.conf +++ b/data/templates/nginx/server.tpl.conf @@ -30,12 +30,7 @@ server { ssl_session_cache shared:SSL:50m; # As suggested by Mozilla : https://wiki.mozilla.org/Security/Server_Side_TLS and https://en.wikipedia.org/wiki/Curve25519 - # (this doesn't work on jessie though ...?) - # ssl_ecdh_curve secp521r1:secp384r1:prime256v1; - - # As suggested by https://cipherli.st/ - ssl_ecdh_curve secp384r1; - + ssl_ecdh_curve secp521r1:secp384r1:prime256v1; ssl_prefer_server_ciphers on; # Ciphers with intermediate compatibility From 8cb029a55e471e1ece3a8a2d7bba00975a6f2d17 Mon Sep 17 00:00:00 2001 From: frju365 Date: Wed, 28 Nov 2018 01:21:28 +0100 Subject: [PATCH 19/49] Better Configuration of nginx (#564) * path-traversal * [fix] try a patch for path-traversal * Use more_set_headers insta --- data/templates/nginx/server.tpl.conf | 18 +++++++++--------- src/yunohost/certificate.py | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/data/templates/nginx/server.tpl.conf b/data/templates/nginx/server.tpl.conf index 464639952..ee20c29c9 100644 --- a/data/templates/nginx/server.tpl.conf +++ b/data/templates/nginx/server.tpl.conf @@ -11,7 +11,7 @@ server { return 301 https://$http_host$request_uri; } - location /.well-known/autoconfig/mail { + location /.well-known/autoconfig/mail/ { alias /var/www/.well-known/{{ domain }}/autoconfig/mail; } @@ -51,14 +51,14 @@ server { # Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners # https://wiki.mozilla.org/Security/Guidelines/Web_Security # https://observatory.mozilla.org/ - add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; - add_header Content-Security-Policy "upgrade-insecure-requests"; - add_header Content-Security-Policy-Report-Only "default-src https: data: 'unsafe-inline' 'unsafe-eval'"; - add_header X-Content-Type-Options nosniff; - add_header X-XSS-Protection "1; mode=block"; - add_header X-Download-Options noopen; - add_header X-Permitted-Cross-Domain-Policies none; - add_header X-Frame-Options "SAMEORIGIN"; + more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload"; + more_set_headers "Content-Security-Policy : upgrade-insecure-requests"; + more_set_headers "Content-Security-Policy-Report-Only : default-src https: data: 'unsafe-inline' 'unsafe-eval'"; + more_set_headers "X-Content-Type-Options : nosniff"; + more_set_headers "X-XSS-Protection : 1; mode=block"; + more_set_headers "X-Download-Options : noopen"; + more_set_headers "X-Permitted-Cross-Domain-Policies : none"; + more_set_headers "X-Frame-Options : SAMEORIGIN"; {% if domain_cert_ca == "Let's Encrypt" %} # OCSP settings diff --git a/src/yunohost/certificate.py b/src/yunohost/certificate.py index 049eeb0f4..801741b31 100644 --- a/src/yunohost/certificate.py +++ b/src/yunohost/certificate.py @@ -466,7 +466,7 @@ def _configure_for_acme_challenge(auth, domain): nginx_conf_file = "%s/000-acmechallenge.conf" % nginx_conf_folder nginx_configuration = ''' -location ^~ '/.well-known/acme-challenge' +location ^~ '/.well-known/acme-challenge/' { default_type "text/plain"; alias %s; From 546102547964697768bb6b77e31c2aae78fc6c61 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 28 Nov 2018 16:16:24 +0100 Subject: [PATCH 20/49] tools_adminpw was still checking the password strength despite --force-password --- src/yunohost/tools.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index 271947b3d..baa614fa5 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -118,7 +118,7 @@ def tools_ldapinit(): return auth -def tools_adminpw(auth, new_password): +def tools_adminpw(auth, new_password, check_strength=True): """ Change admin password @@ -130,7 +130,8 @@ def tools_adminpw(auth, new_password): from yunohost.utils.password import assert_password_is_strong_enough import spwd - assert_password_is_strong_enough("admin", new_password) + if check_strength: + assert_password_is_strong_enough("admin", new_password) new_hash = _hash_user_password(new_password) @@ -416,7 +417,7 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False, tools_maindomain(auth, domain) # Change LDAP admin password - tools_adminpw(auth, password) + tools_adminpw(auth, password, check_strength=not force_password) # Enable UPnP silently and reload firewall firewall_upnp('enable', no_refresh=True) From 69d0503ba56ec509a62d839f5d97c03ada67464b Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 28 Nov 2018 22:01:27 +0000 Subject: [PATCH 21/49] Forgot to get the 'value' key here.. --- src/yunohost/utils/password.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/utils/password.py b/src/yunohost/utils/password.py index 68e51056b..6e8f5ba0a 100644 --- a/src/yunohost/utils/password.py +++ b/src/yunohost/utils/password.py @@ -60,7 +60,7 @@ class PasswordValidator(object): # (or at least that's my understanding -- Alex) settings = json.load(open('/etc/yunohost/settings.json', "r")) setting_key = "security.password." + profile + ".strength" - self.validation_strength = int(settings[setting_key]) + self.validation_strength = int(settings[setting_key]["value"]) except Exception as e: # Fallback to default value if we can't fetch settings for some reason self.validation_strength = 1 From e918836ab09ef72fca590a5a24279f82779e7c25 Mon Sep 17 00:00:00 2001 From: Maniack Crudelis Date: Sat, 1 Dec 2018 16:21:31 +0100 Subject: [PATCH 22/49] Fix multiple value for getopts (#592) --- data/helpers.d/getopts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/helpers.d/getopts b/data/helpers.d/getopts index 1cc66da8a..6d600e207 100644 --- a/data/helpers.d/getopts +++ b/data/helpers.d/getopts @@ -129,6 +129,8 @@ ynh_handle_getopts_args () { shift_value=$(( shift_value - 1 )) fi + # Declare the content of option_var as a variable. + eval ${option_var}="" # Then read the array value per value for i in `seq 0 $(( ${#all_args[@]} - 1 ))` do @@ -140,8 +142,6 @@ ynh_handle_getopts_args () { break fi else - # Declare the content of option_var as a variable. - eval ${option_var}="" # Else, add this value to this option # Each value will be separated by ';' if [ -n "${!option_var}" ] From c9fec565b5455cf428f5e6eafc66331702bd0d07 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 1 Dec 2018 16:21:59 +0100 Subject: [PATCH 23/49] Log dyndns update only if we really update something (#591) --- src/yunohost/dyndns.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/yunohost/dyndns.py b/src/yunohost/dyndns.py index 3e040d682..dd652119f 100644 --- a/src/yunohost/dyndns.py +++ b/src/yunohost/dyndns.py @@ -206,9 +206,6 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None, key = keys[0] - operation_logger.related_to.append(('domain', domain)) - operation_logger.start() - # This mean that hmac-md5 is used # (Re?)Trigger the migration to sha256 and return immediately. # The actual update will be done in next run. @@ -258,6 +255,8 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None, logger.info("No updated needed.") return else: + operation_logger.related_to.append(('domain', domain)) + operation_logger.start() logger.info("Updated needed, going on...") dns_conf = _build_dns_conf(domain) From 09fcea1177213fd3a415392afbb1d7101736057f Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 1 Dec 2018 16:22:40 +0100 Subject: [PATCH 24/49] Add libpam-ldapd as dependency to be able to login through SSH with LDAP identities ? (#587) --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 1f4995195..9f72bf11a 100644 --- a/debian/control +++ b/debian/control @@ -17,7 +17,7 @@ Depends: ${python:Depends}, ${misc:Depends} , dnsutils, bind9utils, unzip, git, curl, cron, wget, jq , ca-certificates, netcat-openbsd, iproute , mariadb-server, php-mysql | php-mysqlnd - , slapd, ldap-utils, sudo-ldap, libnss-ldapd, unscd + , slapd, ldap-utils, sudo-ldap, libnss-ldapd, unscd, libpam-ldapd , postfix-ldap, postfix-policyd-spf-perl, postfix-pcre, procmail, mailutils, postsrsd , dovecot-ldap, dovecot-lmtpd, dovecot-managesieved , dovecot-antispam, fail2ban From 41c1a9ce13634cff7c2c81540cbee1c2fed1cb10 Mon Sep 17 00:00:00 2001 From: Maniack Crudelis Date: Sat, 1 Dec 2018 23:07:32 +0100 Subject: [PATCH 25/49] Do not use a separate ini file for php pools (#548) Have a look to https://github.com/YunoHost-Apps/nextcloud_ynh/issues/138 for more information. --- data/helpers.d/backend | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/data/helpers.d/backend b/data/helpers.d/backend index b36235b42..26e53ede9 100644 --- a/data/helpers.d/backend +++ b/data/helpers.d/backend @@ -222,11 +222,7 @@ ynh_add_fpm_config () { if [ -e "../conf/php-fpm.ini" ] then - finalphpini="$fpm_config_dir/conf.d/20-$app.ini" - ynh_backup_if_checksum_is_different "$finalphpini" - sudo cp ../conf/php-fpm.ini "$finalphpini" - sudo chown root: "$finalphpini" - ynh_store_file_checksum "$finalphpini" + echo "Please do not use a separate ini file, merge you directives in the pool file instead." &>2 fi sudo systemctl reload $fpm_service } From 640bc494cb11937bfb2f3901db203c7b84e449c8 Mon Sep 17 00:00:00 2001 From: "ljf (zamentur)" Date: Sun, 2 Dec 2018 02:43:39 +0100 Subject: [PATCH 26/49] [enh] Improve upnp support (#542) --- src/yunohost/firewall.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/yunohost/firewall.py b/src/yunohost/firewall.py index 7b1c72170..0e1cf6e76 100644 --- a/src/yunohost/firewall.py +++ b/src/yunohost/firewall.py @@ -343,7 +343,8 @@ def firewall_upnp(action='status', no_refresh=False): # Refresh port mapping using UPnP if not no_refresh: upnpc = miniupnpc.UPnP() - upnpc.discoverdelay = 3000 + upnpc.discoverdelay = 62000 + upnpc.localport = 1900 # Discover UPnP device(s) logger.debug('discovering UPnP devices...') From 02544f837c5a88d828ab829bc1b01e193766d469 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 28 Nov 2018 16:16:24 +0100 Subject: [PATCH 27/49] tools_adminpw was still checking the password strength despite --force-password --- src/yunohost/tools.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index 271947b3d..baa614fa5 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -118,7 +118,7 @@ def tools_ldapinit(): return auth -def tools_adminpw(auth, new_password): +def tools_adminpw(auth, new_password, check_strength=True): """ Change admin password @@ -130,7 +130,8 @@ def tools_adminpw(auth, new_password): from yunohost.utils.password import assert_password_is_strong_enough import spwd - assert_password_is_strong_enough("admin", new_password) + if check_strength: + assert_password_is_strong_enough("admin", new_password) new_hash = _hash_user_password(new_password) @@ -416,7 +417,7 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False, tools_maindomain(auth, domain) # Change LDAP admin password - tools_adminpw(auth, password) + tools_adminpw(auth, password, check_strength=not force_password) # Enable UPnP silently and reload firewall firewall_upnp('enable', no_refresh=True) From 207c2516b5943019eaf02d51a05ecf82afaefd2d Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 28 Nov 2018 22:01:27 +0000 Subject: [PATCH 28/49] Forgot to get the 'value' key here.. --- src/yunohost/utils/password.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/utils/password.py b/src/yunohost/utils/password.py index 68e51056b..6e8f5ba0a 100644 --- a/src/yunohost/utils/password.py +++ b/src/yunohost/utils/password.py @@ -60,7 +60,7 @@ class PasswordValidator(object): # (or at least that's my understanding -- Alex) settings = json.load(open('/etc/yunohost/settings.json', "r")) setting_key = "security.password." + profile + ".strength" - self.validation_strength = int(settings[setting_key]) + self.validation_strength = int(settings[setting_key]["value"]) except Exception as e: # Fallback to default value if we can't fetch settings for some reason self.validation_strength = 1 From fe0c127aa8107e52bba890e1cb46abe3c7cf8690 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 1 Dec 2018 16:21:59 +0100 Subject: [PATCH 29/49] Log dyndns update only if we really update something (#591) --- src/yunohost/dyndns.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/yunohost/dyndns.py b/src/yunohost/dyndns.py index 3e040d682..dd652119f 100644 --- a/src/yunohost/dyndns.py +++ b/src/yunohost/dyndns.py @@ -206,9 +206,6 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None, key = keys[0] - operation_logger.related_to.append(('domain', domain)) - operation_logger.start() - # This mean that hmac-md5 is used # (Re?)Trigger the migration to sha256 and return immediately. # The actual update will be done in next run. @@ -258,6 +255,8 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None, logger.info("No updated needed.") return else: + operation_logger.related_to.append(('domain', domain)) + operation_logger.start() logger.info("Updated needed, going on...") dns_conf = _build_dns_conf(domain) From 48e20ca9bf4d40cc683ab654035bf9a5f01b4804 Mon Sep 17 00:00:00 2001 From: frju365 Date: Sun, 2 Dec 2018 17:20:03 +0100 Subject: [PATCH 30/49] [fix] Regen nginx conf to be sure it integrates OCSP Stapling (#588) * [fix] Regen nginx conf to be sure it integrates OCSP Stapling * Typo * Regen nginx each time we enable a new cert * add comment about the reason of the PR --- src/yunohost/certificate.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/yunohost/certificate.py b/src/yunohost/certificate.py index 801741b31..8da6ab52a 100644 --- a/src/yunohost/certificate.py +++ b/src/yunohost/certificate.py @@ -803,6 +803,11 @@ def _enable_certificate(domain, new_cert_folder): for service in ("postfix", "dovecot", "metronome"): _run_service_command("restart", service) + if os.path.isfile('/etc/yunohost/installed'): + # regen nginx conf to be sure it integrates OCSP Stapling + # (We don't do this yet if postinstall is not finished yet) + service_regen_conf(names=['nginx']) + _run_service_command("reload", "nginx") From 65dee220e308a2fad4a65235c6c1ffaebd3761bd Mon Sep 17 00:00:00 2001 From: frju365 Date: Sun, 2 Dec 2018 17:20:03 +0100 Subject: [PATCH 31/49] [fix] Regen nginx conf to be sure it integrates OCSP Stapling (#588) * [fix] Regen nginx conf to be sure it integrates OCSP Stapling * Typo * Regen nginx each time we enable a new cert * add comment about the reason of the PR --- src/yunohost/certificate.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/yunohost/certificate.py b/src/yunohost/certificate.py index 049eeb0f4..0c52f43b1 100644 --- a/src/yunohost/certificate.py +++ b/src/yunohost/certificate.py @@ -803,6 +803,11 @@ def _enable_certificate(domain, new_cert_folder): for service in ("postfix", "dovecot", "metronome"): _run_service_command("restart", service) + if os.path.isfile('/etc/yunohost/installed'): + # regen nginx conf to be sure it integrates OCSP Stapling + # (We don't do this yet if postinstall is not finished yet) + service_regen_conf(names=['nginx']) + _run_service_command("reload", "nginx") From db93aa6d5cded943b3265b77fc8c87a98a137b06 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sun, 2 Dec 2018 16:23:11 +0000 Subject: [PATCH 32/49] Update changelog for 3.3.2 --- debian/changelog | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/debian/changelog b/debian/changelog index ca4d8d928..084d7f096 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,18 @@ +yunohost (3.3.2) stable; urgency=low + + * [fix] Regen nginx conf to be sure it integrates OCSP Stapling (#588) + * [fix] Broken new settings and options to control passwords checks / constrains (#589) + * [fix] Log dyndns update only if we really update something (#591) + + -- Alexandre Aubin Sun, 02 Dev 2018 17:23:00 +0000 + +yunohost (3.3.2) stable; urgency=low + + * [fix] Log dyndns update only if we really update something (#591) + * [fix] Broken new settings and options to control passwords checks / constrains (#589) + + -- Alexandre Aubin Sun, 02 Dev 2018 17:17:00 +0000 + yunohost (3.3.1) stable; urgency=low * [fix] Wait for dpkg lock to be free in apt helpers (#571) From 0ac908326a4a79aec6de9f37da8cf7fa9034fcf8 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 3 Dec 2018 14:02:12 +0100 Subject: [PATCH 33/49] Return instead of break, otherwise warning is shown --- data/helpers.d/package | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/helpers.d/package b/data/helpers.d/package index 22adb9b15..8b672d701 100644 --- a/data/helpers.d/package +++ b/data/helpers.d/package @@ -15,7 +15,7 @@ ynh_wait_dpkg_free() { # Sleep an exponential time at each round sleep $(( try * try )) else - break + return 0 fi done echo "apt still used, but timeout reached !" From 3a2464dfb46bc2d6cba7cbe3862a694b6cd5258c Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 6 Dec 2018 18:27:18 +0100 Subject: [PATCH 34/49] Skip migrations one at a time --- src/yunohost/tools.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index baa614fa5..add114b99 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -938,6 +938,10 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai operation_logger.success() + # Skip migrations one at a time + if skip: + break + # special case where we want to go back from the start if target == 0: state["last_run_migration"] = None From 3ca8c089e116b0d6a5344ffdec6ff106ec25140c Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 6 Dec 2018 18:33:39 +0100 Subject: [PATCH 35/49] Have a function to initialize migrations --- src/yunohost/tools.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index add114b99..f6535d85c 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -432,7 +432,7 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False, _install_appslist_fetch_cron() # Init migrations (skip them, no need to run them on a fresh system) - tools_migrations_migrate(skip=True, auto=True) + _skip_all_migrations() os.system('touch /etc/yunohost/installed') @@ -948,7 +948,6 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai write_to_json(MIGRATIONS_STATE_PATH, state) - def tools_migrations_state(): """ Show current migration state @@ -1048,6 +1047,25 @@ def _load_migration(migration_file): raise MoulinetteError(errno.EINVAL, m18n.n('migrations_error_failed_to_load_migration', number=number, name=name)) +def _skip_all_migrations(): + """ + Skip all pending migrations. + This is meant to be used during postinstall to + initialize the migration system. + """ + state = tools_migrations_state() + + # load all migrations + migrations = _get_migrations_list() + migrations = sorted(migrations, key=lambda x: x.number) + last_migration = migrations[-1] + + state["last_run_migration"] = { + "number": last_migration.number, + "name": last_migration.name + } + write_to_json(MIGRATIONS_STATE_PATH, state) + class Migration(object): From 791ac440375515b6ca4a1c5d53c2f1529bd9b47d Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 6 Dec 2018 22:10:06 +0100 Subject: [PATCH 36/49] Add success message after running migrations --- locales/en.json | 1 + src/yunohost/tools.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/locales/en.json b/locales/en.json index 6ce22ca80..3bb36ae9d 100644 --- a/locales/en.json +++ b/locales/en.json @@ -305,6 +305,7 @@ "migrations_show_currently_running_migration": "Running migration {number} {name}...", "migrations_show_last_migration": "Last ran migration is {}", "migrations_skip_migration": "Skipping migration {number} {name}...", + "migrations_success": "Successfully ran migration {number} {name}!", "migrations_to_be_ran_manually": "Migration {number} {name} has to be ran manually. Please go to Tools > Migrations on the webadmin, or run `yunohost tools migrations migrate`.", "migrations_need_to_accept_disclaimer": "To run the migration {number} {name}, your must accept the following disclaimer:\n---\n{disclaimer}\n---\nIf you accept to run the migration, please re-run the command with the option --accept-disclaimer.", "monitor_disabled": "The server monitoring has been disabled", diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index f6535d85c..fbadb3b20 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -924,6 +924,9 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai logger.error(msg, exc_info=1) operation_logger.error(msg) break + else: + logger.success(m18n.n('migrations_success', + number=migration.number, name=migration.name)) else: # if skip logger.warn(m18n.n('migrations_skip_migration', From 0fa374db40171f6412b2cc4f10d1bb2dd7ffc014 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 6 Dec 2018 22:11:06 +0100 Subject: [PATCH 37/49] This message should be info --- src/yunohost/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index fbadb3b20..3bffe3606 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -903,7 +903,7 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai if not skip: - logger.warn(m18n.n('migrations_show_currently_running_migration', + logger.info(m18n.n('migrations_show_currently_running_migration', number=migration.number, name=migration.name)) try: From 783ecf8f4158876be6192abf576f9acbef379268 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 6 Dec 2018 18:24:53 +0100 Subject: [PATCH 38/49] Manage migration of auto/manual and disclaimer on a per-migration basis --- src/yunohost/tools.py | 47 +++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index 3bffe3606..d8cd53f56 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -872,31 +872,34 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai else: # can't happen, this case is handle before raise Exception() - # If we are migrating in "automatic mode" (i.e. from debian - # configure during an upgrade of the package) but we are asked to run - # migrations is to be ran manually by the user - manual_migrations = [m for m in migrations if m.mode == "manual"] - if not skip and auto and manual_migrations: - for m in manual_migrations: - logger.warn(m18n.n('migrations_to_be_ran_manually', - number=m.number, - name=m.name)) - return - - # If some migrations have disclaimers, require the --accept-disclaimer - # option - migrations_with_disclaimer = [m for m in migrations if m.disclaimer] - if not skip and not accept_disclaimer and migrations_with_disclaimer: - for m in migrations_with_disclaimer: - logger.warn(m18n.n('migrations_need_to_accept_disclaimer', - number=m.number, - name=m.name, - disclaimer=m.disclaimer)) - return - # effectively run selected migrations for migration in migrations: + if not skip: + # If we are migrating in "automatic mode" (i.e. from debian configure + # during an upgrade of the package) but we are asked to run migrations + # to be ran manually by the user, stop there and ask the user to + # run the migration manually. + if auto and migration.mode == "manual": + logger.warn(m18n.n('migrations_to_be_ran_manually', + number=migration.number, + name=migration.name)) + break + + # If some migrations have disclaimers, + if migration.disclaimer: + # require the --accept-disclaimer option. Otherwise, stop everything + # here and display the disclaimer + if not accept_disclaimer: + logger.warn(m18n.n('migrations_need_to_accept_disclaimer', + number=migration.number, + name=migration.name, + disclaimer=migration.disclaimer)) + break + # --accept-disclaimer will only work for the first migration + else: + accept_disclaimer = False + # Start register change on system operation_logger= OperationLogger('tools_migrations_migrate_' + mode) operation_logger.start() From 1ac97c46adc4518eefdf2a43b57c86e9626b087d Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 7 Dec 2018 19:12:47 +0100 Subject: [PATCH 39/49] Explicit root password change each time admin password is changed --- locales/en.json | 2 +- .../data_migrations/0006_sync_admin_and_root_passwords.py | 2 +- src/yunohost/tools.py | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/locales/en.json b/locales/en.json index 6ce22ca80..6a2852f80 100644 --- a/locales/en.json +++ b/locales/en.json @@ -291,7 +291,6 @@ "migration_0005_postgresql_96_not_installed": "Postgresql 9.4 has been found to be installed, but not postgresql 9.6 !? Something weird might have happened on your system :( ...", "migration_0005_not_enough_space": "Not enough space is available in {path} to run the migration right now :(.", "migration_0006_disclaimer": "Yunohost now expects admin and root passwords to be synchronized. By running this migration, your root password is going to be replaced by the admin password.", - "migration_0006_done": "Your root password have been replaced by your admin password.", "migrations_backward": "Migrating backward.", "migrations_bad_value_for_target": "Invalid number for target argument, available migrations numbers are 0 or {}", "migrations_cant_reach_migration_file": "Can't access migrations files at path %s", @@ -375,6 +374,7 @@ "restore_running_hooks": "Running restoration hooks...", "restore_system_part_failed": "Unable to restore the '{part:s}' system part", "root_password_desynchronized": "The admin password has been changed, but YunoHost was unable to propagate this on the root password !", + "root_password_replaced_by_admin_password": "Your root password have been replaced by your admin password.", "server_shutdown": "The server will shutdown", "server_shutdown_confirm": "The server will shutdown immediatly, are you sure? [{answers:s}]", "server_reboot": "The server will reboot", diff --git a/src/yunohost/data_migrations/0006_sync_admin_and_root_passwords.py b/src/yunohost/data_migrations/0006_sync_admin_and_root_passwords.py index 366363f22..ee3aeefcb 100644 --- a/src/yunohost/data_migrations/0006_sync_admin_and_root_passwords.py +++ b/src/yunohost/data_migrations/0006_sync_admin_and_root_passwords.py @@ -23,7 +23,7 @@ class MyMigration(Migration): new_hash = self._get_admin_hash() self._replace_root_hash(new_hash) - logger.info(m18n.n("migration_0006_done")) + logger.info(m18n.n("root_password_replaced_by_admin_password")) def backward(self): pass diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index baa614fa5..fea1f8398 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -155,6 +155,8 @@ def tools_adminpw(auth, new_password, check_strength=True): except IOError as e: logger.warning(m18n.n('root_password_desynchronized')) return + + logger.info(m18n.n("root_password_replaced_by_admin_password")) logger.success(m18n.n('admin_password_changed')) From c2631d74cde608e3a060637391d34bf4ac05e411 Mon Sep 17 00:00:00 2001 From: nqb Date: Sat, 8 Dec 2018 04:39:30 +0100 Subject: [PATCH 40/49] fix change quotes around CAA value for letsencrypt.org --- src/yunohost/domain.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/yunohost/domain.py b/src/yunohost/domain.py index dd2eda4a3..7b387618a 100644 --- a/src/yunohost/domain.py +++ b/src/yunohost/domain.py @@ -340,7 +340,7 @@ def _build_dns_conf(domain, ttl=3600): {"type": "TXT", "name": "_dmarc", "value": "\"v=DMARC1; p=none\"", "ttl": 3600} ], "extra": [ - {"type": "CAA", "name": "@", "value": "128 issue 'letsencrypt.org'", "ttl": 3600}, + {"type": "CAA", "name": "@", "value": "128 issue \"letsencrypt.org\"", "ttl": 3600}, ], } """ @@ -397,7 +397,7 @@ def _build_dns_conf(domain, ttl=3600): # Extra extra = [ - ["@", ttl, "CAA", "128 issue 'letsencrypt.org'"] + ["@", ttl, "CAA", '128 issue "letsencrypt.org"'] ] return { From 7754f2722a9eb3b1aace286fb6ccdc9f97c9983b Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 3 Dec 2018 14:02:12 +0100 Subject: [PATCH 41/49] Return instead of break, otherwise warning is shown --- data/helpers.d/package | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/helpers.d/package b/data/helpers.d/package index 22adb9b15..8b672d701 100644 --- a/data/helpers.d/package +++ b/data/helpers.d/package @@ -15,7 +15,7 @@ ynh_wait_dpkg_free() { # Sleep an exponential time at each round sleep $(( try * try )) else - break + return 0 fi done echo "apt still used, but timeout reached !" From cd3ed6af6fa6e590ef3736ed61c7d3962740a9ef Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 7 Dec 2018 19:12:47 +0100 Subject: [PATCH 42/49] Explicit root password change each time admin password is changed --- locales/en.json | 2 +- .../data_migrations/0006_sync_admin_and_root_passwords.py | 2 +- src/yunohost/tools.py | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/locales/en.json b/locales/en.json index 6ce22ca80..6a2852f80 100644 --- a/locales/en.json +++ b/locales/en.json @@ -291,7 +291,6 @@ "migration_0005_postgresql_96_not_installed": "Postgresql 9.4 has been found to be installed, but not postgresql 9.6 !? Something weird might have happened on your system :( ...", "migration_0005_not_enough_space": "Not enough space is available in {path} to run the migration right now :(.", "migration_0006_disclaimer": "Yunohost now expects admin and root passwords to be synchronized. By running this migration, your root password is going to be replaced by the admin password.", - "migration_0006_done": "Your root password have been replaced by your admin password.", "migrations_backward": "Migrating backward.", "migrations_bad_value_for_target": "Invalid number for target argument, available migrations numbers are 0 or {}", "migrations_cant_reach_migration_file": "Can't access migrations files at path %s", @@ -375,6 +374,7 @@ "restore_running_hooks": "Running restoration hooks...", "restore_system_part_failed": "Unable to restore the '{part:s}' system part", "root_password_desynchronized": "The admin password has been changed, but YunoHost was unable to propagate this on the root password !", + "root_password_replaced_by_admin_password": "Your root password have been replaced by your admin password.", "server_shutdown": "The server will shutdown", "server_shutdown_confirm": "The server will shutdown immediatly, are you sure? [{answers:s}]", "server_reboot": "The server will reboot", diff --git a/src/yunohost/data_migrations/0006_sync_admin_and_root_passwords.py b/src/yunohost/data_migrations/0006_sync_admin_and_root_passwords.py index 366363f22..ee3aeefcb 100644 --- a/src/yunohost/data_migrations/0006_sync_admin_and_root_passwords.py +++ b/src/yunohost/data_migrations/0006_sync_admin_and_root_passwords.py @@ -23,7 +23,7 @@ class MyMigration(Migration): new_hash = self._get_admin_hash() self._replace_root_hash(new_hash) - logger.info(m18n.n("migration_0006_done")) + logger.info(m18n.n("root_password_replaced_by_admin_password")) def backward(self): pass diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index baa614fa5..fea1f8398 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -155,6 +155,8 @@ def tools_adminpw(auth, new_password, check_strength=True): except IOError as e: logger.warning(m18n.n('root_password_desynchronized')) return + + logger.info(m18n.n("root_password_replaced_by_admin_password")) logger.success(m18n.n('admin_password_changed')) From ccd9c1631ea30f4314681662e5ab91f842548f62 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 6 Dec 2018 18:27:18 +0100 Subject: [PATCH 43/49] Skip migrations one at a time --- src/yunohost/tools.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index fea1f8398..fce2f1569 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -940,6 +940,10 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai operation_logger.success() + # Skip migrations one at a time + if skip: + break + # special case where we want to go back from the start if target == 0: state["last_run_migration"] = None From 8c3905c5d3de183227d9836c753b7fbdf64c261d Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 6 Dec 2018 18:33:39 +0100 Subject: [PATCH 44/49] Have a function to initialize migrations --- src/yunohost/tools.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index fce2f1569..ebb9516f1 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -434,7 +434,7 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False, _install_appslist_fetch_cron() # Init migrations (skip them, no need to run them on a fresh system) - tools_migrations_migrate(skip=True, auto=True) + _skip_all_migrations() os.system('touch /etc/yunohost/installed') @@ -950,7 +950,6 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai write_to_json(MIGRATIONS_STATE_PATH, state) - def tools_migrations_state(): """ Show current migration state @@ -1050,6 +1049,25 @@ def _load_migration(migration_file): raise MoulinetteError(errno.EINVAL, m18n.n('migrations_error_failed_to_load_migration', number=number, name=name)) +def _skip_all_migrations(): + """ + Skip all pending migrations. + This is meant to be used during postinstall to + initialize the migration system. + """ + state = tools_migrations_state() + + # load all migrations + migrations = _get_migrations_list() + migrations = sorted(migrations, key=lambda x: x.number) + last_migration = migrations[-1] + + state["last_run_migration"] = { + "number": last_migration.number, + "name": last_migration.name + } + write_to_json(MIGRATIONS_STATE_PATH, state) + class Migration(object): From fee5b1efa108e705451d7eeb05ba28715ccc79d1 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 6 Dec 2018 22:10:06 +0100 Subject: [PATCH 45/49] Add success message after running migrations --- locales/en.json | 1 + src/yunohost/tools.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/locales/en.json b/locales/en.json index 6a2852f80..bc90c93a6 100644 --- a/locales/en.json +++ b/locales/en.json @@ -304,6 +304,7 @@ "migrations_show_currently_running_migration": "Running migration {number} {name}...", "migrations_show_last_migration": "Last ran migration is {}", "migrations_skip_migration": "Skipping migration {number} {name}...", + "migrations_success": "Successfully ran migration {number} {name}!", "migrations_to_be_ran_manually": "Migration {number} {name} has to be ran manually. Please go to Tools > Migrations on the webadmin, or run `yunohost tools migrations migrate`.", "migrations_need_to_accept_disclaimer": "To run the migration {number} {name}, your must accept the following disclaimer:\n---\n{disclaimer}\n---\nIf you accept to run the migration, please re-run the command with the option --accept-disclaimer.", "monitor_disabled": "The server monitoring has been disabled", diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index ebb9516f1..42e5cd690 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -926,6 +926,9 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai logger.error(msg, exc_info=1) operation_logger.error(msg) break + else: + logger.success(m18n.n('migrations_success', + number=migration.number, name=migration.name)) else: # if skip logger.warn(m18n.n('migrations_skip_migration', From 3d5cb7e3d17ca8e9d4e3cecba1b017323bb21dc4 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 6 Dec 2018 22:11:06 +0100 Subject: [PATCH 46/49] This message should be info --- src/yunohost/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index 42e5cd690..63863a57f 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -905,7 +905,7 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai if not skip: - logger.warn(m18n.n('migrations_show_currently_running_migration', + logger.info(m18n.n('migrations_show_currently_running_migration', number=migration.number, name=migration.name)) try: From 34c3968501bf4131e4472c45a4dd337c5f77e5d7 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 6 Dec 2018 18:24:53 +0100 Subject: [PATCH 47/49] Manage migration of auto/manual and disclaimer on a per-migration basis --- src/yunohost/tools.py | 47 +++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index 63863a57f..78e641189 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -874,31 +874,34 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai else: # can't happen, this case is handle before raise Exception() - # If we are migrating in "automatic mode" (i.e. from debian - # configure during an upgrade of the package) but we are asked to run - # migrations is to be ran manually by the user - manual_migrations = [m for m in migrations if m.mode == "manual"] - if not skip and auto and manual_migrations: - for m in manual_migrations: - logger.warn(m18n.n('migrations_to_be_ran_manually', - number=m.number, - name=m.name)) - return - - # If some migrations have disclaimers, require the --accept-disclaimer - # option - migrations_with_disclaimer = [m for m in migrations if m.disclaimer] - if not skip and not accept_disclaimer and migrations_with_disclaimer: - for m in migrations_with_disclaimer: - logger.warn(m18n.n('migrations_need_to_accept_disclaimer', - number=m.number, - name=m.name, - disclaimer=m.disclaimer)) - return - # effectively run selected migrations for migration in migrations: + if not skip: + # If we are migrating in "automatic mode" (i.e. from debian configure + # during an upgrade of the package) but we are asked to run migrations + # to be ran manually by the user, stop there and ask the user to + # run the migration manually. + if auto and migration.mode == "manual": + logger.warn(m18n.n('migrations_to_be_ran_manually', + number=migration.number, + name=migration.name)) + break + + # If some migrations have disclaimers, + if migration.disclaimer: + # require the --accept-disclaimer option. Otherwise, stop everything + # here and display the disclaimer + if not accept_disclaimer: + logger.warn(m18n.n('migrations_need_to_accept_disclaimer', + number=migration.number, + name=migration.name, + disclaimer=migration.disclaimer)) + break + # --accept-disclaimer will only work for the first migration + else: + accept_disclaimer = False + # Start register change on system operation_logger= OperationLogger('tools_migrations_migrate_' + mode) operation_logger.start() From b71ee3a9a0d89fd6405c78308c74c2856cc01d05 Mon Sep 17 00:00:00 2001 From: nqb Date: Sat, 8 Dec 2018 04:39:30 +0100 Subject: [PATCH 48/49] fix change quotes around CAA value for letsencrypt.org --- src/yunohost/domain.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/yunohost/domain.py b/src/yunohost/domain.py index dd2eda4a3..7b387618a 100644 --- a/src/yunohost/domain.py +++ b/src/yunohost/domain.py @@ -340,7 +340,7 @@ def _build_dns_conf(domain, ttl=3600): {"type": "TXT", "name": "_dmarc", "value": "\"v=DMARC1; p=none\"", "ttl": 3600} ], "extra": [ - {"type": "CAA", "name": "@", "value": "128 issue 'letsencrypt.org'", "ttl": 3600}, + {"type": "CAA", "name": "@", "value": "128 issue \"letsencrypt.org\"", "ttl": 3600}, ], } """ @@ -397,7 +397,7 @@ def _build_dns_conf(domain, ttl=3600): # Extra extra = [ - ["@", ttl, "CAA", "128 issue 'letsencrypt.org'"] + ["@", ttl, "CAA", '128 issue "letsencrypt.org"'] ] return { From bda028f2b25928840b5c9d9fb4b38456451ff67b Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sun, 9 Dec 2018 19:59:05 +0000 Subject: [PATCH 49/49] Update changelog for 3.3.3 --- debian/changelog | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/debian/changelog b/debian/changelog index 084d7f096..3abd967e1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,17 +1,19 @@ +yunohost (3.3.3) stable; urgency=low + + * [fix] ynh_wait_dpkg_free displaying a warning despite everything being okay (#593) + * [fix] Quotes for recommended CAA DNS record (#596) + * [fix] Manual migration and disclaimer behaviors (#594) + * [fix] Explicit root password change each time admin password is changed + + -- Alexandre Aubin Sun, 09 Dec 2018 20:58:00 +0000 + yunohost (3.3.2) stable; urgency=low * [fix] Regen nginx conf to be sure it integrates OCSP Stapling (#588) * [fix] Broken new settings and options to control passwords checks / constrains (#589) * [fix] Log dyndns update only if we really update something (#591) - -- Alexandre Aubin Sun, 02 Dev 2018 17:23:00 +0000 - -yunohost (3.3.2) stable; urgency=low - - * [fix] Log dyndns update only if we really update something (#591) - * [fix] Broken new settings and options to control passwords checks / constrains (#589) - - -- Alexandre Aubin Sun, 02 Dev 2018 17:17:00 +0000 + -- Alexandre Aubin Sun, 02 Dec 2018 17:23:00 +0000 yunohost (3.3.1) stable; urgency=low