mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Merge branch 'dev' into manifestv2
This commit is contained in:
commit
8939ba66d3
24 changed files with 315 additions and 133 deletions
|
@ -1,6 +1,7 @@
|
|||
[Unit]
|
||||
Description=YunoHost mDNS service
|
||||
After=network.target
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
User=mdns
|
||||
|
|
32
debian/changelog
vendored
32
debian/changelog
vendored
|
@ -1,3 +1,35 @@
|
|||
yunohost (11.0.4) testing; urgency=low
|
||||
|
||||
- [mod] certificate: drop unused 'staging' LE mode (4b78e8e3)
|
||||
- [fix] cli: bash_completion was broken ([#1423](https://github.com/YunoHost/yunohost/pull/1423))
|
||||
- [enh] mdns: Wait for network to be fully up to start the service ([#1425](https://github.com/YunoHost/yunohost/pull/1425))
|
||||
- [fix] regenconf: make some systemctl enable/disable quiet (bccff1b4, 345e50ae)
|
||||
- [fix] configpanels: Compute choices for the yunohost admin when installing an app ([#1427](https://github.com/YunoHost/yunohost/pull/1427))
|
||||
- [fix] configpanels: optimize _get_toml for domains to not load the whole DNS section stuff when just getting a simple info from another section (bf6252ac)
|
||||
- [fix] configpanel: oopsies, could only change the default app for domain configs :P (0a59f863)
|
||||
- [fix] php73_to_php74: another search&replace for synapse (f0a01ba2)
|
||||
- [fix] php73_to_php74: stopping php7.3 before starting 7.4 should be more robust in case confs are conflicting (9ae7ec59)
|
||||
- [i18n] Translations updated for French, Ukrainian
|
||||
|
||||
Thanks to all contributors <3 ! (Éric Gaspar, Kay0u, Tagadda, tituspijean, Tymofii-Lytvynenko)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 29 Jan 2022 19:19:44 +0100
|
||||
|
||||
yunohost (11.0.3) testing; urgency=low
|
||||
|
||||
- [enh] mail: Add SNI support for postfix and dovecot ([#1413](https://github.com/YunoHost/yunohost/pull/1413))
|
||||
- [fix] services: fix a couple edge cases (4571c5b2)
|
||||
- [fix] services: Do not save php-fpm services in services.yml (5d0f8021)
|
||||
- [fix] diagnosis: diagnosers were run in a funky order ([#1418](https://github.com/YunoHost/yunohost/pull/1418))
|
||||
- [fix] configpanels: config_get should return possible choices for domain, user questions (and other dynamic-choices questions) ([#1420](https://github.com/YunoHost/yunohost/pull/1420))
|
||||
- [enh] apps/domain: Clarify the default app mecanism, handle it fron domain config panel ([#1406](https://github.com/YunoHost/yunohost/pull/1406))
|
||||
- [fix] apps: When no main app permission found, fallback to default label instead of having a 'None' label to prevent the webadmin from displaying an empty app list (07396b8b)
|
||||
- [i18n] Translations updated for Galician
|
||||
|
||||
Thanks to all contributors <3 ! (José M, Kay0u, Tagadda, tituspijean)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 25 Jan 2022 13:06:10 +0100
|
||||
|
||||
yunohost (11.0.2) testing; urgency=low
|
||||
|
||||
- [mod] Various tweaks for Python 3.9, PHP 7.4, PostgreSQL 13, and other changes related to Buster->Bullseye ecosystem
|
||||
|
|
2
debian/install
vendored
2
debian/install
vendored
|
@ -5,6 +5,6 @@ helpers/* /usr/share/yunohost/helpers.d/
|
|||
conf/* /usr/share/yunohost/conf/
|
||||
locales/* /usr/share/yunohost/locales/
|
||||
doc/yunohost.8.gz /usr/share/man/man8/
|
||||
doc/bash-completion.sh /etc/bash_completion.d/yunohost
|
||||
doc/bash_completion.d/* /etc/bash_completion.d/
|
||||
conf/metronome/modules/* /usr/lib/metronome/modules/
|
||||
src/* /usr/lib/python3/dist-packages/yunohost/
|
||||
|
|
|
@ -13,7 +13,8 @@ import yaml
|
|||
|
||||
THIS_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
ACTIONSMAP_FILE = THIS_SCRIPT_DIR + "/../share/actionsmap.yml"
|
||||
BASH_COMPLETION_FILE = THIS_SCRIPT_DIR + "/bash-completion.sh"
|
||||
BASH_COMPLETION_FOLDER = THIS_SCRIPT_DIR + "/bash_completion.d"
|
||||
BASH_COMPLETION_FILE = BASH_COMPLETION_FOLDER + "/yunohost"
|
||||
|
||||
|
||||
def get_dict_actions(OPTION_SUBTREE, category):
|
||||
|
@ -61,6 +62,8 @@ with open(ACTIONSMAP_FILE, "r") as stream:
|
|||
OPTION_TREE[category]["subcategories"], subcategory
|
||||
)
|
||||
|
||||
os.makedirs(BASH_COMPLETION_FOLDER, exist_ok=True)
|
||||
|
||||
with open(BASH_COMPLETION_FILE, "w") as generated_file:
|
||||
|
||||
# header of the file
|
||||
|
|
|
@ -62,7 +62,7 @@ do_init_regen() {
|
|||
|
||||
systemctl daemon-reload
|
||||
|
||||
systemctl enable yunohost-api.service
|
||||
systemctl enable yunohost-api.service --quiet
|
||||
systemctl start yunohost-api.service
|
||||
# Yunohost-firewall is enabled only during postinstall, not init, not 100% sure why
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ _generate_config() {
|
|||
do_init_regen() {
|
||||
do_pre_regen
|
||||
do_post_regen /etc/systemd/system/yunomdns.service
|
||||
systemctl enable yunomdns
|
||||
systemctl enable yunomdns --quiet
|
||||
}
|
||||
|
||||
do_pre_regen() {
|
||||
|
@ -53,12 +53,12 @@ do_post_regen() {
|
|||
systemctl daemon-reload
|
||||
fi
|
||||
|
||||
systemctl disable avahi-daemon.socket --now 2>&1|| true
|
||||
systemctl disable avahi-daemon --now 2>&1 || true
|
||||
systemctl disable avahi-daemon.socket --quiet --now 2>/dev/null || true
|
||||
systemctl disable avahi-daemon --quiet --now 2>/dev/null || true
|
||||
|
||||
# Legacy stuff to enable the new yunomdns service on legacy systems
|
||||
if [[ -e /etc/avahi/avahi-daemon.conf ]] && grep -q 'yunohost' /etc/avahi/avahi-daemon.conf; then
|
||||
systemctl enable yunomdns --now
|
||||
systemctl enable yunomdns --now --quiet
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
|
|
1
locales/da.json
Normal file
1
locales/da.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -310,6 +310,7 @@
|
|||
"domain_config_auth_key": "Authentication key",
|
||||
"domain_config_auth_secret": "Authentication secret",
|
||||
"domain_config_auth_token": "Authentication token",
|
||||
"domain_config_default_app": "Default app",
|
||||
"domain_config_features_disclaimer": "So far, enabling/disabling mail or XMPP features only impact the recommended and automatic DNS configuration, not system configurations!",
|
||||
"domain_config_mail_in": "Incoming emails",
|
||||
"domain_config_mail_out": "Outgoing emails",
|
||||
|
@ -500,7 +501,7 @@
|
|||
"migration_0021_yunohost_upgrade": "Starting YunoHost core upgrade...",
|
||||
"migration_0023_not_enough_space": "Make sufficient space available in {path} to run the migration.",
|
||||
"migration_0023_postgresql_11_not_installed": "PostgreSQL was not installed on your system. Nothing to do.",
|
||||
"migration_0023_postgresql_13_not_installed": "PostgreSQL 11 is installed, but not postgresql 13!? Something weird might have happened on your system :(...",
|
||||
"migration_0023_postgresql_13_not_installed": "PostgreSQL 11 is installed, but not PostgreSQL 13!? Something weird might have happened on your system :(...",
|
||||
"migration_description_0021_migrate_to_bullseye": "Upgrade the system to Debian Bullseye and YunoHost 11.x",
|
||||
"migration_description_0022_php73_to_php74_pools": "Migrate php7.3-fpm 'pool' conf files to php7.4",
|
||||
"migration_description_0023_postgresql_11_to_13": "Migrate databases from PostgreSQL 11 to 13",
|
||||
|
|
|
@ -676,5 +676,14 @@
|
|||
"migration_0021_patch_yunohost_conflicts": "Application du correctif pour contourner le problème de conflit...",
|
||||
"migration_0021_not_buster": "La distribution Debian actuelle n'est pas Buster !",
|
||||
"migration_description_0021_migrate_to_bullseye": "Mise à niveau du système vers Debian Bullseye et YunoHost 11.x",
|
||||
"global_settings_setting_security_ssh_password_authentication": "Autoriser l'authentification par mot de passe pour SSH"
|
||||
}
|
||||
"global_settings_setting_security_ssh_password_authentication": "Autoriser l'authentification par mot de passe pour SSH",
|
||||
"domain_config_default_app": "Application par défaut",
|
||||
"migration_description_0022_php73_to_php74_pools": "Migration des fichiers de configuration php7.3-fpm 'pool' vers php7.4",
|
||||
"migration_description_0023_postgresql_11_to_13": "Migration des bases de données de PostgreSQL 11 vers 13",
|
||||
"service_description_postgresql": "Stocke les données d'application (base de données SQL)",
|
||||
"tools_upgrade": "Mise à niveau des packages système",
|
||||
"migration_0023_postgresql_13_not_installed": "PostgreSQL 11 est installé, mais pas PostgreSQL 13 ! ? Quelque chose d'anormal s'est peut-être produit sur votre système :(...",
|
||||
"tools_upgrade_failed": "Impossible de mettre à jour les paquets : {packages_list}",
|
||||
"migration_0023_not_enough_space": "Prévoyez suffisamment d'espace disponible dans {path} pour exécuter la migration.",
|
||||
"migration_0023_postgresql_11_not_installed": "PostgreSQL n'a pas été installé sur votre système. Il n'y a rien à faire."
|
||||
}
|
||||
|
|
|
@ -676,5 +676,13 @@
|
|||
"migration_description_0021_migrate_to_bullseye": "Actualizar o sistema a Debian Bullseye e YunoHost 11.x",
|
||||
"migration_0021_system_not_fully_up_to_date": "O teu sistema non está completamente actualizado. Fai unha actualización normal antes de executar a migración a Bullseye.",
|
||||
"migration_0021_general_warning": "Ten en conta que a migración é unha operación delicada. O equipo de YunoHost fixo todo o que puido para revisalo e probalo, pero aínda así poderían acontecer fallos no sistema ou apps.\n\nAsí as cousas, é recomendable:\n - Facer unha copia de apoio dos datos e apps importantes. Máis info en https://yunohost.org/backup;\n - Ter paciencia unha vez inicias a migración: dependendo da túa conexión a internet e hardware, podería levarlle varias horas completar o proceso.",
|
||||
"global_settings_setting_security_ssh_password_authentication": "Permitir autenticación con contrasinal para SSH"
|
||||
}
|
||||
"global_settings_setting_security_ssh_password_authentication": "Permitir autenticación con contrasinal para SSH",
|
||||
"tools_upgrade_failed": "Non se actualizaron os paquetes: {packages_list}",
|
||||
"migration_0023_not_enough_space": "Crear espazo suficiente en {path} para realizar a migración.",
|
||||
"migration_0023_postgresql_11_not_installed": "PostgreSQL non estaba instalado no sistema. Nada que facer.",
|
||||
"migration_0023_postgresql_13_not_installed": "PostgreSQL 11 está instalado, pero PostgreSQL 13 non!? Algo raro debeu pasarlle ao teu sistema :(...",
|
||||
"migration_description_0022_php73_to_php74_pools": "Migrar ficheiros de configuración de php7.3-fpm 'pool' a php7.4",
|
||||
"migration_description_0023_postgresql_11_to_13": "Migrar bases de datos de PostgreSQL 11 a 13",
|
||||
"service_description_postgresql": "Almacena datos da app (Base datos SQL)",
|
||||
"tools_upgrade": "Actualizando paquetes do sistema"
|
||||
}
|
||||
|
|
|
@ -676,5 +676,14 @@
|
|||
"migration_0021_system_not_fully_up_to_date": "Ваша система не повністю оновлена. Будь ласка, виконайте регулярне оновлення перед запуском міграції на Bullseye.",
|
||||
"migration_0021_general_warning": "Будь ласка, зверніть увагу, що ця міграція є делікатною операцією. Команда YunoHost зробила все можливе, щоб перевірити і протестувати її, але міграція все ще може порушити частину системи або її застосунків.\n\nТому рекомендовано:\n - Виконати резервне копіювання всіх важливих даних або застосунків. Подробиці на сайті https://yunohost.org/backup; \n - Наберіться терпіння після запуску міграції: В залежності від вашого з'єднання з Інтернетом і апаратного забезпечення, оновлення може зайняти до декількох годин.",
|
||||
"migration_description_0021_migrate_to_bullseye": "Оновлення системи до Debian Bullseye і YunoHost 11.x",
|
||||
"global_settings_setting_security_ssh_password_authentication": "Дозволити автентифікацію паролем для SSH"
|
||||
}
|
||||
"global_settings_setting_security_ssh_password_authentication": "Дозволити автентифікацію паролем для SSH",
|
||||
"service_description_postgresql": "Зберігає дані застосунків (база даних SQL)",
|
||||
"domain_config_default_app": "Типовий застосунок",
|
||||
"migration_0023_postgresql_13_not_installed": "PostgreSQL 11 встановлено, але не PostgreSQL 13!? У вашій системі могло статися щось неприємне :(...",
|
||||
"migration_description_0023_postgresql_11_to_13": "Перенесення баз даних з PostgreSQL 11 на 13",
|
||||
"tools_upgrade": "Оновлення системних пакетів",
|
||||
"tools_upgrade_failed": "Не вдалося оновити наступні пакети: {packages_list}",
|
||||
"migration_0023_not_enough_space": "Звільніть достатньо місця в {path} для виконання міграції.",
|
||||
"migration_0023_postgresql_11_not_installed": "PostgreSQL не було встановлено у вашій системі. Нічого робити.",
|
||||
"migration_description_0022_php73_to_php74_pools": "Перенесення конфігураційних файлів php7.3-fpm 'pool' на php7.4"
|
||||
}
|
||||
|
|
|
@ -531,9 +531,6 @@ domain:
|
|||
--self-signed:
|
||||
help: Install self-signed certificate instead of Let's Encrypt
|
||||
action: store_true
|
||||
--staging:
|
||||
help: Use the fake/staging Let's Encrypt certification authority. The new certificate won't actually be enabled - it is only intended to test the main steps of the procedure.
|
||||
action: store_true
|
||||
|
||||
### certificate_renew()
|
||||
cert-renew:
|
||||
|
@ -552,9 +549,6 @@ domain:
|
|||
--no-checks:
|
||||
help: Does not perform any check that your domain seems correctly configured (DNS, reachability) before attempting to renew. (Not recommended)
|
||||
action: store_true
|
||||
--staging:
|
||||
help: Use the fake/staging Let's Encrypt certification authority. The new certificate won't actually be enabled - it is only intended to test the main steps of the procedure.
|
||||
action: store_true
|
||||
|
||||
### domain_url_available()
|
||||
url-available:
|
||||
|
@ -677,9 +671,6 @@ domain:
|
|||
--self-signed:
|
||||
help: Install self-signed certificate instead of Let's Encrypt
|
||||
action: store_true
|
||||
--staging:
|
||||
help: Use the fake/staging Let's Encrypt certification authority. The new certificate won't actually be enabled - it is only intended to test the main steps of the procedure.
|
||||
action: store_true
|
||||
|
||||
### certificate_renew()
|
||||
renew:
|
||||
|
@ -698,9 +689,6 @@ domain:
|
|||
--no-checks:
|
||||
help: Does not perform any check that your domain seems correctly configured (DNS, reachability) before attempting to renew. (Not recommended)
|
||||
action: store_true
|
||||
--staging:
|
||||
help: Use the fake/staging Let's Encrypt certification authority. The new certificate won't actually be enabled - it is only intended to test the main steps of the procedure.
|
||||
action: store_true
|
||||
|
||||
|
||||
#############################
|
||||
|
@ -896,6 +884,10 @@ app:
|
|||
-d:
|
||||
full: --domain
|
||||
help: Specific domain to put app on (the app domain by default)
|
||||
-u:
|
||||
full: --undo
|
||||
help: Undo redirection
|
||||
action: store_true
|
||||
|
||||
### app_ssowatconf()
|
||||
ssowatconf:
|
||||
|
|
|
@ -11,6 +11,11 @@ i18n = "domain_config"
|
|||
#
|
||||
|
||||
[feature]
|
||||
[feature.app]
|
||||
[feature.app.default_app]
|
||||
type = "app"
|
||||
filter = "is_webapp"
|
||||
default = "_none"
|
||||
|
||||
[feature.mail]
|
||||
#services = ['postfix', 'dovecot']
|
||||
|
|
70
src/app.py
70
src/app.py
|
@ -58,6 +58,7 @@ from yunohost.utils.config import (
|
|||
ask_questions_and_parse_answers,
|
||||
DomainQuestion,
|
||||
PathQuestion,
|
||||
hydrate_questions_with_choices,
|
||||
)
|
||||
from yunohost.utils.i18n import _value_for_locale
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
|
@ -126,6 +127,7 @@ def app_info(app, full=False):
|
|||
Get info for a specific app
|
||||
"""
|
||||
from yunohost.permission import user_permission_list
|
||||
from yunohost.domain import domain_config_get
|
||||
|
||||
_assert_is_installed(app)
|
||||
|
||||
|
@ -162,6 +164,11 @@ def app_info(app, full=False):
|
|||
|
||||
ret["is_webapp"] = "domain" in settings and "path" in settings
|
||||
|
||||
if ret["is_webapp"]:
|
||||
ret["is_default"] = (
|
||||
domain_config_get(settings["domain"], "feature.app.default_app") == app
|
||||
)
|
||||
|
||||
ret["supports_change_url"] = os.path.exists(
|
||||
os.path.join(setting_path, "scripts", "change_url")
|
||||
)
|
||||
|
@ -178,6 +185,7 @@ def app_info(app, full=False):
|
|||
|
||||
if not ret["label"]:
|
||||
logger.warning(f"Failed to get label for app {app} ?")
|
||||
ret["label"] = local_manifest["name"]
|
||||
return ret
|
||||
|
||||
|
||||
|
@ -722,6 +730,9 @@ def app_manifest(app):
|
|||
|
||||
shutil.rmtree(extracted_app_folder)
|
||||
|
||||
raw_questions = manifest.get("arguments", {}).get("install", [])
|
||||
manifest["arguments"]["install"] = hydrate_questions_with_choices(raw_questions)
|
||||
|
||||
return manifest
|
||||
|
||||
|
||||
|
@ -1069,6 +1080,7 @@ def app_remove(operation_logger, app, purge=False):
|
|||
permission_delete,
|
||||
permission_sync_to_user,
|
||||
)
|
||||
from yunohost.domain import domain_list, domain_config_get, domain_config_set
|
||||
|
||||
if not _is_installed(app):
|
||||
raise YunohostValidationError(
|
||||
|
@ -1131,6 +1143,10 @@ def app_remove(operation_logger, app, purge=False):
|
|||
|
||||
hook_remove(app)
|
||||
|
||||
for domain in domain_list()["domains"]:
|
||||
if domain_config_get(domain, "feature.app.default_app") == app:
|
||||
domain_config_set(domain, "feature.app.default_app", "_none")
|
||||
|
||||
if ret == 0:
|
||||
logger.success(m18n.n("app_removed", app=app))
|
||||
hook_callback("post_app_remove", env=env_dict)
|
||||
|
@ -1142,7 +1158,7 @@ def app_remove(operation_logger, app, purge=False):
|
|||
|
||||
|
||||
@is_unit_operation()
|
||||
def app_makedefault(operation_logger, app, domain=None):
|
||||
def app_makedefault(operation_logger, app, domain=None, undo=False):
|
||||
"""
|
||||
Redirect domain root to an app
|
||||
|
||||
|
@ -1151,11 +1167,10 @@ def app_makedefault(operation_logger, app, domain=None):
|
|||
domain
|
||||
|
||||
"""
|
||||
from yunohost.domain import _assert_domain_exists
|
||||
from yunohost.domain import _assert_domain_exists, domain_config_set
|
||||
|
||||
app_settings = _get_app_settings(app)
|
||||
app_domain = app_settings["domain"]
|
||||
app_path = app_settings["path"]
|
||||
|
||||
if domain is None:
|
||||
domain = app_domain
|
||||
|
@ -1164,36 +1179,12 @@ def app_makedefault(operation_logger, app, domain=None):
|
|||
|
||||
operation_logger.related_to.append(("domain", domain))
|
||||
|
||||
if "/" in app_map(raw=True)[domain]:
|
||||
raise YunohostValidationError(
|
||||
"app_make_default_location_already_used",
|
||||
app=app,
|
||||
domain=app_domain,
|
||||
other_app=app_map(raw=True)[domain]["/"]["id"],
|
||||
)
|
||||
|
||||
operation_logger.start()
|
||||
|
||||
# TODO / FIXME : current trick is to add this to conf.json.persisten
|
||||
# This is really not robust and should be improved
|
||||
# e.g. have a flag in /etc/yunohost/apps/$app/ to say that this is the
|
||||
# default app or idk...
|
||||
if not os.path.exists("/etc/ssowat/conf.json.persistent"):
|
||||
ssowat_conf = {}
|
||||
if undo:
|
||||
domain_config_set(domain, "feature.app.default_app", "_none")
|
||||
else:
|
||||
ssowat_conf = read_json("/etc/ssowat/conf.json.persistent")
|
||||
|
||||
if "redirected_urls" not in ssowat_conf:
|
||||
ssowat_conf["redirected_urls"] = {}
|
||||
|
||||
ssowat_conf["redirected_urls"][domain + "/"] = app_domain + app_path
|
||||
|
||||
write_to_json(
|
||||
"/etc/ssowat/conf.json.persistent", ssowat_conf, sort_keys=True, indent=4
|
||||
)
|
||||
chmod("/etc/ssowat/conf.json.persistent", 0o644)
|
||||
|
||||
logger.success(m18n.n("ssowat_conf_updated"))
|
||||
domain_config_set(domain, "feature.app.default_app", app)
|
||||
|
||||
|
||||
def app_setting(app, key, value=None, delete=False):
|
||||
|
@ -1392,7 +1383,7 @@ def app_ssowatconf():
|
|||
|
||||
|
||||
"""
|
||||
from yunohost.domain import domain_list, _get_maindomain
|
||||
from yunohost.domain import domain_list, _get_maindomain, domain_config_get
|
||||
from yunohost.permission import user_permission_list
|
||||
|
||||
main_domain = _get_maindomain()
|
||||
|
@ -1430,6 +1421,23 @@ def app_ssowatconf():
|
|||
redirected_urls.update(app_settings.get("redirected_urls", {}))
|
||||
redirected_regex.update(app_settings.get("redirected_regex", {}))
|
||||
|
||||
from .utils.legacy import (
|
||||
translate_legacy_default_app_in_ssowant_conf_json_persistent,
|
||||
)
|
||||
|
||||
translate_legacy_default_app_in_ssowant_conf_json_persistent()
|
||||
|
||||
for domain in domains:
|
||||
default_app = domain_config_get(domain, "feature.app.default_app")
|
||||
if default_app != "_none" and _is_installed(default_app):
|
||||
app_settings = _get_app_settings(default_app)
|
||||
app_domain = app_settings["domain"]
|
||||
app_path = app_settings["path"]
|
||||
|
||||
# Prevent infinite redirect loop...
|
||||
if domain + "/" != app_domain + app_path:
|
||||
redirected_urls[domain + "/"] = app_domain + app_path
|
||||
|
||||
# New permission system
|
||||
for perm_name, perm_info in all_permissions.items():
|
||||
|
||||
|
|
|
@ -60,8 +60,6 @@ KEY_SIZE = 3072
|
|||
|
||||
VALIDITY_LIMIT = 15 # days
|
||||
|
||||
# For tests
|
||||
STAGING_CERTIFICATION_AUTHORITY = "https://acme-staging-v02.api.letsencrypt.org"
|
||||
# For prod
|
||||
PRODUCTION_CERTIFICATION_AUTHORITY = "https://acme-v02.api.letsencrypt.org"
|
||||
|
||||
|
@ -113,9 +111,7 @@ def certificate_status(domains, full=False):
|
|||
return {"certificates": certificates}
|
||||
|
||||
|
||||
def certificate_install(
|
||||
domain_list, force=False, no_checks=False, self_signed=False, staging=False
|
||||
):
|
||||
def certificate_install(domain_list, force=False, no_checks=False, self_signed=False):
|
||||
"""
|
||||
Install a Let's Encrypt certificate for given domains (all by default)
|
||||
|
||||
|
@ -130,7 +126,7 @@ def certificate_install(
|
|||
if self_signed:
|
||||
_certificate_install_selfsigned(domain_list, force)
|
||||
else:
|
||||
_certificate_install_letsencrypt(domain_list, force, no_checks, staging)
|
||||
_certificate_install_letsencrypt(domain_list, force, no_checks)
|
||||
|
||||
|
||||
def _certificate_install_selfsigned(domain_list, force=False):
|
||||
|
@ -233,9 +229,7 @@ def _certificate_install_selfsigned(domain_list, force=False):
|
|||
operation_logger.error(msg)
|
||||
|
||||
|
||||
def _certificate_install_letsencrypt(
|
||||
domains, force=False, no_checks=False, staging=False
|
||||
):
|
||||
def _certificate_install_letsencrypt(domains, force=False, no_checks=False):
|
||||
from yunohost.domain import domain_list, _assert_domain_exists
|
||||
|
||||
if not os.path.exists(ACCOUNT_KEY_FILE):
|
||||
|
@ -264,11 +258,6 @@ def _certificate_install_letsencrypt(
|
|||
"certmanager_domain_cert_not_selfsigned", domain=domain
|
||||
)
|
||||
|
||||
if staging:
|
||||
logger.warning(
|
||||
"Please note that you used the --staging option, and that no new certificate will actually be enabled !"
|
||||
)
|
||||
|
||||
# Actual install steps
|
||||
for domain in domains:
|
||||
|
||||
|
@ -284,12 +273,12 @@ def _certificate_install_letsencrypt(
|
|||
operation_logger = OperationLogger(
|
||||
"letsencrypt_cert_install",
|
||||
[("domain", domain)],
|
||||
args={"force": force, "no_checks": no_checks, "staging": staging},
|
||||
args={"force": force, "no_checks": no_checks},
|
||||
)
|
||||
operation_logger.start()
|
||||
|
||||
try:
|
||||
_fetch_and_enable_new_certificate(domain, staging, no_checks=no_checks)
|
||||
_fetch_and_enable_new_certificate(domain, no_checks=no_checks)
|
||||
except Exception as e:
|
||||
msg = f"Certificate installation for {domain} failed !\nException: {e}"
|
||||
logger.error(msg)
|
||||
|
@ -304,9 +293,7 @@ def _certificate_install_letsencrypt(
|
|||
operation_logger.success()
|
||||
|
||||
|
||||
def certificate_renew(
|
||||
domains, force=False, no_checks=False, email=False, staging=False
|
||||
):
|
||||
def certificate_renew(domains, force=False, no_checks=False, email=False):
|
||||
"""
|
||||
Renew Let's Encrypt certificate for given domains (all by default)
|
||||
|
||||
|
@ -373,11 +360,6 @@ def certificate_renew(
|
|||
"certmanager_acme_not_configured_for_domain", domain=domain
|
||||
)
|
||||
|
||||
if staging:
|
||||
logger.warning(
|
||||
"Please note that you used the --staging option, and that no new certificate will actually be enabled !"
|
||||
)
|
||||
|
||||
# Actual renew steps
|
||||
for domain in domains:
|
||||
|
||||
|
@ -399,14 +381,13 @@ def certificate_renew(
|
|||
args={
|
||||
"force": force,
|
||||
"no_checks": no_checks,
|
||||
"staging": staging,
|
||||
"email": email,
|
||||
},
|
||||
)
|
||||
operation_logger.start()
|
||||
|
||||
try:
|
||||
_fetch_and_enable_new_certificate(domain, staging, no_checks=no_checks)
|
||||
_fetch_and_enable_new_certificate(domain, no_checks=no_checks)
|
||||
except Exception as e:
|
||||
import traceback
|
||||
from io import StringIO
|
||||
|
@ -473,7 +454,7 @@ def _check_acme_challenge_configuration(domain):
|
|||
return "include /etc/nginx/conf.d/acme-challenge.conf.inc" in read_file(domain_conf)
|
||||
|
||||
|
||||
def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False):
|
||||
def _fetch_and_enable_new_certificate(domain, no_checks=False):
|
||||
|
||||
if not os.path.exists(ACCOUNT_KEY_FILE):
|
||||
_generate_account_key()
|
||||
|
@ -507,11 +488,6 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False):
|
|||
|
||||
domain_csr_file = f"{TMP_FOLDER}/{domain}.csr"
|
||||
|
||||
if staging:
|
||||
certification_authority = STAGING_CERTIFICATION_AUTHORITY
|
||||
else:
|
||||
certification_authority = PRODUCTION_CERTIFICATION_AUTHORITY
|
||||
|
||||
try:
|
||||
signed_certificate = sign_certificate(
|
||||
ACCOUNT_KEY_FILE,
|
||||
|
@ -519,7 +495,7 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False):
|
|||
WEBROOT_FOLDER,
|
||||
log=logger,
|
||||
disable_check=no_checks,
|
||||
CA=certification_authority,
|
||||
CA=PRODUCTION_CERTIFICATION_AUTHORITY,
|
||||
)
|
||||
except ValueError as e:
|
||||
if "urn:acme:error:rateLimited" in str(e):
|
||||
|
@ -539,12 +515,7 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False):
|
|||
# Create corresponding directory
|
||||
date_tag = datetime.utcnow().strftime("%Y%m%d.%H%M%S")
|
||||
|
||||
if staging:
|
||||
folder_flag = "staging"
|
||||
else:
|
||||
folder_flag = "letsencrypt"
|
||||
|
||||
new_cert_folder = f"{CERT_FOLDER}/{domain}-history/{date_tag}-{folder_flag}"
|
||||
new_cert_folder = f"{CERT_FOLDER}/{domain}-history/{date_tag}-letsencrypt"
|
||||
|
||||
os.makedirs(new_cert_folder)
|
||||
|
||||
|
@ -563,9 +534,6 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False):
|
|||
|
||||
_set_permissions(domain_cert_file, "root", "ssl-cert", 0o640)
|
||||
|
||||
if staging:
|
||||
return
|
||||
|
||||
_enable_certificate(domain, new_cert_folder)
|
||||
|
||||
# Check the status of the certificate is now good
|
||||
|
@ -677,12 +645,6 @@ def _get_status(domain):
|
|||
"verbose": "Let's Encrypt",
|
||||
}
|
||||
|
||||
elif cert_issuer.startswith("Fake LE"):
|
||||
CA_type = {
|
||||
"code": "fake-lets-encrypt",
|
||||
"verbose": "Fake Let's Encrypt",
|
||||
}
|
||||
|
||||
else:
|
||||
CA_type = {
|
||||
"code": "other-unknown",
|
||||
|
|
|
@ -18,7 +18,7 @@ class MyDiagnoser(Diagnoser):
|
|||
|
||||
def run(self):
|
||||
|
||||
MB = 1024 ** 2
|
||||
MB = 1024**2
|
||||
GB = MB * 1024
|
||||
|
||||
#
|
||||
|
|
|
@ -656,9 +656,10 @@ class Diagnoser:
|
|||
def _list_diagnosis_categories():
|
||||
|
||||
paths = glob.glob(os.path.dirname(__file__) + "/diagnosers/??-*.py")
|
||||
names = [name.split("-")[-1] for name in sorted(
|
||||
[os.path.basename(path)[: -len(".py")] for path in paths]
|
||||
)]
|
||||
names = [
|
||||
name.split("-")[-1]
|
||||
for name in sorted([os.path.basename(path)[: -len(".py")] for path in paths])
|
||||
]
|
||||
|
||||
return names
|
||||
|
||||
|
|
|
@ -454,19 +454,50 @@ class DomainConfigPanel(ConfigPanel):
|
|||
save_path_tpl = f"{DOMAIN_SETTINGS_DIR}/{{entity}}.yml"
|
||||
save_mode = "diff"
|
||||
|
||||
def _apply(self):
|
||||
if (
|
||||
"default_app" in self.future_values
|
||||
and self.future_values["default_app"] != self.values["default_app"]
|
||||
):
|
||||
from yunohost.app import app_ssowatconf, app_map
|
||||
|
||||
if "/" in app_map(raw=True)[self.entity]:
|
||||
raise YunohostValidationError(
|
||||
"app_make_default_location_already_used",
|
||||
app=self.future_values["default_app"],
|
||||
domain=self.entity,
|
||||
other_app=app_map(raw=True)[self.entity]["/"]["id"],
|
||||
)
|
||||
|
||||
super()._apply()
|
||||
|
||||
# Reload ssowat if default app changed
|
||||
if (
|
||||
"default_app" in self.future_values
|
||||
and self.future_values["default_app"] != self.values["default_app"]
|
||||
):
|
||||
app_ssowatconf()
|
||||
|
||||
def _get_toml(self):
|
||||
from yunohost.dns import _get_registrar_config_section
|
||||
|
||||
toml = super()._get_toml()
|
||||
|
||||
toml["feature"]["xmpp"]["xmpp"]["default"] = (
|
||||
1 if self.entity == _get_maindomain() else 0
|
||||
)
|
||||
toml["dns"]["registrar"] = _get_registrar_config_section(self.entity)
|
||||
|
||||
# FIXME: Ugly hack to save the registar id/value and reinject it in _load_current_values ...
|
||||
self.registar_id = toml["dns"]["registrar"]["registrar"]["value"]
|
||||
del toml["dns"]["registrar"]["registrar"]["value"]
|
||||
# Optimize wether or not to load the DNS section,
|
||||
# e.g. we don't want to trigger the whole _get_registary_config_section
|
||||
# when just getting the current value from the feature section
|
||||
filter_key = self.filter_key.split(".") if self.filter_key != "" else []
|
||||
if not filter_key or filter_key[0] == "dns":
|
||||
from yunohost.dns import _get_registrar_config_section
|
||||
|
||||
toml["dns"]["registrar"] = _get_registrar_config_section(self.entity)
|
||||
|
||||
# FIXME: Ugly hack to save the registar id/value and reinject it in _load_current_values ...
|
||||
self.registar_id = toml["dns"]["registrar"]["registrar"]["value"]
|
||||
del toml["dns"]["registrar"]["registrar"]["value"]
|
||||
|
||||
return toml
|
||||
|
||||
|
@ -476,7 +507,9 @@ class DomainConfigPanel(ConfigPanel):
|
|||
super()._load_current_values()
|
||||
|
||||
# FIXME: Ugly hack to save the registar id/value and reinject it in _load_current_values ...
|
||||
self.values["registrar"] = self.registar_id
|
||||
filter_key = self.filter_key.split(".") if self.filter_key != "" else []
|
||||
if not filter_key or filter_key[0] == "dns":
|
||||
self.values["registrar"] = self.registar_id
|
||||
|
||||
|
||||
def _get_domain_settings(domain: str) -> dict:
|
||||
|
@ -509,20 +542,16 @@ def domain_cert_status(domain_list, full=False):
|
|||
return certificate_status(domain_list, full)
|
||||
|
||||
|
||||
def domain_cert_install(
|
||||
domain_list, force=False, no_checks=False, self_signed=False, staging=False
|
||||
):
|
||||
def domain_cert_install(domain_list, force=False, no_checks=False, self_signed=False):
|
||||
from yunohost.certificate import certificate_install
|
||||
|
||||
return certificate_install(domain_list, force, no_checks, self_signed, staging)
|
||||
return certificate_install(domain_list, force, no_checks, self_signed)
|
||||
|
||||
|
||||
def domain_cert_renew(
|
||||
domain_list, force=False, no_checks=False, email=False, staging=False
|
||||
):
|
||||
def domain_cert_renew(domain_list, force=False, no_checks=False, email=False):
|
||||
from yunohost.certificate import certificate_renew
|
||||
|
||||
return certificate_renew(domain_list, force, no_checks, email, staging)
|
||||
return certificate_renew(domain_list, force, no_checks, email)
|
||||
|
||||
|
||||
def domain_dns_conf(domain):
|
||||
|
|
|
@ -293,7 +293,7 @@ class MyMigration(Migration):
|
|||
raise YunohostError("migration_0021_not_buster")
|
||||
|
||||
# Have > 1 Go free space on /var/ ?
|
||||
if free_space_in_directory("/var/") / (1024 ** 3) < 1.0:
|
||||
if free_space_in_directory("/var/") / (1024**3) < 1.0:
|
||||
raise YunohostError("migration_0021_not_enough_free_space")
|
||||
|
||||
# Check system is up to date
|
||||
|
|
|
@ -17,6 +17,10 @@ NEWPHP_POOLS = "/etc/php/7.4/fpm/pool.d"
|
|||
OLDPHP_SOCKETS_PREFIX = "/run/php/php7.3-fpm"
|
||||
NEWPHP_SOCKETS_PREFIX = "/run/php/php7.4-fpm"
|
||||
|
||||
# Because of synapse é_è
|
||||
OLDPHP_SOCKETS_PREFIX2 = "/run/php7.3-fpm"
|
||||
NEWPHP_SOCKETS_PREFIX2 = "/run/php7.4-fpm"
|
||||
|
||||
MIGRATION_COMMENT = (
|
||||
"; YunoHost note : this file was automatically moved from {}".format(OLDPHP_POOLS)
|
||||
)
|
||||
|
@ -50,6 +54,10 @@ class MyMigration(Migration):
|
|||
OLDPHP_SOCKETS_PREFIX, NEWPHP_SOCKETS_PREFIX, dest
|
||||
)
|
||||
os.system(c)
|
||||
c = "sed -i -e 's@{}@{}@g' {}".format(
|
||||
OLDPHP_SOCKETS_PREFIX2, NEWPHP_SOCKETS_PREFIX2, dest
|
||||
)
|
||||
os.system(c)
|
||||
|
||||
# Also add a comment that it was automatically moved from php7.3
|
||||
# (for human traceability and backward migration)
|
||||
|
@ -69,16 +77,20 @@ class MyMigration(Migration):
|
|||
OLDPHP_SOCKETS_PREFIX, NEWPHP_SOCKETS_PREFIX, nf
|
||||
)
|
||||
os.system(c)
|
||||
c = "sed -i -e 's@{}@{}@g' {}".format(
|
||||
OLDPHP_SOCKETS_PREFIX2, NEWPHP_SOCKETS_PREFIX2, nf
|
||||
)
|
||||
os.system(c)
|
||||
|
||||
os.system(
|
||||
"rm /etc/logrotate.d/php7.3-fpm"
|
||||
) # We remove this otherwise the logrotate cron will be unhappy
|
||||
|
||||
# Reload/restart the php pools
|
||||
_run_service_command("restart", "php7.4-fpm")
|
||||
_run_service_command("enable", "php7.4-fpm")
|
||||
os.system("systemctl stop php7.3-fpm")
|
||||
os.system("systemctl disable php7.3-fpm")
|
||||
_run_service_command("restart", "php7.4-fpm")
|
||||
_run_service_command("enable", "php7.4-fpm")
|
||||
|
||||
# Reload nginx
|
||||
_run_service_command("reload", "nginx")
|
||||
|
|
|
@ -19,6 +19,7 @@ from yunohost.app import (
|
|||
app_config_set,
|
||||
app_ssowatconf,
|
||||
)
|
||||
from yunohost.user import user_create, user_delete
|
||||
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
|
||||
|
@ -101,6 +102,8 @@ def config_app(request):
|
|||
|
||||
def test_app_config_get(config_app):
|
||||
|
||||
user_create("alice", "Alice", "White", _get_maindomain(), "test123Ynh")
|
||||
|
||||
assert isinstance(app_config_get(config_app), dict)
|
||||
assert isinstance(app_config_get(config_app, full=True), dict)
|
||||
assert isinstance(app_config_get(config_app, export=True), dict)
|
||||
|
@ -108,6 +111,8 @@ def test_app_config_get(config_app):
|
|||
assert isinstance(app_config_get(config_app, "main.components"), dict)
|
||||
assert app_config_get(config_app, "main.components.boolean") == "0"
|
||||
|
||||
user_delete("alice")
|
||||
|
||||
|
||||
def test_app_config_nopanel(legacy_app):
|
||||
|
||||
|
|
|
@ -214,7 +214,7 @@ def tools_postinstall(
|
|||
main_space = sum(
|
||||
psutil.disk_usage(d.mountpoint).total for d in main_disk_partitions
|
||||
)
|
||||
GB = 1024 ** 3
|
||||
GB = 1024**3
|
||||
if not force_diskspace and main_space < 10 * GB:
|
||||
raise YunohostValidationError("postinstall_low_rootfsspace")
|
||||
|
||||
|
@ -440,7 +440,7 @@ def tools_upgrade(operation_logger, target=None):
|
|||
raise YunohostValidationError("dpkg_lock_not_available")
|
||||
|
||||
if target not in ["apps", "system"]:
|
||||
raise Exception(
|
||||
raise YunohostValidationError(
|
||||
"Uhoh ?! tools_upgrade should have 'apps' or 'system' value for argument target"
|
||||
)
|
||||
|
||||
|
|
|
@ -285,8 +285,10 @@ class ConfigPanel:
|
|||
ask = m18n.n(self.config["i18n"] + "_" + option["id"])
|
||||
|
||||
if mode == "full":
|
||||
# edit self.config directly
|
||||
option["ask"] = ask
|
||||
question_class = ARGUMENTS_TYPE_PARSERS[option.get("type", "string")]
|
||||
# FIXME : maybe other properties should be taken from the question, not just choices ?.
|
||||
option["choices"] = question_class(option).choices
|
||||
else:
|
||||
result[key] = {"ask": ask}
|
||||
if "current_value" in option:
|
||||
|
@ -438,6 +440,7 @@ class ConfigPanel:
|
|||
"step",
|
||||
"accept",
|
||||
"redact",
|
||||
"filter",
|
||||
],
|
||||
"defaults": {},
|
||||
},
|
||||
|
@ -703,6 +706,7 @@ class Question:
|
|||
self.ask = question.get("ask", {"en": self.name})
|
||||
self.help = question.get("help")
|
||||
self.redact = question.get("redact", False)
|
||||
self.filter = question.get("filter", "true")
|
||||
# .current_value is the currently stored value
|
||||
self.current_value = question.get("current_value")
|
||||
# .value is the "proposed" value which we got from the user
|
||||
|
@ -1109,7 +1113,10 @@ class DomainQuestion(Question):
|
|||
if self.default is None:
|
||||
self.default = _get_maindomain()
|
||||
|
||||
self.choices = domain_list()["domains"]
|
||||
self.choices = {
|
||||
domain: domain + " ★" if domain == self.default else domain
|
||||
for domain in domain_list()["domains"]
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def normalize(value, option={}):
|
||||
|
@ -1124,6 +1131,33 @@ class DomainQuestion(Question):
|
|||
return value
|
||||
|
||||
|
||||
class AppQuestion(Question):
|
||||
argument_type = "app"
|
||||
|
||||
def __init__(
|
||||
self, question, context: Mapping[str, Any] = {}, hooks: Dict[str, Callable] = {}
|
||||
):
|
||||
from yunohost.app import app_list
|
||||
|
||||
super().__init__(question, context, hooks)
|
||||
|
||||
apps = app_list(full=True)["apps"]
|
||||
|
||||
if self.filter:
|
||||
apps = [
|
||||
app
|
||||
for app in apps
|
||||
if evaluate_simple_js_expression(self.filter, context=app)
|
||||
]
|
||||
|
||||
def _app_display(app):
|
||||
domain_path_or_id = f" ({app.get('domain_path', app['id'])})"
|
||||
return app["label"] + domain_path_or_id
|
||||
|
||||
self.choices = {"_none": "---"}
|
||||
self.choices.update({app["id"]: _app_display(app) for app in apps})
|
||||
|
||||
|
||||
class UserQuestion(Question):
|
||||
argument_type = "user"
|
||||
|
||||
|
@ -1134,7 +1168,11 @@ class UserQuestion(Question):
|
|||
from yunohost.domain import _get_maindomain
|
||||
|
||||
super().__init__(question, context, hooks)
|
||||
self.choices = list(user_list()["users"].keys())
|
||||
|
||||
self.choices = {
|
||||
username: f"{infos['fullname']} ({infos['mail']})"
|
||||
for username, infos in user_list()["users"].items()
|
||||
}
|
||||
|
||||
if not self.choices:
|
||||
raise YunohostValidationError(
|
||||
|
@ -1145,7 +1183,7 @@ class UserQuestion(Question):
|
|||
|
||||
if self.default is None:
|
||||
root_mail = "root@%s" % _get_maindomain()
|
||||
for user in self.choices:
|
||||
for user in self.choices.keys():
|
||||
if root_mail in user_info(user).get("mail-aliases", []):
|
||||
self.default = user
|
||||
break
|
||||
|
@ -1331,6 +1369,7 @@ ARGUMENTS_TYPE_PARSERS = {
|
|||
"alert": DisplayTextQuestion,
|
||||
"markdown": DisplayTextQuestion,
|
||||
"file": FileQuestion,
|
||||
"app": AppQuestion,
|
||||
}
|
||||
|
||||
|
||||
|
@ -1378,3 +1417,18 @@ def ask_questions_and_parse_answers(
|
|||
out.append(question)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def hydrate_questions_with_choices(raw_questions: List) -> List:
|
||||
out = []
|
||||
|
||||
for raw_question in raw_questions:
|
||||
question = ARGUMENTS_TYPE_PARSERS[raw_question.get("type", "string")](
|
||||
raw_question
|
||||
)
|
||||
if question.choices:
|
||||
raw_question["choices"] = question.choices
|
||||
raw_question["default"] = question.default
|
||||
out.append(raw_question)
|
||||
|
||||
return out
|
||||
|
|
|
@ -7,6 +7,7 @@ from moulinette.utils.filesystem import (
|
|||
read_file,
|
||||
write_to_file,
|
||||
write_to_yaml,
|
||||
write_to_json,
|
||||
read_yaml,
|
||||
)
|
||||
|
||||
|
@ -68,6 +69,55 @@ def legacy_permission_label(app, permission_type):
|
|||
)
|
||||
|
||||
|
||||
def translate_legacy_default_app_in_ssowant_conf_json_persistent():
|
||||
from yunohost.app import app_list
|
||||
from yunohost.domain import domain_config_set
|
||||
|
||||
persistent_file_name = "/etc/ssowat/conf.json.persistent"
|
||||
if not os.path.exists(persistent_file_name):
|
||||
return
|
||||
|
||||
# Ugly hack because for some reason so many people have tabs in their conf.json.persistent ...
|
||||
os.system(r"sed -i 's/\t/ /g' /etc/ssowat/conf.json.persistent")
|
||||
|
||||
# Ugly hack to try not to misarably fail migration
|
||||
persistent = read_yaml(persistent_file_name)
|
||||
|
||||
if "redirected_urls" not in persistent:
|
||||
return
|
||||
|
||||
redirected_urls = persistent["redirected_urls"]
|
||||
|
||||
if not any(
|
||||
from_url.count("/") == 1 and from_url.endswith("/")
|
||||
for from_url in redirected_urls
|
||||
):
|
||||
return
|
||||
|
||||
apps = app_list()["apps"]
|
||||
|
||||
if not any(app.get("domain_path") in redirected_urls.values() for app in apps):
|
||||
return
|
||||
|
||||
for from_url, dest_url in redirected_urls.copy().items():
|
||||
# Not a root domain, skip
|
||||
if from_url.count("/") != 1 or not from_url.endswith("/"):
|
||||
continue
|
||||
for app in apps:
|
||||
if app.get("domain_path") != dest_url:
|
||||
continue
|
||||
domain_config_set(from_url.strip("/"), "feature.app.default_app", app["id"])
|
||||
del redirected_urls[from_url]
|
||||
|
||||
persistent["redirected_urls"] = redirected_urls
|
||||
|
||||
write_to_json(persistent_file_name, persistent, sort_keys=True, indent=4)
|
||||
|
||||
logger.warning(
|
||||
"YunoHost automatically translated some legacy redirections in /etc/ssowat/conf.json.persistent to match the new default application using domain configuration"
|
||||
)
|
||||
|
||||
|
||||
LEGACY_PHP_VERSION_REPLACEMENTS = [
|
||||
("/etc/php5", "/etc/php/7.4"),
|
||||
("/etc/php/7.0", "/etc/php/7.4"),
|
||||
|
|
Loading…
Add table
Reference in a new issue