mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Merge branch 'stretch-unstable' into get-rid-of-app-status
This commit is contained in:
commit
3c76497003
16 changed files with 540 additions and 321 deletions
|
@ -677,30 +677,6 @@ app:
|
|||
help: Delete the key
|
||||
action: store_true
|
||||
|
||||
### app_checkport()
|
||||
checkport:
|
||||
action_help: Check availability of a local port
|
||||
api: GET /tools/checkport
|
||||
deprecated: true
|
||||
arguments:
|
||||
port:
|
||||
help: Port to check
|
||||
extra:
|
||||
pattern: &pattern_port
|
||||
- !!str ^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$
|
||||
- "pattern_port"
|
||||
|
||||
### app_checkurl()
|
||||
checkurl:
|
||||
action_help: Check availability of a web path
|
||||
api: GET /tools/checkurl
|
||||
deprecated: True
|
||||
arguments:
|
||||
url:
|
||||
help: Url to check
|
||||
-a:
|
||||
full: --app
|
||||
help: Write domain & path to app settings for further checks
|
||||
|
||||
### app_register_url()
|
||||
register-url:
|
||||
|
@ -715,24 +691,6 @@ app:
|
|||
help: The path to be registered (e.g. /coffee)
|
||||
|
||||
|
||||
### app_initdb()
|
||||
initdb:
|
||||
action_help: Create database and initialize it with optionnal attached script
|
||||
api: POST /tools/initdb
|
||||
deprecated: true
|
||||
arguments:
|
||||
user:
|
||||
help: Name of the DB user
|
||||
-p:
|
||||
full: --password
|
||||
help: Password of the DB (generated unless set)
|
||||
-d:
|
||||
full: --db
|
||||
help: DB name (user unless set)
|
||||
-s:
|
||||
full: --sql
|
||||
help: Initial SQL file
|
||||
|
||||
### app_makedefault()
|
||||
makedefault:
|
||||
action_help: Redirect domain root to an app
|
||||
|
@ -1433,16 +1391,6 @@ tools:
|
|||
help: Upgrade only the system packages
|
||||
action: store_true
|
||||
|
||||
### tools_port_available()
|
||||
port-available:
|
||||
action_help: Check availability of a local port
|
||||
api: GET /tools/portavailable
|
||||
arguments:
|
||||
port:
|
||||
help: Port to check
|
||||
extra:
|
||||
pattern: *pattern_port
|
||||
|
||||
### tools_shell()
|
||||
shell:
|
||||
action_help: Launch a development shell
|
||||
|
@ -1652,7 +1600,7 @@ log:
|
|||
api: GET /logs
|
||||
arguments:
|
||||
category:
|
||||
help: Log category to display (default operations), could be operation, history, package, system, access, service or app
|
||||
help: Log category to display (default operations), could be operation, history, package, system, access, service or app
|
||||
nargs: "*"
|
||||
-l:
|
||||
full: --limit
|
||||
|
|
|
@ -24,6 +24,31 @@ ynh_find_port () {
|
|||
echo $port
|
||||
}
|
||||
|
||||
# Test if a port is available
|
||||
#
|
||||
# example: ynh_port_available --port=1234 || ynh_die "Port 1234 is needs to be available for this app"
|
||||
#
|
||||
# usage: ynh_find_port --port=XYZ
|
||||
# | arg: -p, --port - port to check
|
||||
#
|
||||
# Requires YunoHost version 3.7.x or higher.
|
||||
ynh_port_available () {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=p
|
||||
declare -Ar args_array=( [p]=port= )
|
||||
local port
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
if ss -nltu | grep -q -w :$port
|
||||
then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Validate an IP address
|
||||
#
|
||||
# usage: ynh_validate_ip --family=family --ip_address=ip_address
|
||||
|
|
|
@ -257,6 +257,7 @@ ynh_webpath_register () {
|
|||
# re:/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
|
||||
# re:domain.tld/app/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
|
||||
#
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_create() {
|
||||
declare -Ar args_array=( [p]=permission= [u]=url= [a]=allowed= )
|
||||
local permission
|
||||
|
@ -273,7 +274,7 @@ ynh_permission_create() {
|
|||
if [[ -n ${allowed:-} ]]; then
|
||||
allowed=",allowed=['${allowed//';'/"','"}']"
|
||||
fi
|
||||
|
||||
|
||||
yunohost tools shell -c "from yunohost.permission import permission_create; permission_create('$app.$permission', url=$url ${allowed:-} , sync_perm=False)"
|
||||
}
|
||||
|
||||
|
@ -284,6 +285,7 @@ ynh_permission_create() {
|
|||
# usage: ynh_permission_delete --permission "permission"
|
||||
# | arg: permission - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
|
||||
#
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_delete() {
|
||||
declare -Ar args_array=( [p]=permission= )
|
||||
local permission
|
||||
|
@ -292,12 +294,27 @@ ynh_permission_delete() {
|
|||
yunohost tools shell -c "from yunohost.permission import permission_delete; permission_delete('$app.$permission', sync_perm=False)"
|
||||
}
|
||||
|
||||
# Check if a permission exists
|
||||
#
|
||||
# usage: ynh_permission_exists --permission=permission
|
||||
# | arg: -p, --permission - the permission to check
|
||||
#
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_exists() {
|
||||
declare -Ar args_array=( [p]=permission= )
|
||||
local permission
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
yunohost user permission list -s | grep -w -q "$app.$permission"
|
||||
}
|
||||
|
||||
# Redefine the url associated to a permission
|
||||
#
|
||||
# usage: ynh_permission_url --permission "permission" --url "url"
|
||||
# | arg: permission - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
|
||||
# | arg: url - (optional) URL for which access will be allowed/forbidden
|
||||
#
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_url() {
|
||||
declare -Ar args_array=([p]=permission= [u]=url=)
|
||||
local permission
|
||||
|
@ -322,6 +339,7 @@ ynh_permission_url() {
|
|||
# | arg: remove - the list of group or users to remove from the permission
|
||||
#
|
||||
# example: ynh_permission_update --permission admin --add samdoe --remove all_users
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_update() {
|
||||
declare -Ar args_array=( [p]=permission= [a]=add= [r]=remove= )
|
||||
local permission
|
||||
|
|
|
@ -28,43 +28,6 @@ ynh_exit_properly () {
|
|||
# Small tempo to avoid the next message being mixed up with other DEBUG messages
|
||||
sleep 0.5
|
||||
|
||||
ynh_print_err --message="!!\n $app's script has encountered an error. Its execution was cancelled.\n!!"
|
||||
|
||||
# If the script is executed from the CLI, dump the end of the log that precedes the crash.
|
||||
if [ "$YNH_INTERFACE" == "cli" ]
|
||||
then
|
||||
# Unset xtrace to not spoil the log
|
||||
set +x
|
||||
|
||||
local ynh_log="/var/log/yunohost/yunohost-cli.log"
|
||||
|
||||
# Wait for the log to be fill with the data until the crash.
|
||||
local timeout=0
|
||||
while ! tail --lines=20 "$ynh_log" | grep --quiet "+ ynh_exit_properly"
|
||||
do
|
||||
((timeout++))
|
||||
if [ $timeout -eq 500 ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e "\e[34m\e[1mPlease find here an extract of the log before the crash:\e[0m" >&2
|
||||
# Tail the last 30 lines of log of YunoHost
|
||||
# But remove all lines after "ynh_exit_properly"
|
||||
# Remove the timestamp at the beginning of the line
|
||||
# Remove "yunohost.hook..."
|
||||
# Add DEBUG and color it at the beginning of each log line.
|
||||
echo -e "$(tail --lines=30 "$ynh_log" \
|
||||
| sed '1,/+ ynh_exit_properly/!d' \
|
||||
| sed 's/^[[:digit:]: ,-]*//g' \
|
||||
| sed 's/ *yunohost.hook.*\]/ -/g' \
|
||||
| sed 's/^WARNING /&/g' \
|
||||
| sed 's/^DEBUG /& /g' \
|
||||
| sed 's/^INFO /& /g' \
|
||||
| sed 's/^/\\e[34m\\e[1m[DEBUG]\\e[0m: /g')" >&2
|
||||
set -x
|
||||
fi
|
||||
|
||||
if type -t ynh_clean_setup > /dev/null; then # Check if the function exist in the app script.
|
||||
ynh_clean_setup # Call the function to do specific cleaning for the app.
|
||||
fi
|
||||
|
|
|
@ -24,7 +24,7 @@ class PortsDiagnoser(Diagnoser):
|
|||
ports = [22, 25, 53, 80, 443, 587, 993, 5222, 5269]
|
||||
|
||||
try:
|
||||
r = requests.post('https://ynhdiagnoser.netlib.re/check-ports', json={'ports': ports}, timeout=30).json()
|
||||
r = requests.post('https://diagnosis.yunohost.org/check-ports', json={'ports': ports}, timeout=30).json()
|
||||
if "status" not in r.keys():
|
||||
raise Exception("Bad syntax for response ? Raw json: %s" % str(r))
|
||||
elif r["status"] == "error":
|
||||
|
|
|
@ -28,7 +28,7 @@ class HttpDiagnoser(Diagnoser):
|
|||
os.system("touch /tmp/.well-known/ynh-diagnosis/%s" % nonce)
|
||||
|
||||
try:
|
||||
r = requests.post('https://ynhdiagnoser.netlib.re/check-http', json={'domain': domain, "nonce": nonce}, timeout=30).json()
|
||||
r = requests.post('https://diagnosis.yunohost.org/check-http', json={'domain': domain, "nonce": nonce}, timeout=30).json()
|
||||
if "status" not in r.keys():
|
||||
raise Exception("Bad syntax for response ? Raw json: %s" % str(r))
|
||||
elif r["status"] == "error" and ("code" not in r.keys() or r["code"] not in ["error_http_check_connection_error", "error_http_check_unknown_error"]):
|
||||
|
|
|
@ -162,7 +162,7 @@
|
|||
"admin_password_too_long": "Trieu una contrasenya de menys de 127 caràcters",
|
||||
"dpkg_is_broken": "No es pot fer això en aquest instant perquè dpkg/APT (els gestors de paquets del sistema) sembla estar mal configurat… Podeu intentar solucionar-ho connectant-vos per SSH i executant «sudo dpkg --configure -a».",
|
||||
"dnsmasq_isnt_installed": "sembla que dnsmasq no està instal·lat, executeu \"apt-get remove bind9 && apt-get install dnsmasq\"",
|
||||
"domain_cannot_remove_main": "No es pot eliminar el domini principal. S'ha d'establir un nou domini primer",
|
||||
"domain_cannot_remove_main": "No es pot eliminar «{domain:s}» ja que és el domini principal, primer s'ha d'establir un nou domini principal utilitzant «yunohost domain main-domain -n <un-altre-domini>», aquí hi ha una llista dels possibles dominis: {other_domains:s}",
|
||||
"domain_cert_gen_failed": "No s'ha pogut generar el certificat",
|
||||
"domain_created": "S'ha creat el domini",
|
||||
"domain_creation_failed": "No s'ha pogut crear el domini {domain}: {error}",
|
||||
|
@ -308,7 +308,7 @@
|
|||
"migration_description_0007_ssh_conf_managed_by_yunohost_step1": "La configuració SSH serà gestionada per YunoHost (pas 1, automàtic)",
|
||||
"migration_description_0008_ssh_conf_managed_by_yunohost_step2": "La configuració SSH serà gestionada per YunoHost (pas 2, manual)",
|
||||
"migration_description_0009_decouple_regenconf_from_services": "Desvincula el mecanisme regen-conf dels serveis",
|
||||
"migration_description_0010_migrate_to_apps_json": "Elimina les llistes d'aplicacions obsoletes i utilitza la nova llista unificada «apps.json» en el seu lloc",
|
||||
"migration_description_0010_migrate_to_apps_json": "Elimina els catàlegs d'aplicacions obsolets i utilitza la nova llista unificada «apps.json» en el seu lloc (obsolet, substituït per la migració 13)",
|
||||
"migration_0003_backward_impossible": "La migració Stretch no és reversible.",
|
||||
"migration_0003_start": "Ha començat la migració a Stretch. Els registres estaran disponibles a {logfile}.",
|
||||
"migration_0003_patching_sources_list": "Modificant el fitxer sources.lists…",
|
||||
|
@ -320,7 +320,7 @@
|
|||
"migration_0003_system_not_fully_up_to_date": "El vostre sistema no està completament actualitzat. S'ha de fer una actualització normal abans de fer la migració a Stretch.",
|
||||
"migration_0003_still_on_jessie_after_main_upgrade": "Hi ha hagut un problema durant l'actualització principal: El sistema encara està amb Jessie? Per investigar el problema, mireu el registres a {log}:s…",
|
||||
"migration_0003_general_warning": "Tingueu en compte que la migració és una operació delicada. L'equip de YunoHost a fet els possibles per revisar-la i provar-la, però la migració pot provocar errors en parts del sistema o aplicacions.\n\nPer tant, es recomana:\n - Fer una còpia de seguretat de les dades o aplicacions importants. Més informació a https://yunohost.org/backup;\n - Sigueu pacient un cop llençada la migració: en funció de la connexió a internet i el maquinari, pot trigar fins a unes hores per actualitzar-ho tot.\n\nD'altra banda, el port per SMTP, utilitzat per clients de correu externs (com Thunderbird o K9-Mail) ha canviat de 465 (SSL/TLS) a 587 (STARTTLS). L'antic port (465) serà tancat automàticament, i el nou port (587) serà obert en el tallafocs. Tots els usuaris *hauran* d'adaptar la configuració dels clients de correu en acord amb aquests canvis.",
|
||||
"migration_0003_problematic_apps_warning": "Tingueu en compte que s'han detectat les aplicacions, possiblement, problemàtiques següents. Sembla que aquestes no s'han instal·lat des d'una applist, o que no estan marcades com a «working». Per conseqüent, no podem garantir que segueixin funcionant després de l'actualització: {problematic_apps}",
|
||||
"migration_0003_problematic_apps_warning": "Tingueu en compte que s'han detectat les aplicacions, possiblement, problemàtiques següents. Sembla que aquestes no s'han instal·lat des d'un catàleg d'aplicacions, o que no estan marcades com a «working». Per conseqüent, no podem garantir que segueixin funcionant després de l'actualització: {problematic_apps}",
|
||||
"migration_0003_modified_files": "Tingueu en compte que s'han detectat els següents fitxers que han estat modificats manualment i podrien sobreescriure's al final de l'actualització: {manually_modified_files}",
|
||||
"migration_0005_postgresql_94_not_installed": "PostgreSQL no està instal·lat en el sistema. No hi ha res per fer.",
|
||||
"migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 està instal·lat, però no PostgreSQL 9.6? Alguna cosa estranya a passat en el sistema :( …",
|
||||
|
@ -627,5 +627,81 @@
|
|||
"permission_currently_allowed_for_visitors": "El permís ja el tenen el grup de visitants a més d'altres grups. Segurament s'hauria de revocar el permís al grup dels visitants o eliminar els altres grups als que s'ha atribuït.",
|
||||
"permission_currently_allowed_for_all_users": "El permís ha el té el grup de tots els usuaris (all_users) a més d'altres grups. Segurament s'hauria de revocar el permís a «all_users» o eliminar els altres grups als que s'ha atribuït.",
|
||||
"permission_require_account": "El permís {permission} només té sentit per als usuaris que tenen un compte, i per tant no es pot activar per als visitants.",
|
||||
"app_remove_after_failed_install": "Eliminant l'aplicació després que hagi fallat la instal·lació…"
|
||||
"app_remove_after_failed_install": "Eliminant l'aplicació després que hagi fallat la instal·lació…",
|
||||
"diagnosis_basesystem_ynh_main_version": "El servidor funciona amb YunoHost {main_version} ({repo})",
|
||||
"diagnosis_ram_low": "El sistema només té {available_abs_MB} MB ({available_percent}%) de memòria RAM disponibles d'un total de {total_abs_MB} MB. Aneu amb compte.",
|
||||
"diagnosis_swap_none": "El sistema no té swap. Hauríeu de considerar afegir un mínim de 256 MB de swap per evitar situacions en les que el sistema es queda sense memòria.",
|
||||
"diagnosis_regenconf_manually_modified": "El fitxer de configuració {file} ha estat modificat manualment.",
|
||||
"diagnosis_regenconf_nginx_conf_broken": "Sembla que s'ha trencat la configuració NGINX!",
|
||||
"diagnosis_security_vulnerable_to_meltdown_details": "Per arreglar-ho, hauríeu d'actualitzar i reiniciar el sistema per tal de carregar el nou nucli de linux (o contactar amb el proveïdor del servidor si no funciona). Vegeu https://meltdownattack.com/ per a més informació.",
|
||||
"diagnosis_http_could_not_diagnose": "No s'ha pogut diagnosticar si el domini és accessible des de l'exterior. Error: {error}",
|
||||
"domain_cannot_remove_main_add_new_one": "No es pot eliminar «{domain:s}» ja que és el domini principal i únic domini, primer s'ha d'afegir un altre domini utilitzant «yunohost domain add <un-altre-domini.com>», i després fer-lo el domini principal amb «yunohost domain main-domain -n <un-altre-domini.com>» i després es pot eliminar el domini «{domain:s}» utilitzant «yunohost domain remove {domain:s}».",
|
||||
"diagnosis_basesystem_host": "El servidor funciona amb Debian {debian_version}.",
|
||||
"diagnosis_basesystem_kernel": "El servidor funciona amb el nucli de Linux {kernel_version}",
|
||||
"diagnosis_basesystem_ynh_single_version": "{0} versió: {1}({2})",
|
||||
"diagnosis_basesystem_ynh_inconsistent_versions": "Esteu utilitzant versions inconsistents dels paquets de YunoHost… probablement a causa d'una actualització fallida o parcial.",
|
||||
"diagnosis_display_tip_web": "Podeu anar a la secció de Diagnòstics (en la pantalla principal) per veure els errors que s'han trobat.",
|
||||
"diagnosis_failed_for_category": "Ha fallat el diagnòstic per la categoria «{category}» : {error}",
|
||||
"diagnosis_display_tip_cli": "Podeu executar «yunohost diagnosis show --issues» per mostrar els errors que s'han trobat.",
|
||||
"diagnosis_cache_still_valid": "(La memòria cau encara és vàlida pel diagnòstic de {category}. No es tornar a diagnosticar de moment!)",
|
||||
"diagnosis_cant_run_because_of_dep": "No es pot fer el diagnòstic per {category} mentre hi ha problemes importants relacionats amb {dep}.",
|
||||
"diagnosis_ignored_issues": "(+ {nb_ignored} problema(es) ignorat(s))",
|
||||
"diagnosis_found_errors": "S'ha trobat problema(es) important(s) {errors} relacionats amb {category}!",
|
||||
"diagnosis_found_errors_and_warnings": "S'ha trobat problema(es) important(s) {errors} (i avis(os) {warnings}) relacionats amb {category}!",
|
||||
"diagnosis_found_warnings": "S'han trobat ítems {warnings} que es podrien millorar per {category}.",
|
||||
"diagnosis_everything_ok": "Tot sembla correcte per {category}!",
|
||||
"diagnosis_failed": "No s'han pogut obtenir els resultats del diagnòstic per la categoria «{category}» : {error}",
|
||||
"diagnosis_ip_connected_ipv4": "El servidor està connectat a Internet amb IPv4!",
|
||||
"diagnosis_ip_no_ipv4": "El servidor no té una IPv4 que funcioni.",
|
||||
"diagnosis_ip_connected_ipv6": "El servidor està connectat a Internet amb IPv6!",
|
||||
"diagnosis_ip_no_ipv6": "El servidor no té una IPv6 que funcioni.",
|
||||
"diagnosis_ip_not_connected_at_all": "Sembla que el servidor no està connectat a internet!?",
|
||||
"diagnosis_ip_dnsresolution_working": "La resolució de nom de domini està funcionant!",
|
||||
"diagnosis_ip_broken_dnsresolution": "La resolució de nom de domini falla per algun motiu… Està el tallafocs bloquejant les peticions DNS?",
|
||||
"diagnosis_ip_broken_resolvconf": "La resolució de nom de domini sembla caiguda en el servidor, podria estar relacionat amb el fet que /etc/resolv.conf no apunta cap a 127.0.0.1.",
|
||||
"diagnosis_ip_weird_resolvconf": "La resolució DNS sembla estar funcionant, però aneu amb compte ja que esteu utilitzant un versió personalitzada de /etc/resolv.conf.",
|
||||
"diagnosis_ip_weird_resolvconf_details": "En canvi, aquest fitxer hauria de ser un enllaç simbòlic cap a /etc/resolvconf/run/resolv.conf i que aquest apunti cap a 127.0.0.1 (dnsmasq). La configuració del «resolver» real s'hauria de fer via /etc/resolv.dnsmaq.conf.",
|
||||
"diagnosis_dns_good_conf": "Bona configuració DNS pel domini {domain} (categoria {category})",
|
||||
"diagnosis_dns_bad_conf": "Configuració DNS incorrecta o inexistent pel domini {domain} (categoria {category})",
|
||||
"diagnosis_dns_missing_record": "Segons la configuració DNS recomanada, hauríeu d'afegir un registre DNS de tipus {0}, nom {1} i valor {2}",
|
||||
"diagnosis_dns_discrepancy": "Segons la configuració DNS recomanada, el valor pel registre DNS de tipus {0} i nom {1} hauria de ser {2}, en comptes de {3}.",
|
||||
"diagnosis_services_good_status": "El servei {service} està {status} tal i com s'esperava!",
|
||||
"diagnosis_services_bad_status": "El servei {service} està {status} :/",
|
||||
"diagnosis_diskusage_verylow": "El lloc d'emmagatzematge {mountpoint} (en l'aparell {device}) només té disponibles {free_abs_GB} GB ({free_percent}%). Hauríeu de considerar alliberar una mica d'espai.",
|
||||
"diagnosis_diskusage_low": "El lloc d'emmagatzematge {mountpoint} (en l'aparell {device}) només té disponibles {free_abs_GB} GB ({free_percent}%). Aneu amb compte.",
|
||||
"diagnosis_diskusage_ok": "El lloc d'emmagatzematge {mountpoint} (en l'aparell {device}) encara té {free_abs_GB} GB ({free_percent}%) lliures!",
|
||||
"diagnosis_ram_verylow": "El sistema només té {available_abs_MB} MB ({available_percent}%) de memòria RAM disponibles! (d'un total de {total_abs_MB} MB)",
|
||||
"diagnosis_ram_ok": "El sistema encara té {available_abs_MB} MB ({available_percent}%) de memòria RAM disponibles d'un total de {total_abs_MB} MB.",
|
||||
"diagnosis_swap_notsomuch": "El sistema només té {total_MB} MB de swap. Hauríeu de considerar tenir un mínim de 256 MB per evitar situacions en les que el sistema es queda sense memòria.",
|
||||
"diagnosis_swap_ok": "El sistema té {total_MB} MB de swap!",
|
||||
"diagnosis_regenconf_allgood": "Tots els fitxers de configuració estan en acord amb la configuració recomanada!",
|
||||
"diagnosis_regenconf_manually_modified_details": "No hauria de ser cap problema sempre i quan sapigueu el que esteu fent ;) !",
|
||||
"diagnosis_regenconf_manually_modified_debian": "El fitxer de configuració {file} ha estat modificat manualment respecte al fitxer per defecte de Debian.",
|
||||
"diagnosis_regenconf_manually_modified_debian_details": "No hauria de ser cap problema, però ho haureu de vigilar...",
|
||||
"diagnosis_security_all_good": "No s'ha trobat cap vulnerabilitat de seguretat crítica.",
|
||||
"diagnosis_security_vulnerable_to_meltdown": "Sembla que el sistema és vulnerable a la vulnerabilitat de seguretat crítica Meltdown",
|
||||
"diagnosis_description_basesystem": "Sistema de base",
|
||||
"diagnosis_description_ip": "Connectivitat a Internet",
|
||||
"diagnosis_description_dnsrecords": "Registres DNS",
|
||||
"diagnosis_description_services": "Verificació de l'estat dels serveis",
|
||||
"diagnosis_description_systemresources": "Recursos del sistema",
|
||||
"diagnosis_description_ports": "Exposició dels ports",
|
||||
"diagnosis_description_http": "Exposició HTTP",
|
||||
"diagnosis_description_regenconf": "Configuració del sistema",
|
||||
"diagnosis_description_security": "Verificacions de seguretat",
|
||||
"diagnosis_ports_could_not_diagnose": "No s'ha pogut diagnosticar si els ports són accessibles des de l'exterior. Error: {error}",
|
||||
"diagnosis_ports_unreachable": "El port {port} no és accessible des de l'exterior.",
|
||||
"diagnosis_ports_ok": "El port {port} és accessible des de l'exterior.",
|
||||
"diagnosis_http_ok": "El domini {domain} és accessible des de l'exterior.",
|
||||
"diagnosis_http_unreachable": "El domini {domain} no és accessible a través de HTTP des de l'exterior.",
|
||||
"diagnosis_unknown_categories": "Les següents categories són desconegudes: {categories}",
|
||||
"apps_catalog_init_success": "S'ha iniciat el sistema de catàleg d'aplicacions!",
|
||||
"apps_catalog_updating": "S'està actualitzant el catàleg d'aplicacions…",
|
||||
"apps_catalog_failed_to_download": "No s'ha pogut descarregar el catàleg d'aplicacions {apps_catalog}: {error}",
|
||||
"apps_catalog_obsolete_cache": "La memòria cau del catàleg d'aplicacions és buida o obsoleta.",
|
||||
"apps_catalog_update_success": "S'ha actualitzat el catàleg d'aplicacions!",
|
||||
"diagnosis_mail_ougoing_port_25_ok": "El port de sortida 25 no està bloquejat i els correus es poden enviar a altres servidors.",
|
||||
"diagnosis_mail_ougoing_port_25_blocked": "Sembla que el port de sortida 25 està bloquejat. Hauríeu d'intentar desbloquejar-lo al panell de configuració del proveïdor d'accés a internet (o allotjador). Mentrestant, el servidor no podrà enviar correus a altres servidors.",
|
||||
"diagnosis_description_mail": "Correu electrònic",
|
||||
"migration_description_0013_futureproof_apps_catalog_system": "Migrar al nou sistema de catàleg d'aplicacions resistent al pas del temps"
|
||||
}
|
||||
|
|
|
@ -24,9 +24,7 @@
|
|||
"app_install_files_invalid": "These files cannot be installed",
|
||||
"app_install_failed": "Could not install {app}: {error}",
|
||||
"app_install_script_failed": "An error occurred inside the app installation script",
|
||||
"app_location_already_used": "The app '{app}' is already installed in ({path})",
|
||||
"app_make_default_location_already_used": "Can't make the app '{app}' the default on the domain, '{domain}' is already in use by the other app '{other_app}'",
|
||||
"app_location_install_failed": "Cannot install the app there because it conflicts with the app '{other_app}' already installed in '{other_path}'",
|
||||
"app_location_unavailable": "This URL is either unavailable, or conflicts with the already installed app(s):\n{apps:s}",
|
||||
"app_manifest_invalid": "Something is wrong with the app manifest: {error}",
|
||||
"app_not_upgraded": "The app '{failed_app}' failed to upgrade, and as a consequence the following apps upgrades have been cancelled: {apps}",
|
||||
|
@ -433,9 +431,6 @@
|
|||
"migrations_skip_migration": "Skipping migration {id}…",
|
||||
"migrations_success_forward": "Migration {id} completed",
|
||||
"migrations_to_be_ran_manually": "Migration {id} has to be run manually. Please go to Tools → Migrations on the webadmin page, or run `yunohost tools migrations migrate`.",
|
||||
"mysql_db_creation_failed": "Could not create MySQL database",
|
||||
"mysql_db_init_failed": "Could not initialize MySQL database",
|
||||
"mysql_db_initialized": "The MySQL database is now initialized",
|
||||
"no_internet_connection": "The server is not connected to the Internet",
|
||||
"not_enough_disk_space": "Not enough free space on '{path:s}'",
|
||||
"operation_interrupted": "The operation was manually interrupted?",
|
||||
|
@ -477,8 +472,6 @@
|
|||
"permission_require_account": "Permission {permission} only makes sense for users having an account, and therefore cannot be enabled for visitors.",
|
||||
"port_already_closed": "Port {port:d} is already closed for {ip_version:s} connections",
|
||||
"port_already_opened": "Port {port:d} is already opened for {ip_version:s} connections",
|
||||
"port_available": "Port {port:d} is available",
|
||||
"port_unavailable": "Port {port:d} is not available",
|
||||
"recommend_to_add_first_user": "The post-install is finished, but YunoHost needs at least one user to work correctly, you should add one using 'yunohost user create <username>' or do it from the admin interface.",
|
||||
"regenconf_file_backed_up": "Configuration file '{conf}' backed up to '{backup}'",
|
||||
"regenconf_file_copy_failed": "Could not copy the new configuration file '{new}' to '{conf}'",
|
||||
|
|
|
@ -564,5 +564,20 @@
|
|||
"permission_currently_allowed_for_all_users": "Ĉi tiu permeso estas nuntempe donita al ĉiuj uzantoj aldone al aliaj grupoj. Vi probable volas aŭ forigi la permeson \"all_users\" aŭ forigi la aliajn grupojn, kiujn ĝi nuntempe donas.",
|
||||
"app_install_failed": "Ne povis instali {app} : {error}",
|
||||
"app_install_script_failed": "Eraro okazis en la skripto de instalado de la app",
|
||||
"app_remove_after_failed_install": "Forigado de la app post la instala fiasko …"
|
||||
"app_remove_after_failed_install": "Forigado de la app post la instala fiasko …",
|
||||
"diagnosis_basesystem_host": "Servilo funkcias Debian {debian_version}.",
|
||||
"apps_catalog_init_success": "Aplikoj katalogsistemo inicializita !",
|
||||
"apps_catalog_updating": "Ĝisdatigante katalogo de aplikoj ...",
|
||||
"apps_catalog_failed_to_download": "Ne eblas elŝuti la katalogon de {apps_catalog}: {error}",
|
||||
"apps_catalog_obsolete_cache": "La kaŝmemoro de la katalogo de programoj estas malplena aŭ malaktuala.",
|
||||
"apps_catalog_update_success": "La aplika katalogo estis ĝisdatigita!",
|
||||
"diagnosis_basesystem_kernel": "Servilo funkcias Linuksan kernon {kernel_version}",
|
||||
"diagnosis_basesystem_ynh_single_version": "{0} versio: {1} ({2})",
|
||||
"diagnosis_basesystem_ynh_main_version": "Servilo funkcias YunoHost {main_version} ({repo})",
|
||||
"diagnosis_basesystem_ynh_inconsistent_versions": "Vi prizorgas malkonsekvencajn versiojn de la YunoHost-pakoj... plej probable pro malsukcesa aŭ parta ĝisdatigo.",
|
||||
"diagnosis_display_tip_web": "Vi povas iri al la sekcio Diagnozo (en la hejmekrano) por vidi la trovitajn problemojn.",
|
||||
"diagnosis_cache_still_valid": "(Kaŝmemoro ankoraŭ validas por {category} diagnozo. Ankoraŭ ne re-diagnoza!)",
|
||||
"diagnosis_cant_run_because_of_dep": "Ne eblas fari diagnozon por {category} dum estas gravaj problemoj rilataj al {dep}.",
|
||||
"diagnosis_display_tip_cli": "Vi povas aranĝi 'yunohost diagnosis show --issues' por aperigi la trovitajn problemojn.",
|
||||
"diagnosis_failed_for_category": "Diagnozo malsukcesis por kategorio '{category}': {error}"
|
||||
}
|
||||
|
|
|
@ -638,5 +638,25 @@
|
|||
"permission_currently_allowed_for_visitors": "Este permiso se concede actualmente a los visitantes además de otros grupos. Probablemente quiere o eliminar el permiso de «visitors» o eliminar los otros grupos a los que está otorgado actualmente.",
|
||||
"permission_currently_allowed_for_all_users": "Este permiso se concede actualmente a todos los usuarios además de los otros grupos. Probablemente quiere o eliminar el permiso de «all_users» o eliminar los otros grupos a los que está otorgado actualmente.",
|
||||
"permission_require_account": "El permiso {permission} solo tiene sentido para usuarios con una cuenta y, por lo tanto, no se puede activar para visitantes.",
|
||||
"app_remove_after_failed_install": "Eliminando la aplicación tras el fallo de instalación…"
|
||||
"app_remove_after_failed_install": "Eliminando la aplicación tras el fallo de instalación…",
|
||||
"diagnosis_basesystem_host": "El servidor está ejecutando Debian {debian_version}.",
|
||||
"diagnosis_basesystem_kernel": "El servidor está ejecutando el núcleo de Linux {kernel_version}",
|
||||
"diagnosis_basesystem_ynh_single_version": "{0} versión: {1} ({2})",
|
||||
"diagnosis_basesystem_ynh_main_version": "El servidor está ejecutando YunoHost {main_version} ({repo})",
|
||||
"diagnosis_basesystem_ynh_inconsistent_versions": "Está ejecutando versiones incoherentes de los paquetes de YunoHost... probablemente por una actualización errónea o parcial.",
|
||||
"diagnosis_failed_for_category": "Diagnóstico fallido para la categoría «{category}» : {error}",
|
||||
"diagnosis_cache_still_valid": "(Caché aún válida para el diagnóstico de {category}. ¡Aún no se ha rediagnosticado!)",
|
||||
"diagnosis_found_errors_and_warnings": "¡Encontrado(s) error(es) significativo(s) {errors} (y aviso(s) {warnings}) relacionado(s) con {category}!",
|
||||
"diagnosis_display_tip_web": "Puede ir a la sección de diagnóstico (en la pantalla principal) para ver los problemas encontrados.",
|
||||
"diagnosis_display_tip_cli": "Puede ejecutar «yunohost diagnosis show --issues» para mostrar los problemas encontrados.",
|
||||
"apps_catalog_init_success": "¡Sistema de catálogo de aplicaciones inicializado!",
|
||||
"apps_catalog_updating": "Actualizando catálogo de aplicaciones...",
|
||||
"apps_catalog_failed_to_download": "No se pudo descargar el catálogo de aplicaciones {apps_catalog}: {error}",
|
||||
"apps_catalog_obsolete_cache": "La caché del catálogo de aplicaciones está vacía u obsoleta.",
|
||||
"apps_catalog_update_success": "¡El catálogo de aplicaciones ha sido actualizado!",
|
||||
"diagnosis_cant_run_because_of_dep": "No se puede ejecutar el diagnóstico para {category} mientras haya problemas importantes relacionados con {dep}.",
|
||||
"diagnosis_ignored_issues": "(+ {nb_ignored} problema(s) ignorado(s))",
|
||||
"diagnosis_found_errors": "¡Encontrado(s) error(es) significativo(s) {errors} relacionado(s) con {category}!",
|
||||
"diagnosis_found_warnings": "Encontrado elemento(s) {warnings} que puede(n) ser mejorado(s) para {category}.",
|
||||
"diagnosis_everything_ok": "¡Todo se ve bien para {category}!"
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
"domain_created": "Le domaine a été créé",
|
||||
"domain_creation_failed": "Impossible de créer le domaine {domain}: {error}",
|
||||
"domain_deleted": "Le domaine a été supprimé",
|
||||
"domain_deletion_failed": "Impossible de supprimer le domaine {domain}: {error}",
|
||||
"domain_deletion_failed": "Impossible de supprimer le domaine {domain}:{error}",
|
||||
"domain_dyndns_already_subscribed": "Vous avez déjà souscris à un domaine DynDNS",
|
||||
"domain_dyndns_invalid": "Domaine incorrect pour un usage avec DynDNS",
|
||||
"domain_dyndns_root_unknown": "Domaine DynDNS principal inconnu",
|
||||
|
@ -270,7 +270,7 @@
|
|||
"ldap_init_failed_to_create_admin": "L’initialisation de l'annuaire LDAP n’a pas réussi à créer l’utilisateur admin",
|
||||
"ssowat_persistent_conf_read_error": "Impossible de lire la configuration persistante de SSOwat : {error:s}. Modifiez le fichier /etc/ssowat/conf.json.persistent pour réparer la syntaxe JSON",
|
||||
"ssowat_persistent_conf_write_error": "Impossible de sauvegarder de la configuration persistante de SSOwat : {error:s}. Modifiez le fichier /etc/ssowat/conf.json.persistent pour réparer la syntaxe JSON",
|
||||
"domain_cannot_remove_main": "Impossible de supprimer le domaine principal. Définissez d'abord un nouveau domaine principal",
|
||||
"domain_cannot_remove_main": "Vous ne pouvez pas supprimer '{domain: s}' car il s'agit du domaine principal. Vous devez d'abord définir un autre domaine comme domaine principal à l'aide de 'yunohost domain main-domain -n <another-domain>', voici la liste des domaines candidats. : {other_domains: s}",
|
||||
"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 courriel Dovecot doit être démarré, si vous souhaitez voir l’espace disque occupé par la messagerie",
|
||||
|
@ -394,7 +394,7 @@
|
|||
"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 mal passé pendant la mise à niveau principale : le système est toujours sur Debian Jessie !? Pour investiguer sur le problème, veuillez regarder les journaux {log}:s …",
|
||||
"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\nEn outre, 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 des applications possiblement 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 comme « fonctionnelles ». En conséquence, nous ne pouvons pas garantir qu’elles fonctionneront après la mise à niveau : {problematic_apps}",
|
||||
"migration_0003_problematic_apps_warning": "Veuillez noter que les applications installées potentiellement problématiques suivantes ont été détectées. Il semble que celles-ci n'ont pas été installées à partir d'un catalogue d'applications, ou ne sont pas marquées comme \"working \". Par conséquent, il ne peut pas être garanti qu'ils fonctionneront toujours 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.",
|
||||
"migrations_to_be_ran_manually": "La migration {id} doit être lancée manuellement. Veuillez aller dans Outils > Migrations dans l’interface admin, ou lancer `yunohost tools migrations migrate`.",
|
||||
|
@ -541,7 +541,7 @@
|
|||
"global_settings_setting_security_ssh_compatibility": "Compatibilité versus compromis sécuritaire pour le serveur SSH. Affecte les cryptogrammes (et d'autres aspects liés à la sécurité)",
|
||||
"global_settings_setting_security_postfix_compatibility": "Compatibilité versus compromis sécuritaire pour le serveur Postfix. Affecte les cryptogrammes (et d'autres aspects liés à la sécurité)",
|
||||
"migration_description_0009_decouple_regenconf_from_services": "Dissocier le mécanisme « regen-conf » des services",
|
||||
"migration_description_0010_migrate_to_apps_json": "Supprimer les listes d'applications obsolètes et utiliser la nouvelle liste unifiée 'apps.json' à la place",
|
||||
"migration_description_0010_migrate_to_apps_json": "Supprimez les catalogues d'applications obsolètes et utilisez à la place la nouvelle liste unifiée 'apps.json' (obsolète, remplacée par la migration 13).",
|
||||
"regenconf_file_kept_back": "Le fichier de configuration '{conf}' devait être supprimé par « regen-conf » (catégorie {category}) mais a été conservé.",
|
||||
"regenconf_updated": "La configuration a été mise à jour pour la catégorie '{category}'",
|
||||
"regenconf_would_be_updated": "La configuration aurait dû être mise à jour pour la catégorie '{category}'",
|
||||
|
@ -625,7 +625,7 @@
|
|||
"migrations_running_forward": "Exécution de la migration {id}…",
|
||||
"migrations_success_forward": "Migration {id} terminée",
|
||||
"need_define_permission_before": "Redéfinissez l'autorisation à l'aide de 'yunohost user permission add -u USER' avant de supprimer un groupe autorisé",
|
||||
"operation_interrupted": "L'opération a-t-elle été interrompue manuellement ?",
|
||||
"operation_interrupted": "L'opération a été interrompue manuellement ?",
|
||||
"permission_already_clear": "L'autorisation '{permission: s}' est déjà vide pour l'application {app: s}",
|
||||
"permission_already_exist": "L'autorisation '{permission}' existe déjà",
|
||||
"permission_created": "Permission '{permission:s}' créée",
|
||||
|
@ -665,5 +665,81 @@
|
|||
"app_install_failed": "Impossible d'installer {app}: {error}",
|
||||
"app_install_script_failed": "Une erreur est survenue dans le script d'installation de l'application",
|
||||
"permission_require_account": "Permission {permission} n'a de sens que pour les utilisateurs ayant un compte et ne peut donc pas être activé pour les visiteurs.",
|
||||
"app_remove_after_failed_install": "Supprimer l'application après l'échec de l'installation…"
|
||||
"app_remove_after_failed_install": "Supprimer l'application après l'échec de l'installation…",
|
||||
"diagnosis_display_tip_web": "Vous pouvez aller à la section Diagnostic (dans l'écran d'accueil) pour voir les problèmes rencontrés.",
|
||||
"diagnosis_cant_run_because_of_dep": "Impossible d'exécuter le diagnostic pour {category} alors qu'il existe des problèmes importants liés à {dep}.",
|
||||
"diagnosis_found_errors": "Trouvé {errors} problème(s) significatif(s) lié(s) à {category} !",
|
||||
"diagnosis_found_errors_and_warnings": "Trouvé {errors} problème(s) significatif(s) (et {warnings} (avertissement(s)) en relation avec {category} !",
|
||||
"diagnosis_ip_not_connected_at_all": "Le serveur ne semble pas du tout connecté à Internet !?",
|
||||
"diagnosis_ip_weird_resolvconf": "La résolution DNS semble fonctionner, mais soyer prudent en utilisant un fichier /etc/resolv.conf personnalisé.",
|
||||
"diagnosis_ip_weird_resolvconf_details": "Au lieu de cela, ce fichier devrait être un lien symbolique vers /etc/resolvconf/run/resolv.conf lui-même pointant vers 127.0.0.1 (dnsmasq). Les résolveurs réels doivent être configurés via /etc/resolv.dnsmasq.conf.",
|
||||
"diagnosis_dns_missing_record": "Selon la configuration DNS recommandée, vous devez ajouter un enregistrement DNS de type {0}, nom {1} et valeur {2}",
|
||||
"diagnosis_diskusage_ok": "Le stockage {mountpoint} (sur le périphérique {device}) a toujours {espace libre {free_abs_GB} GB ({free_percent}%) !",
|
||||
"diagnosis_ram_ok": "Le système dispose toujours de {available_abs_MB} MB ({available_percent}%) de RAM sur {total_abs_MB} MB.",
|
||||
"diagnosis_regenconf_allgood": "Tous les fichiers de configuration sont conformes à la configuration recommandée !",
|
||||
"diagnosis_security_vulnerable_to_meltdown": "Vous semblez vulnérable à la vulnérabilité de sécurité critique de Meltdown",
|
||||
"diagnosis_basesystem_host": "Le serveur exécute Debian {debian_version}.",
|
||||
"diagnosis_basesystem_kernel": "Le serveur exécute le noyau Linux {kernel_version}",
|
||||
"diagnosis_basesystem_ynh_single_version": "{0} version: {1} ({2})",
|
||||
"diagnosis_basesystem_ynh_main_version": "Le serveur exécute YunoHost {main_version} ({repo})",
|
||||
"diagnosis_basesystem_ynh_inconsistent_versions": "Vous exécutez des versions incohérentes des packages YunoHost ... probablement à cause d'une mise à niveau partielle ou échouée.",
|
||||
"diagnosis_display_tip_cli": "Vous pouvez exécuter 'yunohost diagnosis show --issues' pour afficher les problèmes détectés.",
|
||||
"diagnosis_failed_for_category": "Échec du diagnostic pour la catégorie '{category}' : {error}",
|
||||
"diagnosis_cache_still_valid": "(Le cache est toujours valide pour le diagnostic {category}. Pas re-diagnostiquer pour le moment!)",
|
||||
"diagnosis_ignored_issues": "(+ {nb_ignored} questions ignorée(s))",
|
||||
"diagnosis_found_warnings": "Trouvé {warnings} objet(s) pouvant être amélioré(s) pour {category}.",
|
||||
"diagnosis_everything_ok": "Tout semble bien pour {category} !",
|
||||
"diagnosis_failed": "Impossible d'extraire le résultat du diagnostic pour la catégorie '{category}': {error}",
|
||||
"diagnosis_ip_connected_ipv4": "Le serveur est connecté à Internet via IPv4 !",
|
||||
"diagnosis_ip_no_ipv4": "Le serveur ne dispose pas d’une adresse IPv4 active.",
|
||||
"diagnosis_ip_connected_ipv6": "Le serveur est connecté à Internet via IPv6 !",
|
||||
"diagnosis_ip_no_ipv6": "Le serveur ne dispose pas d'une adresse IPv6 active.",
|
||||
"diagnosis_ip_dnsresolution_working": "La résolution de nom de domaine fonctionne !",
|
||||
"diagnosis_ip_broken_dnsresolution": "La résolution du nom de domaine semble interrompue pour une raison quelconque ... Un pare-feu bloque-t-il les requêtes DNS ?",
|
||||
"diagnosis_ip_broken_resolvconf": "La résolution du nom de domaine semble cassée sur votre serveur, ce qui semble lié au fait que /etc/resolv.conf ne pointe pas vers 127.0.0.1.",
|
||||
"diagnosis_dns_good_conf": "Bonne configuration DNS pour le domaine {domain} (catégorie {category})",
|
||||
"diagnosis_dns_bad_conf": "Configuration DNS incorrecte/manquante pour le domaine {domain} (catégorie {category})",
|
||||
"diagnosis_dns_discrepancy": "Selon la configuration DNS recommandée, la valeur de l'enregistrement DNS de type {0} et nom {1} doit être {2} et non {3}.",
|
||||
"diagnosis_services_bad_status": "Le service {service} est {status} :/",
|
||||
"diagnosis_services_good_status": "Le service {service} est {status} comme prévu !",
|
||||
"diagnosis_diskusage_verylow": "Le stockage {mountpoint} (sur le périphérique {device}) ne dispose que de {free_abs_GB} Go ({free_percent}%). Vous devriez vraiment envisager de nettoyer un peu d'espace.",
|
||||
"diagnosis_diskusage_low": "Le stockage {mountpoint} (sur le périphérique {device}) ne dispose que de {free_abs_GB} Go ({free_percent}%). Faites attention.",
|
||||
"diagnosis_ram_verylow": "Le système ne dispose plus que de {available_abs_MB} MB ({available_percent}%)! (sur {total_abs_MB} Mo)",
|
||||
"diagnosis_ram_low": "Le système n'a plus de {available_abs_MB} MB ({available_percent}%) RAM sur {total_abs_MB} MB. Faites attention.",
|
||||
"diagnosis_swap_none": "Le système n'a aucun échange. Vous devez envisager d’ajouter au moins 256 Mo de swap pour éviter les situations où le système manque de mémoire.",
|
||||
"diagnosis_swap_notsomuch": "Le système ne dispose que de {total_MB} Mo de swap. Vous devez envisager d'avoir au moins 256 Mo pour éviter les situations où le système manque de mémoire.",
|
||||
"diagnosis_swap_ok": "Le système dispose de {total_MB} Mo de swap !",
|
||||
"diagnosis_regenconf_manually_modified": "Le fichier de configuration {file} a été modifié manuellement.",
|
||||
"diagnosis_regenconf_manually_modified_debian": "Le fichier de configuration {file} a été modifié manuellement par rapport à celui par défaut de Debian.",
|
||||
"diagnosis_regenconf_manually_modified_details": "C'est probablement OK tant que vous savez ce que vous faites;) !",
|
||||
"diagnosis_regenconf_manually_modified_debian_details": "Cela peut probablement être OK, mais il faut garder un œil dessus ...",
|
||||
"diagnosis_regenconf_nginx_conf_broken": "La configuration de nginx semble être cassée !",
|
||||
"diagnosis_security_all_good": "Aucune vulnérabilité de sécurité critique n'a été trouvée.",
|
||||
"apps_catalog_init_success": "Système de catalogue d'applications initialisé !",
|
||||
"apps_catalog_failed_to_download": "Impossible de télécharger le catalogue des applications {apps_catalog}:{error}",
|
||||
"diagnosis_mail_ougoing_port_25_blocked": "Le port sortant 25 semble être bloqué. Vous devriez essayer de le débloquer dans le panneau de configuration de votre fournisseur de services Internet (ou hébergeur). En attendant, le serveur ne pourra pas envoyer de courrier électronique à d'autres serveurs.",
|
||||
"domain_cannot_remove_main_add_new_one": "Vous ne pouvez pas supprimer '{domain:s}' car il s'agit du domaine principal et de votre seul domaine. Vous devez d'abord ajouter un autre domaine à l'aide de 'yunohost domain add <another-domain.com>', puis définir comme domaine principal à l'aide de ' yunohost domain main-domain -n <nomd'un-autre-domaine.com>' et vous pouvez ensuite supprimer le domaine '{domaine: s}' à l'aide de 'yunohost domain remove {domain:s}'.'",
|
||||
"diagnosis_security_vulnerable_to_meltdown_details": "Pour résoudre ce problème, vous devez mettre à niveau votre système et redémarrer pour charger le nouveau noyau Linux (ou contacter votre fournisseur de serveur si cela ne fonctionne pas). Voir https://meltdownattack.com/ pour plus d'informations.",
|
||||
"diagnosis_description_basesystem": "Système de base",
|
||||
"diagnosis_description_ip": "Connectivité Internet",
|
||||
"diagnosis_description_dnsrecords": "Enregistrements DNS",
|
||||
"diagnosis_description_services": "Vérification de l'état des services",
|
||||
"diagnosis_description_systemresources": "Ressources système",
|
||||
"diagnosis_description_ports": "Exposition des ports",
|
||||
"diagnosis_description_http": "Exposition HTTP",
|
||||
"diagnosis_description_regenconf": "Configurations système",
|
||||
"diagnosis_description_security": "Contrôles de sécurité",
|
||||
"diagnosis_ports_could_not_diagnose": "Impossible de diagnostiquer si les ports sont accessibles de l'extérieur. Erreur: {error}",
|
||||
"apps_catalog_updating": "Mise à jour du catalogue d'applications...",
|
||||
"apps_catalog_obsolete_cache": "Le cache du catalogue d'applications est vide ou obsolète.",
|
||||
"apps_catalog_update_success": "Le catalogue des applications a été mis à jour !",
|
||||
"diagnosis_mail_ougoing_port_25_ok": "Le port sortant 25 n'est pas bloqué et le courrier électronique peut être envoyé à d'autres serveurs.",
|
||||
"diagnosis_description_mail": "Email",
|
||||
"diagnosis_ports_unreachable": "Le port {port} n'est pas accessible de l'extérieur.",
|
||||
"diagnosis_ports_ok": "Le port {port} est accessible de l'extérieur.",
|
||||
"diagnosis_http_could_not_diagnose": "Impossible de diagnostiquer si le domaine est accessible de l'extérieur. Erreur: {error}",
|
||||
"diagnosis_http_ok": "Le domaine {domain} est accessible de l'extérieur.",
|
||||
"diagnosis_http_unreachable": "Le domaine {domain} est inaccessible via HTTP de l'extérieur.",
|
||||
"diagnosis_unknown_categories": "Les catégories suivantes sont inconnues: {categories}",
|
||||
"migration_description_0013_futureproof_apps_catalog_system": "Migrer vers le nouveau système de catalogue d'applications à l'épreuve du temps"
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"app_already_installed": "{app:s} es ja installat",
|
||||
"app_already_up_to_date": "{app:s} es ja a jorn",
|
||||
"installation_complete": "Installacion acabada",
|
||||
"app_id_invalid": "Id d’aplicacion incorrècte",
|
||||
"app_id_invalid": "ID d’aplicacion incorrècte",
|
||||
"app_install_files_invalid": "Fichièrs d’installacion incorrèctes",
|
||||
"app_no_upgrade": "Pas cap d’aplicacion d’actualizar",
|
||||
"app_not_correctly_installed": "{app:s} sembla pas ben installat",
|
||||
|
@ -41,15 +41,15 @@
|
|||
"backup_archive_name_unknown": "L’archiu local de salvagarda apelat « {name:s} » es desconegut",
|
||||
"action_invalid": "Accion « {action:s} » incorrècta",
|
||||
"app_argument_choice_invalid": "Causida invalida pel paramètre « {name:s} », cal que siá un de {choices:s}",
|
||||
"app_argument_invalid": "Valor invalida pel paramètre « {name:s} » : {error:s}",
|
||||
"app_argument_invalid": "Causissètz una valor invalida pel paramètre « {name:s} » : {error:s}",
|
||||
"app_argument_required": "Lo paramètre « {name:s} » es requesit",
|
||||
"app_change_url_failed_nginx_reload": "La reaviada de nginx a fracassat. Vaquí la sortida de « nginx -t » :\n{nginx_errors:s}",
|
||||
"app_change_url_failed_nginx_reload": "Reaviada de NGINX impossibla. Vaquí la sortida de « nginx -t » :\n{nginx_errors:s}",
|
||||
"app_change_url_identical_domains": "L’ancian e lo novèl coble domeni/camin son identics per {domain:s}{path:s}, pas res a far.",
|
||||
"app_change_url_success": "L’URL de l’aplicacion {app:s} a cambiat per {domain:s}{path:s}",
|
||||
"app_change_url_success": "L’URL de l’aplicacion {app:s} es ara {domain:s}{path:s}",
|
||||
"app_checkurl_is_deprecated": "Packagers /!\\ ’app checkurl’ es obsolèt ! Utilizatz ’app register-url’ a la plaça !",
|
||||
"app_extraction_failed": "Extraccion dels fichièrs d’installacion impossibla",
|
||||
"app_incompatible": "L’aplicacion {app} es pas compatibla amb vòstra version de YunoHost",
|
||||
"app_location_already_used": "L’aplicacion « {app} » es ja installada a aqueste emplaçament ({path})",
|
||||
"app_location_already_used": "L’aplicacion « {app} » es ja installada dins ({path})",
|
||||
"app_manifest_invalid": "Manifest d’aplicacion incorrècte : {error}",
|
||||
"app_package_need_update": "Lo paquet de l’aplicacion {app} deu èsser actualizat per poder seguir los cambiaments de YunoHost",
|
||||
"app_requirements_checking": "Verificacion dels paquets requesits per {app}…",
|
||||
|
@ -612,5 +612,91 @@
|
|||
"migrations_must_provide_explicit_targets": "Devètz fornir una cibla explicita quand utilizatz using --skip o --force-rerun",
|
||||
"migrations_exclusive_options": "--auto, --skip, e --force-rerun son las opcions exclusivas.",
|
||||
"migrations_failed_to_load_migration": "Cargament impossible de la migracion {id} : {error}",
|
||||
"migrations_already_ran": "Aquelas migracions s’executèron ja : {ids}"
|
||||
"migrations_already_ran": "Aquelas migracions s’executèron ja : {ids}",
|
||||
"diagnosis_basesystem_ynh_main_version": "Lo servidor fonciona amb YunoHost {main_version} ({repo})",
|
||||
"migrations_dependencies_not_satisfied": "Executatz aquestas migracions : « {dependencies_id} », abans la migracion {id}.",
|
||||
"migrations_no_such_migration": "I a pas cap de migracion apelada « {id} »",
|
||||
"migrations_not_pending_cant_skip": "Aquestas migracions son pas en espèra, las podètz pas doncas ignorar : {ids}",
|
||||
"app_action_broke_system": "Aquesta accion sembla aver copat de servicis importants : {services}",
|
||||
"diagnosis_display_tip_web": "Podètz anar a la seccion Diagnostic (dins l’ecran d’acuèlh) per veire los problèmas trobats.",
|
||||
"diagnosis_ip_no_ipv6": "Lo servidor a pas d’adreça IPv5 activa.",
|
||||
"diagnosis_ip_not_connected_at_all": "Lo servidor sembla pas connectat a Internet ?!",
|
||||
"diagnosis_security_all_good": "Cap de vulnerabilitat de seguretat critica pas trobada.",
|
||||
"diagnosis_description_regenconf": "Configuracion sistèma",
|
||||
"diagnosis_http_ok": "Lo domeni {domain} accessible de l’exterior.",
|
||||
"app_full_domain_unavailable": "Aquesta aplicacion a d’èsser installada sul seu pròpri domeni, mas i a d’autras aplicacions installadas sus aqueste domeni « {domain} ». Podètz utilizar allòc un josdomeni dedicat a aquesta aplicacion.",
|
||||
"app_upgrade_stopped": "L’actualizacion de totas las aplicacions s‘es arrestada per evitar de possibles damatges pr’amor qu’èra pas possible d’actualizar una aplicacion",
|
||||
"diagnosis_dns_bad_conf": "Configuracion DNS incorrècta o inexistenta pel domeni {domain} (categoria {category})",
|
||||
"diagnosis_ram_verylow": "Lo sistèma a solament {available_abs_MB} Mo ({available_percent}%) de memòria RAM disponibla ! (d’un total de {total_abs_MB} MB)",
|
||||
"diagnosis_ram_ok": "Lo sistèma a encara {available_abs_MB} Mo ({available_percent}%) de memòria RAM disponibla d’un total de {total_abs_MB} MB).",
|
||||
"permission_already_allowed": "Lo grop « {group} » a ja la permission « {permission} » activada",
|
||||
"permission_already_disallowed": "Lo grop « {group} » a ja la permission « {permission} » desactivada",
|
||||
"permission_cannot_remove_main": "La supression d’una permission màger es pas autorizada",
|
||||
"log_permission_url": "Actualizacion de l’URL ligada a la permission « {} »",
|
||||
"app_install_failed": "Installacion impossibla de {app} : {error}",
|
||||
"app_install_script_failed": "Una error s’es producha en installar lo script de l’aplicacion",
|
||||
"migration_0011_failed_to_remove_stale_object": "Supression impossibla d’un objècte obsolèt {dn} : {error}",
|
||||
"apps_already_up_to_date": "Totas las aplicacions son ja al jorn",
|
||||
"app_remove_after_failed_install": "Supression de l’aplicacion aprèp fracàs de l’installacion…",
|
||||
"group_already_exist": "Lo grop {group} existís ja",
|
||||
"group_already_exist_on_system": "Lo grop {group} existís ja dins lo sistèma de grops",
|
||||
"group_user_not_in_group": "L’utilizaire {user} es pas dins lo grop {group}",
|
||||
"log_user_permission_reset": "Restablir la permission « {} »",
|
||||
"user_already_exists": "L’utilizaire {user} existís ja",
|
||||
"diagnosis_basesystem_host": "Lo servidor fonciona amb Debian {debian_version}.",
|
||||
"diagnosis_basesystem_kernel": "Lo servidor fonciona amb lo nuclèu Linuxl {kernel_version}",
|
||||
"diagnosis_basesystem_ynh_single_version": "{0} version : {1} ({2})",
|
||||
"diagnosis_basesystem_ynh_inconsistent_versions": "Utilizatz de versions inconsistentas dels paquets de YunoHost… probablament a causa d'una actualizacion fracassada o parciala.",
|
||||
"diagnosis_display_tip_cli": "Podètz executar « yunohost diagnosis show --issues » per mostrar las errors trobadas.",
|
||||
"diagnosis_ignored_issues": "(+ {nb_ignored} problèma(es) ignorat(s))",
|
||||
"diagnosis_everything_ok": "Tot sembla corrècte per {category} !",
|
||||
"diagnosis_ip_connected_ipv4": "Lo servidor es connectat a Internet via IPv4 !",
|
||||
"diagnosis_ip_no_ipv4": "Lo servidor a pas d’adreça IPv4 activa.",
|
||||
"diagnosis_ip_connected_ipv6": "Lo servidor es connectat a Internet via IPv6 !",
|
||||
"diagnosis_ip_dnsresolution_working": "La resolucion del nom de domeni fonciona !",
|
||||
"diagnosis_dns_good_conf": "Bona configuracion DNS pel domeni {domain} (categoria {category})",
|
||||
"diagnosis_failed_for_category": "Lo diagnostic a reüssit per la categoria « {category} » : {error}",
|
||||
"diagnosis_cache_still_valid": "(Memòria cache totjorn valida pel diagnostic {category}. Cap d’autre diagnostic pel moment !)",
|
||||
"diagnosis_found_errors": "{errors} errors importantas trobadas ligadas a {category} !",
|
||||
"diagnosis_services_good_status": "Lo servici {service} es {status} coma previst !",
|
||||
"diagnosis_services_bad_status": "Lo servici {service} es {status} :/",
|
||||
"diagnosis_swap_ok": "Lo sistèma a {total_MB} MB d’escambi !",
|
||||
"diagnosis_regenconf_allgood": "Totes los fichièrs de configuracion son confòrmes a la configuracion recomandada !",
|
||||
"diagnosis_regenconf_manually_modified": "Lo fichièr de configuracion {file} foguèt modificat manualament.",
|
||||
"diagnosis_regenconf_manually_modified_details": "Es probablament bon tan que sabètz çò que fasètz ;) !",
|
||||
"diagnosis_regenconf_nginx_conf_broken": "La configuracion de nginx sembla èsser copada !",
|
||||
"diagnosis_security_vulnerable_to_meltdown": "Semblatz èsser vulnerable a la vulnerabilitat de seguretat critica de Meltdown",
|
||||
"diagnosis_description_basesystem": "Sistèma de basa",
|
||||
"diagnosis_description_ip": "Connectivitat Internet",
|
||||
"diagnosis_description_dnsrecords": "Enregistraments DNS",
|
||||
"diagnosis_description_services": "Verificacion d’estat de servicis",
|
||||
"diagnosis_description_systemresources": "Resorgas sistèma",
|
||||
"diagnosis_description_ports": "Exposicion dels pòrts",
|
||||
"diagnosis_description_http": "Exposicion HTTP",
|
||||
"diagnosis_description_security": "Verificacion de seguretat",
|
||||
"diagnosis_ports_unreachable": "Lo pòrt {port} es pas accessible de l’exterior.",
|
||||
"diagnosis_ports_ok": "Lo pòrt {port} es accessible de l’exterior.",
|
||||
"diagnosis_http_unreachable": "Lo domeni {domain} es pas accessible via HTTP de l’exterior.",
|
||||
"diagnosis_unknown_categories": "La categorias seguentas son desconegudas : {categories}",
|
||||
"diagnosis_ram_low": "Lo sistèma a {available_abs_MB} Mo ({available_percent}%) de memòria RAM disponibla d’un total de {total_abs_MB} MB). Atencion.",
|
||||
"diagnosis_regenconf_manually_modified_debian": "Lo fichier de configuracion {file} foguèt modificat manualament respècte al fichièr per defaut de Debian.",
|
||||
"log_permission_create": "Crear la permission « {} »",
|
||||
"log_permission_delete": "Suprimir la permission « {} »",
|
||||
"log_user_group_create": "Crear lo grop « {} »",
|
||||
"log_user_permission_update": "Actualizacion dels accèsses per la permission « {} »",
|
||||
"operation_interrupted": "L’operacion es estada interrompuda manualament ?",
|
||||
"group_cannot_be_edited": "Lo grop « {group} » pòt pas èsser modificat manualament.",
|
||||
"group_cannot_be_deleted": "Lo grop « {group} » pòt pas èsser suprimit manualament.",
|
||||
"diagnosis_found_warnings": "Trobat {warnings} element(s) que se poirián melhorar per {category}.",
|
||||
"diagnosis_dns_missing_record": "Segon la configuracion DNS recomandada, vos calriá ajustar un enregistrament DNS de tipe {0}, nom {1} e valor {2}",
|
||||
"diagnosis_dns_discrepancy": "Segon la configuracion DNS recomandada, la valor per l’enregistrament DNS de tipe {0} e nom {1} deuriá èsser {2} allòc de {3}.",
|
||||
"diagnosis_regenconf_manually_modified_debian_details": "Es pas problematic, mas car téner d’agacher...",
|
||||
"diagnosis_ports_could_not_diagnose": "Impossible de diagnosticar se los pòrts son accessibles de l’exterior. Error : {error}",
|
||||
"diagnosis_http_could_not_diagnose": "Impossible de diagnosticar se lo domeni es accessible de l’exterior. Error : {error}",
|
||||
"apps_catalog_updating": "Actualizacion del catalòg d’aplicacion…",
|
||||
"apps_catalog_failed_to_download": "Telecargament impossible del catalòg d’aplicacions {apps_catalog} : {error}",
|
||||
"apps_catalog_obsolete_cache": "La memòria cache del catalòg d’aplicacion es voida o obsolèta.",
|
||||
"apps_catalog_update_success": "Lo catalòg d’aplicacions es a jorn !",
|
||||
"diagnosis_mail_ougoing_port_25_ok": "Lo pòrt de sortida 25 es pas blocat e lo corrièr electronic pòt partir als autres servidors.",
|
||||
"diagnosis_description_mail": "Corrièl"
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ from datetime import datetime
|
|||
from moulinette import msignals, m18n, msettings
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.network import download_json
|
||||
from moulinette.utils.filesystem import read_json, read_toml, read_yaml, write_to_file, write_to_json, write_to_yaml, chmod, chown, mkdir
|
||||
from moulinette.utils.filesystem import read_file, read_json, read_toml, read_yaml, write_to_file, write_to_json, write_to_yaml, chmod, chown, mkdir
|
||||
|
||||
from yunohost.service import service_log, service_status, _run_service_command
|
||||
from yunohost.utils import packages
|
||||
|
@ -136,6 +136,7 @@ def app_list(filter=None, raw=False, installed=False, with_backup=False):
|
|||
|
||||
# dirty: we used to have manifest containing multi_instance value in form of a string
|
||||
# but we've switched to bool, this line ensure retrocompatibility
|
||||
|
||||
app_info_dict["manifest"]["multi_instance"] = is_true(app_info_dict["manifest"].get("multi_instance", False))
|
||||
|
||||
list_dict[app_id] = app_info_dict
|
||||
|
@ -529,6 +530,9 @@ def app_upgrade(app=[], url=None, file=None):
|
|||
operation_logger = OperationLogger('app_upgrade', related_to, env=env_dict)
|
||||
operation_logger.start()
|
||||
|
||||
# Attempt to patch legacy helpers ...
|
||||
_patch_legacy_helpers(extracted_app_folder)
|
||||
|
||||
# Apply dirty patch to make php5 apps compatible with php7
|
||||
_patch_php5(extracted_app_folder)
|
||||
|
||||
|
@ -546,6 +550,8 @@ def app_upgrade(app=[], url=None, file=None):
|
|||
error = m18n.n('app_upgrade_script_failed')
|
||||
logger.exception(m18n.n("app_upgrade_failed", app=app_instance_name, error=error))
|
||||
failure_message_with_debug_instructions = operation_logger.error(error)
|
||||
if msettings.get('interface') != 'api':
|
||||
dump_app_log_extract_for_debugging(operation_logger)
|
||||
# Script got manually interrupted ... N.B. : KeyboardInterrupt does not inherit from Exception
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
upgrade_retcode = -1
|
||||
|
@ -759,6 +765,9 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
|
|||
}
|
||||
_set_app_settings(app_instance_name, app_settings)
|
||||
|
||||
# Attempt to patch legacy helpers ...
|
||||
_patch_legacy_helpers(extracted_app_folder)
|
||||
|
||||
# Apply dirty patch to make php5 apps compatible with php7
|
||||
_patch_php5(extracted_app_folder)
|
||||
|
||||
|
@ -794,6 +803,8 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
|
|||
error = m18n.n('app_install_script_failed')
|
||||
logger.exception(m18n.n("app_install_failed", app=app_id, error=error))
|
||||
failure_message_with_debug_instructions = operation_logger.error(error)
|
||||
if msettings.get('interface') != 'api':
|
||||
dump_app_log_extract_for_debugging(operation_logger)
|
||||
# Script got manually interrupted ... N.B. : KeyboardInterrupt does not inherit from Exception
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
error = m18n.n('operation_interrupted')
|
||||
|
@ -906,6 +917,33 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
|
|||
hook_callback('post_app_install', args=args_list, env=env_dict)
|
||||
|
||||
|
||||
def dump_app_log_extract_for_debugging(operation_logger):
|
||||
|
||||
with open(operation_logger.log_path, "r") as f:
|
||||
lines = f.readlines()
|
||||
|
||||
lines_to_display = []
|
||||
for line in lines:
|
||||
|
||||
if not ": " in line.strip():
|
||||
continue
|
||||
|
||||
# A line typically looks like
|
||||
# 2019-10-19 16:10:27,611: DEBUG - + mysql -u piwigo --password=********** -B piwigo
|
||||
# And we just want the part starting by "DEBUG - "
|
||||
line = line.strip().split(": ", 1)[1]
|
||||
lines_to_display.append(line)
|
||||
|
||||
if line.endswith("+ ynh_exit_properly"):
|
||||
break
|
||||
elif len(lines_to_display) > 20:
|
||||
lines_to_display.pop(0)
|
||||
|
||||
logger.warning("Here's an extract of the logs before the crash. It might help debugging the error:")
|
||||
for line in lines_to_display:
|
||||
logger.info(line)
|
||||
|
||||
|
||||
def _migrate_legacy_permissions(app):
|
||||
|
||||
from yunohost.permission import user_permission_list, user_permission_update
|
||||
|
@ -960,6 +998,9 @@ def app_remove(operation_logger, app):
|
|||
except Exception:
|
||||
pass
|
||||
|
||||
# Attempt to patch legacy helpers ...
|
||||
_patch_legacy_helpers(app_setting_path)
|
||||
|
||||
# Apply dirty patch to make php5 apps compatible with php7 (e.g. the remove
|
||||
# script might date back from jessie install)
|
||||
_patch_php5(app_setting_path)
|
||||
|
@ -1161,24 +1202,6 @@ def app_setting(app, key, value=None, delete=False):
|
|||
user_permission_update(app + ".main", remove="all_users", add="visitors")
|
||||
|
||||
|
||||
def app_checkport(port):
|
||||
"""
|
||||
Check availability of a local port
|
||||
|
||||
Keyword argument:
|
||||
port -- Port to check
|
||||
|
||||
"""
|
||||
|
||||
# This import cannot be moved on top of file because it create a recursive
|
||||
# import...
|
||||
from yunohost.tools import tools_port_available
|
||||
if tools_port_available(port):
|
||||
logger.success(m18n.n('port_available', port=int(port)))
|
||||
else:
|
||||
raise YunohostError('port_unavailable', port=int(port))
|
||||
|
||||
|
||||
def app_register_url(app, domain, path):
|
||||
"""
|
||||
Book/register a web path for a given app
|
||||
|
@ -1222,93 +1245,6 @@ def app_register_url(app, domain, path):
|
|||
app_setting(app, 'path', value=path)
|
||||
|
||||
|
||||
def app_checkurl(url, app=None):
|
||||
"""
|
||||
Check availability of a web path
|
||||
|
||||
Keyword argument:
|
||||
url -- Url to check
|
||||
app -- Write domain & path to app settings for further checks
|
||||
|
||||
"""
|
||||
|
||||
logger.error("Packagers /!\\ : 'app checkurl' is deprecated ! Please use the helper 'ynh_webpath_register' instead !")
|
||||
|
||||
from yunohost.domain import domain_list, _normalize_domain_path
|
||||
|
||||
if "https://" == url[:8]:
|
||||
url = url[8:]
|
||||
elif "http://" == url[:7]:
|
||||
url = url[7:]
|
||||
|
||||
if url[-1:] != '/':
|
||||
url = url + '/'
|
||||
|
||||
domain = url[:url.index('/')]
|
||||
path = url[url.index('/'):]
|
||||
installed = False
|
||||
|
||||
domain, path = _normalize_domain_path(domain, path)
|
||||
|
||||
apps_map = app_map(raw=True)
|
||||
|
||||
if domain not in domain_list()['domains']:
|
||||
raise YunohostError('domain_unknown')
|
||||
|
||||
if domain in apps_map:
|
||||
# Loop through apps
|
||||
for p, a in apps_map[domain].items():
|
||||
# Skip requested app checking
|
||||
if app is not None and a['id'] == app:
|
||||
installed = True
|
||||
continue
|
||||
if path == p:
|
||||
raise YunohostError('app_location_already_used', app=a["id"], path=path)
|
||||
# can't install "/a/b/" if "/a/" exists
|
||||
elif path.startswith(p) or p.startswith(path):
|
||||
raise YunohostError('app_location_install_failed', other_path=p, other_app=a['id'])
|
||||
|
||||
if app is not None and not installed:
|
||||
app_setting(app, 'domain', value=domain)
|
||||
app_setting(app, 'path', value=path)
|
||||
|
||||
|
||||
def app_initdb(user, password=None, db=None, sql=None):
|
||||
"""
|
||||
Create database and initialize it with optionnal attached script
|
||||
|
||||
Keyword argument:
|
||||
db -- DB name (user unless set)
|
||||
user -- Name of the DB user
|
||||
password -- Password of the DB (generated unless set)
|
||||
sql -- Initial SQL file
|
||||
|
||||
"""
|
||||
|
||||
logger.error("Packagers /!\\ : 'app initdb' is deprecated ! Please use the helper 'ynh_mysql_setup_db' instead !")
|
||||
|
||||
if db is None:
|
||||
db = user
|
||||
|
||||
return_pwd = False
|
||||
if password is None:
|
||||
password = random_password(12)
|
||||
return_pwd = True
|
||||
|
||||
mysql_root_pwd = open('/etc/yunohost/mysql').read().rstrip()
|
||||
mysql_command = 'mysql -u root -p%s -e "CREATE DATABASE %s ; GRANT ALL PRIVILEGES ON %s.* TO \'%s\'@localhost IDENTIFIED BY \'%s\';"' % (mysql_root_pwd, db, db, user, password)
|
||||
if os.system(mysql_command) != 0:
|
||||
raise YunohostError('mysql_db_creation_failed')
|
||||
if sql is not None:
|
||||
if os.system('mysql -u %s -p%s %s < %s' % (user, password, db, sql)) != 0:
|
||||
raise YunohostError('mysql_db_init_failed')
|
||||
|
||||
if return_pwd:
|
||||
return password
|
||||
|
||||
logger.success(m18n.n('mysql_db_initialized'))
|
||||
|
||||
|
||||
def app_ssowatconf():
|
||||
"""
|
||||
Regenerate SSOwat configuration file
|
||||
|
@ -2929,3 +2865,76 @@ def _patch_php5(app_folder):
|
|||
"-e 's@php5@php7.0@g' " \
|
||||
"%s" % filename
|
||||
os.system(c)
|
||||
|
||||
def _patch_legacy_helpers(app_folder):
|
||||
|
||||
files_to_patch = []
|
||||
files_to_patch.extend(glob.glob("%s/scripts/*" % app_folder))
|
||||
files_to_patch.extend(glob.glob("%s/scripts/.*" % app_folder))
|
||||
|
||||
stuff_to_replace = {
|
||||
# Replace
|
||||
# sudo yunohost app initdb $db_user -p $db_pwd
|
||||
# by
|
||||
# ynh_mysql_setup_db --db_user=$db_user --db_name=$db_user --db_pwd=$db_pwd
|
||||
"yunohost app initdb": (
|
||||
r"(sudo )?yunohost app initdb \"?(\$\{?\w+\}?)\"?\s+-p\s\"?(\$\{?\w+\}?)\"?",
|
||||
r"ynh_mysql_setup_db --db_user=\2 --db_name=\2 --db_pwd=\3"),
|
||||
# Replace
|
||||
# sudo yunohost app checkport whaterver
|
||||
# by
|
||||
# ynh_port_available whatever
|
||||
"yunohost app checkport": (
|
||||
r"(sudo )?yunohost app checkport",
|
||||
r"ynh_port_available"),
|
||||
# We can't migrate easily port-available
|
||||
# .. but at the time of writing this code, only two non-working apps are using it.
|
||||
"yunohost tools port-available": (None, None),
|
||||
# Replace
|
||||
# yunohost app checkurl "${domain}${path_url}" -a "${app}"
|
||||
# by
|
||||
# ynh_webpath_register --app=${app} --domain=${domain} --path_url=${path_url}
|
||||
"yunohost app checkurl": (
|
||||
r"(sudo )?yunohost app checkurl \"?(\$\{?\w+\}?)\/?(\$\{?\w+\}?)\"?\s+-a\s\"?(\$\{?\w+\}?)\"?",
|
||||
r"ynh_webpath_register --app=\4 --domain=\2 --path_url=\3"),
|
||||
}
|
||||
|
||||
stuff_to_replace_compiled = {h: (re.compile(r[0]), r[1]) if r[0] else (None,None) for h, r in stuff_to_replace.items()}
|
||||
|
||||
for filename in files_to_patch:
|
||||
|
||||
# Ignore non-regular files
|
||||
if not os.path.isfile(filename):
|
||||
continue
|
||||
|
||||
content = read_file(filename)
|
||||
replaced_stuff = False
|
||||
|
||||
for helper, regexes in stuff_to_replace_compiled.items():
|
||||
pattern, replace = regexes
|
||||
# If helper is used, attempt to patch the file
|
||||
if helper in content and pattern != "":
|
||||
content = pattern.sub(replace, content)
|
||||
replaced_stuff = True
|
||||
|
||||
# If the helpert is *still* in the content, it means that we
|
||||
# couldn't patch the deprecated helper in the previous lines. In
|
||||
# that case, abort the install or whichever step is performed
|
||||
if helper in content:
|
||||
raise YunohostError("This app is likely pretty old and uses deprecated / outdated helpers that can't be migrated easily. It can't be installed anymore.")
|
||||
|
||||
if replaced_stuff:
|
||||
|
||||
# Check the app do load the helper
|
||||
# If it doesn't, add the instruction ourselve (making sure it's after the #!/bin/bash if it's there...
|
||||
if filename.split("/")[-1] in ["install", "remove", "upgrade", "backup", "restore"]:
|
||||
source_helpers = "source /usr/share/yunohost/helpers"
|
||||
if source_helpers not in content:
|
||||
content.replace("#!/bin/bash", "#!/bin/bash\n"+source_helpers)
|
||||
if source_helpers not in content:
|
||||
content = source_helpers + "\n" + content
|
||||
|
||||
# Actually write the new content in the file
|
||||
write_to_file(filename, content)
|
||||
# And complain about those damn deprecated helpers
|
||||
logger.error("/!\ Packagers ! This app uses a very old deprecated helpers ... Yunohost automatically patched the helpers to use the new recommended practice, but please do consider fixing the upstream code right now ...")
|
||||
|
|
|
@ -36,14 +36,14 @@ from datetime import datetime
|
|||
from glob import glob
|
||||
from collections import OrderedDict
|
||||
|
||||
from moulinette import msignals, m18n
|
||||
from moulinette import msignals, m18n, msettings
|
||||
from yunohost.utils.error import YunohostError
|
||||
from moulinette.utils import filesystem
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import read_file, mkdir, write_to_yaml, read_yaml
|
||||
|
||||
from yunohost.app import (
|
||||
app_info, _is_installed, _parse_app_instance_name, _patch_php5
|
||||
app_info, _is_installed, _parse_app_instance_name, _patch_php5, dump_app_log_extract_for_debugging, _patch_legacy_helpers
|
||||
)
|
||||
from yunohost.hook import (
|
||||
hook_list, hook_info, hook_callback, hook_exec, CUSTOM_HOOK_FOLDER
|
||||
|
@ -1321,6 +1321,9 @@ class RestoreManager():
|
|||
app_settings_in_archive = os.path.join(app_dir_in_archive, 'settings')
|
||||
app_scripts_in_archive = os.path.join(app_settings_in_archive, 'scripts')
|
||||
|
||||
# Attempt to patch legacy helpers...
|
||||
_patch_legacy_helpers(app_settings_in_archive)
|
||||
|
||||
# Apply dirty patch to make php5 apps compatible with php7
|
||||
_patch_php5(app_settings_in_archive)
|
||||
|
||||
|
@ -1398,6 +1401,9 @@ class RestoreManager():
|
|||
logger.exception(msg)
|
||||
operation_logger.error(msg)
|
||||
|
||||
if msettings.get('interface') != 'api':
|
||||
dump_app_log_extract_for_debugging(operation_logger)
|
||||
|
||||
self.targets.set_result("apps", app_instance_name, "Error")
|
||||
|
||||
remove_script = os.path.join(app_scripts_in_archive, 'remove')
|
||||
|
|
|
@ -92,7 +92,6 @@ def user_permission_update(operation_logger, permission, add=None, remove=None,
|
|||
remove -- List of groups or usernames to remove from to this permission
|
||||
"""
|
||||
from yunohost.hook import hook_callback
|
||||
from yunohost.user import user_group_list
|
||||
from yunohost.utils.ldap import _get_ldap_interface
|
||||
ldap = _get_ldap_interface()
|
||||
|
||||
|
@ -111,7 +110,6 @@ def user_permission_update(operation_logger, permission, add=None, remove=None,
|
|||
raise YunohostError('permission_not_found', permission=permission)
|
||||
|
||||
current_allowed_groups = existing_permission["allowed"]
|
||||
all_existing_groups = user_group_list()['groups'].keys()
|
||||
operation_logger.related_to.append(('app', permission.split(".")[0]))
|
||||
|
||||
# Compute new allowed group list (and make sure what we're doing make sense)
|
||||
|
@ -121,8 +119,6 @@ def user_permission_update(operation_logger, permission, add=None, remove=None,
|
|||
if add:
|
||||
groups_to_add = [add] if not isinstance(add, list) else add
|
||||
for group in groups_to_add:
|
||||
if group not in all_existing_groups:
|
||||
raise YunohostError('group_unknown', group=group)
|
||||
if group in current_allowed_groups:
|
||||
logger.warning(m18n.n('permission_already_allowed', permission=permission, group=group))
|
||||
else:
|
||||
|
@ -133,8 +129,6 @@ def user_permission_update(operation_logger, permission, add=None, remove=None,
|
|||
if remove:
|
||||
groups_to_remove = [remove] if not isinstance(remove, list) else remove
|
||||
for group in groups_to_remove:
|
||||
if group not in all_existing_groups:
|
||||
raise YunohostError('group_unknown', group=group)
|
||||
if group not in current_allowed_groups:
|
||||
logger.warning(m18n.n('permission_already_disallowed', permission=permission, group=group))
|
||||
else:
|
||||
|
@ -161,36 +155,10 @@ def user_permission_update(operation_logger, permission, add=None, remove=None,
|
|||
|
||||
operation_logger.start()
|
||||
|
||||
try:
|
||||
ldap.update('cn=%s,ou=permission' % permission,
|
||||
{'groupPermission': ['cn=' + g + ',ou=groups,dc=yunohost,dc=org' for g in new_allowed_groups]})
|
||||
except Exception as e:
|
||||
raise YunohostError('permission_update_failed', permission=permission, error=e)
|
||||
new_permission = _update_ldap_group_permission(permission=permission, allowed=new_allowed_groups, sync_perm=sync_perm)
|
||||
|
||||
logger.debug(m18n.n('permission_updated', permission=permission))
|
||||
|
||||
# Trigger permission sync if asked
|
||||
|
||||
if sync_perm:
|
||||
permission_sync_to_user()
|
||||
|
||||
new_permission = user_permission_list(full=True)["permissions"][permission]
|
||||
|
||||
# Trigger app callbacks
|
||||
|
||||
app = permission.split(".")[0]
|
||||
|
||||
old_allowed_users = set(existing_permission["corresponding_users"])
|
||||
new_allowed_users = set(new_permission["corresponding_users"])
|
||||
|
||||
effectively_added_users = new_allowed_users - old_allowed_users
|
||||
effectively_removed_users = old_allowed_users - new_allowed_users
|
||||
|
||||
if effectively_added_users:
|
||||
hook_callback('post_app_addaccess', args=[app, ','.join(effectively_added_users)])
|
||||
if effectively_removed_users:
|
||||
hook_callback('post_app_removeaccess', args=[app, ','.join(effectively_removed_users)])
|
||||
|
||||
return new_permission
|
||||
|
||||
|
||||
|
@ -225,34 +193,10 @@ def user_permission_reset(operation_logger, permission, sync_perm=True):
|
|||
operation_logger.related_to.append(('app', permission.split(".")[0]))
|
||||
operation_logger.start()
|
||||
|
||||
default_permission = {'groupPermission': ['cn=all_users,ou=groups,dc=yunohost,dc=org']}
|
||||
try:
|
||||
ldap.update('cn=%s,ou=permission' % permission, default_permission)
|
||||
except Exception as e:
|
||||
raise YunohostError('permission_update_failed', permission=permission, error=e)
|
||||
new_permission = _update_ldap_group_permission(permission=permission, allowed="all_users", sync_perm=sync_perm)
|
||||
|
||||
logger.debug(m18n.n('permission_updated', permission=permission))
|
||||
|
||||
if sync_perm:
|
||||
permission_sync_to_user()
|
||||
|
||||
new_permission = user_permission_list(full=True)["permissions"][permission]
|
||||
|
||||
# Trigger app callbacks
|
||||
|
||||
app = permission.split(".")[0]
|
||||
|
||||
old_allowed_users = set(existing_permission["corresponding_users"])
|
||||
new_allowed_users = set(new_permission["corresponding_users"])
|
||||
|
||||
effectively_added_users = new_allowed_users - old_allowed_users
|
||||
effectively_removed_users = old_allowed_users - new_allowed_users
|
||||
|
||||
if effectively_added_users:
|
||||
hook_callback('post_app_addaccess', args=[app, ','.join(effectively_added_users)])
|
||||
if effectively_removed_users:
|
||||
hook_callback('post_app_removeaccess', args=[app, ','.join(effectively_removed_users)])
|
||||
|
||||
return new_permission
|
||||
|
||||
#
|
||||
|
@ -286,7 +230,6 @@ def permission_create(operation_logger, permission, url=None, allowed=None, sync
|
|||
re:domain.tld/app/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
|
||||
"""
|
||||
|
||||
from yunohost.user import user_group_list
|
||||
from yunohost.utils.ldap import _get_ldap_interface
|
||||
ldap = _get_ldap_interface()
|
||||
|
||||
|
@ -313,20 +256,6 @@ def permission_create(operation_logger, permission, url=None, allowed=None, sync
|
|||
'gidNumber': gid,
|
||||
}
|
||||
|
||||
# If who should be allowed is explicitly provided, use this info
|
||||
if allowed:
|
||||
if not isinstance(allowed, list):
|
||||
allowed = [allowed]
|
||||
# (though first we validate that the targets actually exist)
|
||||
all_existing_groups = user_group_list()['groups'].keys()
|
||||
for g in allowed:
|
||||
if g not in all_existing_groups:
|
||||
raise YunohostError('group_unknown', group=g)
|
||||
attr_dict['groupPermission'] = ['cn=%s,ou=groups,dc=yunohost,dc=org' % g for g in allowed]
|
||||
# For main permission, we add all users by default
|
||||
elif permission.endswith(".main"):
|
||||
attr_dict['groupPermission'] = ['cn=all_users,ou=groups,dc=yunohost,dc=org']
|
||||
|
||||
if url:
|
||||
attr_dict['URL'] = url
|
||||
|
||||
|
@ -338,11 +267,20 @@ def permission_create(operation_logger, permission, url=None, allowed=None, sync
|
|||
except Exception as e:
|
||||
raise YunohostError('permission_creation_failed', permission=permission, error=e)
|
||||
|
||||
if sync_perm:
|
||||
permission_sync_to_user()
|
||||
to_add = None
|
||||
|
||||
# If who should be allowed is explicitly provided, use this info
|
||||
if allowed:
|
||||
if not isinstance(allowed, list):
|
||||
to_add = [allowed]
|
||||
# For main permission, we add all users by default
|
||||
elif permission.endswith(".main"):
|
||||
to_add = "all_users"
|
||||
|
||||
new_permission = _update_ldap_group_permission(permission=permission, allowed=to_add, sync_perm=sync_perm)
|
||||
|
||||
logger.debug(m18n.n('permission_created', permission=permission))
|
||||
return user_permission_list(full=True)["permissions"][permission]
|
||||
return new_permission
|
||||
|
||||
|
||||
@is_unit_operation()
|
||||
|
@ -471,3 +409,68 @@ def permission_sync_to_user():
|
|||
# Reload unscd, otherwise the group ain't propagated to the LDAP database
|
||||
os.system('nscd --invalidate=passwd')
|
||||
os.system('nscd --invalidate=group')
|
||||
|
||||
def _update_ldap_group_permission(permission, allowed, sync_perm=True):
|
||||
"""
|
||||
Internal function that will rewrite user permission
|
||||
|
||||
permission -- Name of the permission (e.g. mail or nextcloud or wordpress.editors)
|
||||
allowed -- A list of group/user to allow for the permission
|
||||
"""
|
||||
|
||||
from yunohost.hook import hook_callback
|
||||
from yunohost.user import user_group_list
|
||||
from yunohost.utils.ldap import _get_ldap_interface
|
||||
ldap = _get_ldap_interface()
|
||||
|
||||
# Fetch currently allowed groups for this permission
|
||||
|
||||
existing_permission = user_permission_list(full=True)["permissions"].get(permission, None)
|
||||
if existing_permission is None:
|
||||
raise YunohostError('permission_not_found', permission=permission)
|
||||
|
||||
all_existing_groups = user_group_list()['groups'].keys()
|
||||
|
||||
if allowed:
|
||||
if not isinstance(allowed, list):
|
||||
allowed = [allowed]
|
||||
for group in allowed:
|
||||
if group not in all_existing_groups:
|
||||
raise YunohostError('group_unknown', group=group)
|
||||
else:
|
||||
if sync_perm:
|
||||
permission_sync_to_user()
|
||||
|
||||
return user_permission_list(full=True)["permissions"][permission]
|
||||
|
||||
try:
|
||||
ldap.update('cn=%s,ou=permission' % permission,
|
||||
{'groupPermission': ['cn=' + g + ',ou=groups,dc=yunohost,dc=org' for g in allowed]})
|
||||
except Exception as e:
|
||||
raise YunohostError('permission_update_failed', permission=permission, error=e)
|
||||
|
||||
# Trigger permission sync if asked
|
||||
|
||||
if sync_perm:
|
||||
permission_sync_to_user()
|
||||
|
||||
new_permission = user_permission_list(full=True)["permissions"][permission]
|
||||
|
||||
# Trigger app callbacks
|
||||
|
||||
app = permission.split(".")[0]
|
||||
sub_permission = permission.split(".")[1]
|
||||
|
||||
old_allowed_users = set(existing_permission["corresponding_users"])
|
||||
new_allowed_users = set(new_permission["corresponding_users"])
|
||||
|
||||
effectively_added_users = new_allowed_users - old_allowed_users
|
||||
effectively_removed_users = old_allowed_users - new_allowed_users
|
||||
|
||||
if effectively_added_users:
|
||||
hook_callback('post_app_addaccess', args=[app, ','.join(effectively_added_users), sub_permission])
|
||||
if effectively_removed_users:
|
||||
hook_callback('post_app_removeaccess', args=[app, ','.join(effectively_removed_users), sub_permission])
|
||||
|
||||
return new_permission
|
||||
|
|
@ -673,25 +673,6 @@ def tools_upgrade(operation_logger, apps=None, system=False):
|
|||
operation_logger.success()
|
||||
|
||||
|
||||
def tools_port_available(port):
|
||||
"""
|
||||
Check availability of a local port
|
||||
|
||||
Keyword argument:
|
||||
port -- Port to check
|
||||
|
||||
"""
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.settimeout(1)
|
||||
s.connect(("localhost", int(port)))
|
||||
s.close()
|
||||
except socket.error:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
@is_unit_operation()
|
||||
def tools_shutdown(operation_logger, force=False):
|
||||
shutdown = force
|
||||
|
|
Loading…
Add table
Reference in a new issue