mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Merge branch 'bookworm' into portal-api
This commit is contained in:
commit
db30b3acb8
70 changed files with 889 additions and 936 deletions
|
@ -7,7 +7,6 @@ generate-helpers-doc:
|
|||
image: "before-install"
|
||||
needs: []
|
||||
before_script:
|
||||
- apt-get update -y && apt-get install git hub -y
|
||||
- git config --global user.email "yunohost@yunohost.org"
|
||||
- git config --global user.name "$GITHUB_USER"
|
||||
script:
|
||||
|
|
|
@ -3,34 +3,33 @@
|
|||
########################################
|
||||
# later we must fix lint and format-check jobs and remove "allow_failure"
|
||||
|
||||
lint39:
|
||||
lint311:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
needs: []
|
||||
allow_failure: true
|
||||
script:
|
||||
- tox -e py39-lint
|
||||
- tox -e py311-lint
|
||||
|
||||
invalidcode39:
|
||||
invalidcode311:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
needs: []
|
||||
script:
|
||||
- tox -e py39-invalidcode
|
||||
- tox -e py311-invalidcode
|
||||
|
||||
mypy:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
needs: []
|
||||
script:
|
||||
- tox -e py39-mypy
|
||||
- tox -e py311-mypy
|
||||
|
||||
black:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
needs: []
|
||||
before_script:
|
||||
- apt-get update -y && apt-get install git hub -y
|
||||
- git config --global user.email "yunohost@yunohost.org"
|
||||
- git config --global user.name "$GITHUB_USER"
|
||||
- hub clone --branch ${CI_COMMIT_REF_NAME} "https://$GITHUB_TOKEN:x-oauth-basic@github.com/YunoHost/yunohost.git" github_repo
|
||||
|
@ -38,7 +37,7 @@ black:
|
|||
script:
|
||||
# create a local branch that will overwrite distant one
|
||||
- git checkout -b "ci-format-${CI_COMMIT_REF_NAME}" --no-track
|
||||
- tox -e py39-black-run
|
||||
- tox -e py311-black-run
|
||||
- '[ $(git diff | wc -l) != 0 ] || exit 0' # stop if there is nothing to commit
|
||||
- git commit -am "[CI] Format code with Black" || true
|
||||
- git push -f origin "ci-format-${CI_COMMIT_REF_NAME}":"ci-format-${CI_COMMIT_REF_NAME}"
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
.install_debs: &install_debs
|
||||
- apt-get update -o Acquire::Retries=3
|
||||
- DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ${CI_PROJECT_DIR}/*.deb
|
||||
- pip3 install -U mock pip pytest pytest-cov pytest-mock pytest-sugar requests-mock tox ansi2html black jinja2 "packaging<22"
|
||||
|
||||
.test-stage:
|
||||
stage: test
|
||||
|
|
|
@ -16,7 +16,6 @@ autofix-translated-strings:
|
|||
image: "before-install"
|
||||
needs: []
|
||||
before_script:
|
||||
- apt-get update -y && apt-get install git hub -y
|
||||
- git config --global user.email "yunohost@yunohost.org"
|
||||
- git config --global user.name "$GITHUB_USER"
|
||||
- hub clone --branch ${CI_COMMIT_REF_NAME} "https://$GITHUB_TOKEN:x-oauth-basic@github.com/YunoHost/yunohost.git" github_repo
|
||||
|
|
|
@ -132,12 +132,8 @@ def main() -> bool:
|
|||
)
|
||||
continue
|
||||
|
||||
# Only broadcast IPv4 because IPv6 is buggy ... because we ain't using python3-ifaddr >= 0.1.7
|
||||
# Buster only ships 0.1.6
|
||||
# Bullseye ships 0.1.7
|
||||
# To be re-enabled once we're on bullseye...
|
||||
# ips: List[str] = interfaces[interface]["ipv4"] + interfaces[interface]["ipv6"]
|
||||
ips: List[str] = interfaces[interface]["ipv4"]
|
||||
# Broadcast IPv4 and IPv6
|
||||
ips: List[str] = interfaces[interface]["ipv4"] + interfaces[interface]["ipv6"]
|
||||
|
||||
# If at least one IP is listed
|
||||
if not ips:
|
||||
|
|
|
@ -13,9 +13,8 @@ protocols = imap sieve {% if pop3_enabled == "True" %}pop3{% endif %}
|
|||
mail_plugins = $mail_plugins quota notify push_notification
|
||||
|
||||
###############################################################################
|
||||
|
||||
# generated 2020-08-18, Mozilla Guideline v5.6, Dovecot 2.3.4, OpenSSL 1.1.1d, intermediate configuration
|
||||
# https://ssl-config.mozilla.org/#server=dovecot&version=2.3.4&config=intermediate&openssl=1.1.1d&guideline=5.6
|
||||
# generated 2023-06-13, Mozilla Guideline v5.7, Dovecot 2.3.19, OpenSSL 3.0.9, intermediate configuration
|
||||
# https://ssl-config.mozilla.org/#server=dovecot&version=2.3.19&config=intermediate&openssl=3.0.9&guideline=5.7
|
||||
|
||||
ssl = required
|
||||
|
||||
|
@ -32,7 +31,7 @@ ssl_dh = </usr/share/yunohost/ffdhe2048.pem
|
|||
|
||||
# intermediate configuration
|
||||
ssl_min_protocol = TLSv1.2
|
||||
ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
||||
ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305
|
||||
ssl_prefer_server_ciphers = no
|
||||
|
||||
###############################################################################
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
# See man 5 jail.conf for details.
|
||||
#
|
||||
# [DEFAULT]
|
||||
# bantime = 3600
|
||||
# bantime = 1h
|
||||
#
|
||||
# [sshd]
|
||||
# enabled = true
|
||||
|
@ -44,10 +44,52 @@ before = paths-debian.conf
|
|||
# MISCELLANEOUS OPTIONS
|
||||
#
|
||||
|
||||
# "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not
|
||||
# ban a host which matches an address in this list. Several addresses can be
|
||||
# defined using space (and/or comma) separator.
|
||||
ignoreip = 127.0.0.1/8
|
||||
# "bantime.increment" allows to use database for searching of previously banned ip's to increase a
|
||||
# default ban time using special formula, default it is banTime * 1, 2, 4, 8, 16, 32...
|
||||
#bantime.increment = true
|
||||
|
||||
# "bantime.rndtime" is the max number of seconds using for mixing with random time
|
||||
# to prevent "clever" botnets calculate exact time IP can be unbanned again:
|
||||
#bantime.rndtime =
|
||||
|
||||
# "bantime.maxtime" is the max number of seconds using the ban time can reach (doesn't grow further)
|
||||
#bantime.maxtime =
|
||||
|
||||
# "bantime.factor" is a coefficient to calculate exponent growing of the formula or common multiplier,
|
||||
# default value of factor is 1 and with default value of formula, the ban time
|
||||
# grows by 1, 2, 4, 8, 16 ...
|
||||
#bantime.factor = 1
|
||||
|
||||
# "bantime.formula" used by default to calculate next value of ban time, default value below,
|
||||
# the same ban time growing will be reached by multipliers 1, 2, 4, 8, 16, 32...
|
||||
#bantime.formula = ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFactor
|
||||
#
|
||||
# more aggressive example of formula has the same values only for factor "2.0 / 2.885385" :
|
||||
#bantime.formula = ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)
|
||||
|
||||
# "bantime.multipliers" used to calculate next value of ban time instead of formula, corresponding
|
||||
# previously ban count and given "bantime.factor" (for multipliers default is 1);
|
||||
# following example grows ban time by 1, 2, 4, 8, 16 ... and if last ban count greater as multipliers count,
|
||||
# always used last multiplier (64 in example), for factor '1' and original ban time 600 - 10.6 hours
|
||||
#bantime.multipliers = 1 2 4 8 16 32 64
|
||||
# following example can be used for small initial ban time (bantime=60) - it grows more aggressive at begin,
|
||||
# for bantime=60 the multipliers are minutes and equal: 1 min, 5 min, 30 min, 1 hour, 5 hour, 12 hour, 1 day, 2 day
|
||||
#bantime.multipliers = 1 5 30 60 300 720 1440 2880
|
||||
|
||||
# "bantime.overalljails" (if true) specifies the search of IP in the database will be executed
|
||||
# cross over all jails, if false (default), only current jail of the ban IP will be searched
|
||||
#bantime.overalljails = false
|
||||
|
||||
# --------------------
|
||||
|
||||
# "ignoreself" specifies whether the local resp. own IP addresses should be ignored
|
||||
# (default is true). Fail2ban will not ban a host which matches such addresses.
|
||||
#ignoreself = true
|
||||
|
||||
# "ignoreip" can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban
|
||||
# will not ban a host which matches an address in this list. Several addresses
|
||||
# can be defined using space (and/or comma) separator.
|
||||
#ignoreip = 127.0.0.1/8 ::1
|
||||
|
||||
# External command that will take an tagged arguments to ignore, e.g. <ip>,
|
||||
# and return true if the IP is to be ignored. False otherwise.
|
||||
|
@ -56,15 +98,18 @@ ignoreip = 127.0.0.1/8
|
|||
ignorecommand =
|
||||
|
||||
# "bantime" is the number of seconds that a host is banned.
|
||||
bantime = 600
|
||||
bantime = 10m
|
||||
|
||||
# A host is banned if it has generated "maxretry" during the last "findtime"
|
||||
# seconds.
|
||||
findtime = 600
|
||||
findtime = 10m
|
||||
|
||||
# "maxretry" is the number of failures before a host get banned.
|
||||
maxretry = 10
|
||||
|
||||
# "maxmatches" is the number of matches stored in ticket (resolvable via tag <matches> in actions).
|
||||
maxmatches = %(maxretry)s
|
||||
|
||||
# "backend" specifies the backend used to get files modification.
|
||||
# Available options are "pyinotify", "gamin", "polling", "systemd" and "auto".
|
||||
# This option can be overridden in each jail as well.
|
||||
|
@ -113,10 +158,13 @@ logencoding = auto
|
|||
enabled = false
|
||||
|
||||
|
||||
# "mode" defines the mode of the filter (see corresponding filter implementation for more info).
|
||||
mode = normal
|
||||
|
||||
# "filter" defines the filter to use by the jail.
|
||||
# By default jails have names matching their filter name
|
||||
#
|
||||
filter = %(__name__)s
|
||||
filter = %(__name__)s[mode=%(mode)s]
|
||||
|
||||
|
||||
#
|
||||
|
@ -140,7 +188,7 @@ mta = sendmail
|
|||
# Default protocol
|
||||
protocol = tcp
|
||||
|
||||
# Specify chain where jumps would need to be added in iptables-* actions
|
||||
# Specify chain where jumps would need to be added in ban-actions expecting parameter chain
|
||||
chain = INPUT
|
||||
|
||||
# Ports to be banned
|
||||
|
@ -161,51 +209,53 @@ banaction = iptables-multiport
|
|||
banaction_allports = iptables-allports
|
||||
|
||||
# The simplest action to take: ban only
|
||||
action_ = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
action_ = %(banaction)s[port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
|
||||
# ban & send an e-mail with whois report to the destemail.
|
||||
action_mw = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
%(mta)s-whois[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
action_mw = %(action_)s
|
||||
%(mta)s-whois[sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
|
||||
# ban & send an e-mail with whois report and relevant log lines
|
||||
# to the destemail.
|
||||
action_mwl = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
%(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]
|
||||
action_mwl = %(action_)s
|
||||
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
|
||||
|
||||
# See the IMPORTANT note in action.d/xarf-login-attack for when to use this action
|
||||
#
|
||||
# ban & send a xarf e-mail to abuse contact of IP address and include relevant log lines
|
||||
# to the destemail.
|
||||
action_xarf = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath=%(logpath)s, port="%(port)s"]
|
||||
action_xarf = %(action_)s
|
||||
xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]
|
||||
|
||||
# ban & send a notification to one or more of the 50+ services supported by Apprise.
|
||||
# See https://github.com/caronc/apprise/wiki for details on what is supported.
|
||||
#
|
||||
# You may optionally over-ride the default configuration line (containing the Apprise URLs)
|
||||
# by using 'apprise[config="/alternate/path/to/apprise.cfg"]' otherwise
|
||||
# /etc/fail2ban/apprise.conf is sourced for your supported notification configuration.
|
||||
# action = %(action_)s
|
||||
# apprise
|
||||
|
||||
# ban IP on CloudFlare & send an e-mail with whois report and relevant log lines
|
||||
# to the destemail.
|
||||
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
|
||||
%(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]
|
||||
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
|
||||
|
||||
# Report block via blocklist.de fail2ban reporting service API
|
||||
#
|
||||
# See the IMPORTANT note in action.d/blocklist_de.conf for when to
|
||||
# use this action. Create a file jail.d/blocklist_de.local containing
|
||||
# [Init]
|
||||
# blocklist_de_apikey = {api key from registration]
|
||||
# See the IMPORTANT note in action.d/blocklist_de.conf for when to use this action.
|
||||
# Specify expected parameters in file action.d/blocklist_de.local or if the interpolation
|
||||
# `action_blocklist_de` used for the action, set value of `blocklist_de_apikey`
|
||||
# in your `jail.local` globally (section [DEFAULT]) or per specific jail section (resp. in
|
||||
# corresponding jail.d/my-jail.local file).
|
||||
#
|
||||
action_blocklist_de = blocklist_de[email="%(sender)s", service=%(filter)s, apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"]
|
||||
action_blocklist_de = blocklist_de[email="%(sender)s", service="%(__name__)s", apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"]
|
||||
|
||||
# Report ban via badips.com, and use as blacklist
|
||||
# Report ban via abuseipdb.com.
|
||||
#
|
||||
# See BadIPsAction docstring in config/action.d/badips.py for
|
||||
# documentation for this action.
|
||||
# See action.d/abuseipdb.conf for usage example and details.
|
||||
#
|
||||
# NOTE: This action relies on banaction being present on start and therefore
|
||||
# should be last action defined for a jail.
|
||||
#
|
||||
action_badips = badips.py[category="%(__name__)s", banaction="%(banaction)s", agent="%(fail2ban_agent)s"]
|
||||
#
|
||||
# Report ban via badips.com (uses action.d/badips.conf for reporting only)
|
||||
#
|
||||
action_badips_report = badips[category="%(__name__)s", agent="%(fail2ban_agent)s"]
|
||||
action_abuseipdb = abuseipdb
|
||||
|
||||
# Choose default action. To change, just override value of 'action' with the
|
||||
# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local
|
||||
|
@ -223,15 +273,10 @@ action = %(action_)s
|
|||
|
||||
[sshd]
|
||||
|
||||
port = ssh
|
||||
logpath = %(sshd_log)s
|
||||
backend = %(sshd_backend)s
|
||||
|
||||
|
||||
[sshd-ddos]
|
||||
# This jail corresponds to the standard configuration in Fail2ban.
|
||||
# The mail-whois action send a notification e-mail with a whois request
|
||||
# in the body.
|
||||
# To use more aggressive sshd modes set filter parameter "mode" in jail.local:
|
||||
# normal (default), ddos, extra or aggressive (combines all).
|
||||
# See "tests/files/logs/sshd" or "filter.d/sshd.conf" for usage example and details.
|
||||
#mode = normal
|
||||
port = ssh
|
||||
logpath = %(sshd_log)s
|
||||
backend = %(sshd_backend)s
|
||||
|
@ -265,7 +310,7 @@ logpath = %(apache_error_log)s
|
|||
# for email addresses. The mail outputs are buffered.
|
||||
port = http,https
|
||||
logpath = %(apache_access_log)s
|
||||
bantime = 172800
|
||||
bantime = 48h
|
||||
maxretry = 1
|
||||
|
||||
|
||||
|
@ -301,7 +346,7 @@ maxretry = 2
|
|||
port = http,https
|
||||
logpath = %(apache_access_log)s
|
||||
maxretry = 1
|
||||
ignorecommand = %(ignorecommands_dir)s/apache-fakegooglebot <ip>
|
||||
ignorecommand = %(fail2ban_confpath)s/filter.d/ignorecommands/apache-fakegooglebot <ip>
|
||||
|
||||
|
||||
[apache-modsecurity]
|
||||
|
@ -321,12 +366,15 @@ maxretry = 1
|
|||
[openhab-auth]
|
||||
|
||||
filter = openhab
|
||||
action = iptables-allports[name=NoAuthFailures]
|
||||
banaction = %(banaction_allports)s
|
||||
logpath = /opt/openhab/logs/request.log
|
||||
|
||||
|
||||
# To use more aggressive http-auth modes set filter parameter "mode" in jail.local:
|
||||
# normal (default), aggressive (combines all), auth or fallback
|
||||
# See "tests/files/logs/nginx-http-auth" or "filter.d/nginx-http-auth.conf" for usage example and details.
|
||||
[nginx-http-auth]
|
||||
|
||||
# mode = normal
|
||||
port = http,https
|
||||
logpath = %(nginx_error_log)s
|
||||
|
||||
|
@ -342,8 +390,10 @@ logpath = %(nginx_error_log)s
|
|||
|
||||
port = http,https
|
||||
logpath = %(nginx_error_log)s
|
||||
maxretry = 2
|
||||
|
||||
[nginx-bad-request]
|
||||
port = http,https
|
||||
logpath = %(nginx_access_log)s
|
||||
|
||||
# Ban attackers that try to use PHP's URL-fopen() functionality
|
||||
# through GET/POST variables. - Experimental, with more than a year
|
||||
|
@ -377,6 +427,8 @@ logpath = %(lighttpd_error_log)s
|
|||
|
||||
port = http,https
|
||||
logpath = %(roundcube_errors_log)s
|
||||
# Use following line in your jail.local if roundcube logs to journal.
|
||||
#backend = %(syslog_backend)s
|
||||
|
||||
|
||||
[openwebmail]
|
||||
|
@ -426,11 +478,13 @@ backend = %(syslog_backend)s
|
|||
|
||||
port = http,https
|
||||
logpath = /var/log/tomcat*/catalina.out
|
||||
#logpath = /var/log/guacamole.log
|
||||
|
||||
[monit]
|
||||
#Ban clients brute-forcing the monit gui login
|
||||
port = 2812
|
||||
logpath = /var/log/monit
|
||||
/var/log/monit.log
|
||||
|
||||
|
||||
[webmin-auth]
|
||||
|
@ -513,27 +567,29 @@ logpath = %(vsftpd_log)s
|
|||
# ASSP SMTP Proxy Jail
|
||||
[assp]
|
||||
|
||||
port = smtp,submission
|
||||
port = smtp,465,submission
|
||||
logpath = /root/path/to/assp/logs/maillog.txt
|
||||
|
||||
|
||||
[courier-smtp]
|
||||
|
||||
port = smtp,submission
|
||||
port = smtp,465,submission
|
||||
logpath = %(syslog_mail)s
|
||||
backend = %(syslog_backend)s
|
||||
|
||||
|
||||
[postfix]
|
||||
|
||||
port = smtp,submission
|
||||
logpath = %(postfix_log)s
|
||||
backend = %(postfix_backend)s
|
||||
# To use another modes set filter parameter "mode" in jail.local:
|
||||
mode = more
|
||||
port = smtp,465,submission
|
||||
logpath = %(postfix_log)s
|
||||
backend = %(postfix_backend)s
|
||||
|
||||
|
||||
[postfix-rbl]
|
||||
|
||||
port = smtp,submission
|
||||
filter = postfix[mode=rbl]
|
||||
port = smtp,465,submission
|
||||
logpath = %(postfix_log)s
|
||||
backend = %(postfix_backend)s
|
||||
maxretry = 1
|
||||
|
@ -541,14 +597,17 @@ maxretry = 1
|
|||
|
||||
[sendmail-auth]
|
||||
|
||||
port = submission,smtp
|
||||
port = submission,465,smtp
|
||||
logpath = %(syslog_mail)s
|
||||
backend = %(syslog_backend)s
|
||||
|
||||
|
||||
[sendmail-reject]
|
||||
|
||||
port = smtp,submission
|
||||
# To use more aggressive modes set filter parameter "mode" in jail.local:
|
||||
# normal (default), extra or aggressive
|
||||
# See "tests/files/logs/sendmail-reject" or "filter.d/sendmail-reject.conf" for usage example and details.
|
||||
#mode = normal
|
||||
port = smtp,465,submission
|
||||
logpath = %(syslog_mail)s
|
||||
backend = %(syslog_backend)s
|
||||
|
||||
|
@ -556,7 +615,7 @@ backend = %(syslog_backend)s
|
|||
[qmail-rbl]
|
||||
|
||||
filter = qmail
|
||||
port = smtp,submission
|
||||
port = smtp,465,submission
|
||||
logpath = /service/qmail/log/main/current
|
||||
|
||||
|
||||
|
@ -564,14 +623,14 @@ logpath = /service/qmail/log/main/current
|
|||
# but can be set by syslog_facility in the dovecot configuration.
|
||||
[dovecot]
|
||||
|
||||
port = pop3,pop3s,imap,imaps,submission,sieve
|
||||
port = pop3,pop3s,imap,imaps,submission,465,sieve
|
||||
logpath = %(dovecot_log)s
|
||||
backend = %(dovecot_backend)s
|
||||
|
||||
|
||||
[sieve]
|
||||
|
||||
port = smtp,submission
|
||||
port = smtp,465,submission
|
||||
logpath = %(dovecot_log)s
|
||||
backend = %(dovecot_backend)s
|
||||
|
||||
|
@ -583,20 +642,21 @@ logpath = %(solidpop3d_log)s
|
|||
|
||||
|
||||
[exim]
|
||||
|
||||
port = smtp,submission
|
||||
# see filter.d/exim.conf for further modes supported from filter:
|
||||
#mode = normal
|
||||
port = smtp,465,submission
|
||||
logpath = %(exim_main_log)s
|
||||
|
||||
|
||||
[exim-spam]
|
||||
|
||||
port = smtp,submission
|
||||
port = smtp,465,submission
|
||||
logpath = %(exim_main_log)s
|
||||
|
||||
|
||||
[kerio]
|
||||
|
||||
port = imap,smtp,imaps
|
||||
port = imap,smtp,imaps,465
|
||||
logpath = /opt/kerio/mailserver/store/logs/security.log
|
||||
|
||||
|
||||
|
@ -607,14 +667,15 @@ logpath = /opt/kerio/mailserver/store/logs/security.log
|
|||
|
||||
[courier-auth]
|
||||
|
||||
port = smtp,submission,imaps,pop3,pop3s
|
||||
port = smtp,465,submission,imap,imaps,pop3,pop3s
|
||||
logpath = %(syslog_mail)s
|
||||
backend = %(syslog_backend)s
|
||||
|
||||
|
||||
[postfix-sasl]
|
||||
|
||||
port = smtp,submission,imap,imaps,pop3,pop3s
|
||||
filter = postfix[mode=auth]
|
||||
port = smtp,465,submission,imap,imaps,pop3,pop3s
|
||||
# You might consider monitoring /var/log/mail.warn instead if you are
|
||||
# running postfix since it would provide the same log lines at the
|
||||
# "warn" level but overall at the smaller filesize.
|
||||
|
@ -631,7 +692,7 @@ backend = %(syslog_backend)s
|
|||
|
||||
[squirrelmail]
|
||||
|
||||
port = smtp,submission,imap,imap2,imaps,pop3,pop3s,http,https,socks
|
||||
port = smtp,465,submission,imap,imap2,imaps,pop3,pop3s,http,https,socks
|
||||
logpath = /var/lib/squirrelmail/prefs/squirrelmail_access_log
|
||||
|
||||
|
||||
|
@ -684,8 +745,8 @@ logpath = /var/log/named/security.log
|
|||
[nsd]
|
||||
|
||||
port = 53
|
||||
action = %(banaction)s[name=%(__name__)s-tcp, port="%(port)s", protocol="tcp", chain="%(chain)s", actname=%(banaction)s-tcp]
|
||||
%(banaction)s[name=%(__name__)s-udp, port="%(port)s", protocol="udp", chain="%(chain)s", actname=%(banaction)s-udp]
|
||||
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
|
||||
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
|
||||
logpath = /var/log/nsd.log
|
||||
|
||||
|
||||
|
@ -696,9 +757,8 @@ logpath = /var/log/nsd.log
|
|||
[asterisk]
|
||||
|
||||
port = 5060,5061
|
||||
action = %(banaction)s[name=%(__name__)s-tcp, port="%(port)s", protocol="tcp", chain="%(chain)s", actname=%(banaction)s-tcp]
|
||||
%(banaction)s[name=%(__name__)s-udp, port="%(port)s", protocol="udp", chain="%(chain)s", actname=%(banaction)s-udp]
|
||||
%(mta)s-whois[name=%(__name__)s, dest="%(destemail)s"]
|
||||
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
|
||||
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
|
||||
logpath = /var/log/asterisk/messages
|
||||
maxretry = 10
|
||||
|
||||
|
@ -706,16 +766,22 @@ maxretry = 10
|
|||
[freeswitch]
|
||||
|
||||
port = 5060,5061
|
||||
action = %(banaction)s[name=%(__name__)s-tcp, port="%(port)s", protocol="tcp", chain="%(chain)s", actname=%(banaction)s-tcp]
|
||||
%(banaction)s[name=%(__name__)s-udp, port="%(port)s", protocol="udp", chain="%(chain)s", actname=%(banaction)s-udp]
|
||||
%(mta)s-whois[name=%(__name__)s, dest="%(destemail)s"]
|
||||
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
|
||||
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
|
||||
logpath = /var/log/freeswitch.log
|
||||
maxretry = 10
|
||||
|
||||
|
||||
# enable adminlog; it will log to a file inside znc's directory by default.
|
||||
[znc-adminlog]
|
||||
|
||||
port = 6667
|
||||
logpath = /var/lib/znc/moddata/adminlog/znc.log
|
||||
|
||||
|
||||
# To log wrong MySQL access attempts add to /etc/my.cnf in [mysqld] or
|
||||
# equivalent section:
|
||||
# log-warning = 2
|
||||
# log-warnings = 2
|
||||
#
|
||||
# for syslog (daemon facility)
|
||||
# [mysqld_safe]
|
||||
|
@ -731,6 +797,14 @@ logpath = %(mysql_log)s
|
|||
backend = %(mysql_backend)s
|
||||
|
||||
|
||||
[mssql-auth]
|
||||
# Default configuration for Microsoft SQL Server for Linux
|
||||
# See the 'mssql-conf' manpage how to change logpath or port
|
||||
logpath = /var/opt/mssql/log/errorlog
|
||||
port = 1433
|
||||
filter = mssql-auth
|
||||
|
||||
|
||||
# Log wrong MongoDB auth (for details see filter 'filter.d/mongodb-auth.conf')
|
||||
[mongodb-auth]
|
||||
# change port when running with "--shardsvr" or "--configsvr" runtime operation
|
||||
|
@ -749,8 +823,8 @@ logpath = /var/log/mongodb/mongodb.log
|
|||
|
||||
logpath = /var/log/fail2ban.log
|
||||
banaction = %(banaction_allports)s
|
||||
bantime = 604800 ; 1 week
|
||||
findtime = 86400 ; 1 day
|
||||
bantime = 1w
|
||||
findtime = 1d
|
||||
|
||||
|
||||
# Generic filter for PAM. Has to be used with action which bans all
|
||||
|
@ -786,11 +860,31 @@ logpath = /var/log/ejabberd/ejabberd.log
|
|||
[counter-strike]
|
||||
|
||||
logpath = /opt/cstrike/logs/L[0-9]*.log
|
||||
# Firewall: http://www.cstrike-planet.com/faq/6
|
||||
tcpport = 27030,27031,27032,27033,27034,27035,27036,27037,27038,27039
|
||||
udpport = 1200,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010,27011,27012,27013,27014,27015
|
||||
action = %(banaction)s[name=%(__name__)s-tcp, port="%(tcpport)s", protocol="tcp", chain="%(chain)s", actname=%(banaction)s-tcp]
|
||||
%(banaction)s[name=%(__name__)s-udp, port="%(udpport)s", protocol="udp", chain="%(chain)s", actname=%(banaction)s-udp]
|
||||
action_ = %(default/action_)s[name=%(__name__)s-tcp, port="%(tcpport)s", protocol="tcp"]
|
||||
%(default/action_)s[name=%(__name__)s-udp, port="%(udpport)s", protocol="udp"]
|
||||
|
||||
[softethervpn]
|
||||
port = 500,4500
|
||||
protocol = udp
|
||||
logpath = /usr/local/vpnserver/security_log/*/sec.log
|
||||
|
||||
[gitlab]
|
||||
port = http,https
|
||||
logpath = /var/log/gitlab/gitlab-rails/application.log
|
||||
|
||||
[grafana]
|
||||
port = http,https
|
||||
logpath = /var/log/grafana/grafana.log
|
||||
|
||||
[bitwarden]
|
||||
port = http,https
|
||||
logpath = /home/*/bwdata/logs/identity/Identity/log.txt
|
||||
|
||||
[centreon]
|
||||
port = http,https
|
||||
logpath = /var/log/centreon/login.log
|
||||
|
||||
# consider low maxretry and a long bantime
|
||||
# nobody except your own Nagios server should ever probe nrpe
|
||||
|
@ -824,7 +918,9 @@ filter = apache-pass[knocking_url="%(knocking_url)s"]
|
|||
logpath = %(apache_access_log)s
|
||||
blocktype = RETURN
|
||||
returntype = DROP
|
||||
bantime = 3600
|
||||
action = %(action_)s[blocktype=%(blocktype)s, returntype=%(returntype)s,
|
||||
actionstart_on_demand=false, actionrepair_on_unban=true]
|
||||
bantime = 1h
|
||||
maxretry = 1
|
||||
findtime = 1
|
||||
|
||||
|
@ -832,8 +928,8 @@ findtime = 1
|
|||
[murmur]
|
||||
# AKA mumble-server
|
||||
port = 64738
|
||||
action = %(banaction)s[name=%(__name__)s-tcp, port="%(port)s", protocol=tcp, chain="%(chain)s", actname=%(banaction)s-tcp]
|
||||
%(banaction)s[name=%(__name__)s-udp, port="%(port)s", protocol=udp, chain="%(chain)s", actname=%(banaction)s-udp]
|
||||
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
|
||||
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
|
||||
logpath = /var/log/mumble-server/mumble-server.log
|
||||
|
||||
|
||||
|
@ -851,5 +947,34 @@ logpath = /var/log/haproxy.log
|
|||
|
||||
[slapd]
|
||||
port = ldap,ldaps
|
||||
filter = slapd
|
||||
logpath = /var/log/slapd.log
|
||||
|
||||
[domino-smtp]
|
||||
port = smtp,ssmtp
|
||||
logpath = /home/domino01/data/IBM_TECHNICAL_SUPPORT/console.log
|
||||
|
||||
[phpmyadmin-syslog]
|
||||
port = http,https
|
||||
logpath = %(syslog_authpriv)s
|
||||
backend = %(syslog_backend)s
|
||||
|
||||
|
||||
[zoneminder]
|
||||
# Zoneminder HTTP/HTTPS web interface auth
|
||||
# Logs auth failures to apache2 error log
|
||||
port = http,https
|
||||
logpath = %(apache_error_log)s
|
||||
|
||||
[traefik-auth]
|
||||
# to use 'traefik-auth' filter you have to configure your Traefik instance,
|
||||
# see `filter.d/traefik-auth.conf` for details and service example.
|
||||
port = http,https
|
||||
logpath = /var/log/traefik/access.log
|
||||
|
||||
[scanlogd]
|
||||
logpath = %(syslog_local0)s
|
||||
banaction = %(banaction_allports)s
|
||||
|
||||
[monitorix]
|
||||
port = 8080
|
||||
logpath = /var/log/monitorix-httpd
|
||||
|
|
|
@ -3,16 +3,16 @@ ssl_session_cache shared:SSL:50m; # about 200000 sessions
|
|||
ssl_session_tickets off;
|
||||
|
||||
{% if compatibility == "modern" %}
|
||||
# generated 2020-08-14, Mozilla Guideline v5.6, nginx 1.14.2, OpenSSL 1.1.1d, modern configuration
|
||||
# https://ssl-config.mozilla.org/#server=nginx&version=1.14.2&config=modern&openssl=1.1.1d&guideline=5.6
|
||||
# generated 2023-06-13, Mozilla Guideline v5.7, nginx 1.22.1, OpenSSL 3.0.9, modern configuration
|
||||
# https://ssl-config.mozilla.org/#server=nginx&version=1.22.1&config=modern&openssl=3.0.9&guideline=5.7
|
||||
ssl_protocols TLSv1.3;
|
||||
ssl_prefer_server_ciphers off;
|
||||
{% else %}
|
||||
# Ciphers with intermediate compatibility
|
||||
# generated 2020-08-14, Mozilla Guideline v5.6, nginx 1.14.2, OpenSSL 1.1.1d, intermediate configuration
|
||||
# https://ssl-config.mozilla.org/#server=nginx&version=1.14.2&config=intermediate&openssl=1.1.1d&guideline=5.6
|
||||
# generated 2023-06-13, Mozilla Guideline v5.7, nginx 1.22.1, OpenSSL 3.0.9, intermediate configuration
|
||||
# https://ssl-config.mozilla.org/#server=nginx&version=1.22.1&config=intermediate&openssl=3.0.9&guideline=5.7
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
# Pre-defined FFDHE group (RFC 7919)
|
||||
|
|
|
@ -30,8 +30,8 @@ smtpd_tls_chain_files =
|
|||
tls_server_sni_maps = hash:/etc/postfix/sni
|
||||
|
||||
{% if compatibility == "intermediate" %}
|
||||
# generated 2020-08-18, Mozilla Guideline v5.6, Postfix 3.4.14, OpenSSL 1.1.1d, intermediate configuration
|
||||
# https://ssl-config.mozilla.org/#server=postfix&version=3.4.14&config=intermediate&openssl=1.1.1d&guideline=5.6
|
||||
# generated 2023-06-13, Mozilla Guideline v5.7, Postfix 3.7.5, OpenSSL 3.0.9, intermediate configuration
|
||||
# https://ssl-config.mozilla.org/#server=postfix&version=3.7.5&config=intermediate&openssl=3.0.9&guideline=5.7
|
||||
|
||||
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
||||
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
||||
|
@ -41,10 +41,10 @@ smtpd_tls_mandatory_ciphers = medium
|
|||
# not actually 1024 bits, this applies to all DHE >= 1024 bits
|
||||
smtpd_tls_dh1024_param_file = /usr/share/yunohost/ffdhe2048.pem
|
||||
|
||||
tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
||||
tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305
|
||||
{% else %}
|
||||
# generated 2020-08-18, Mozilla Guideline v5.6, Postfix 3.4.14, OpenSSL 1.1.1d, modern configuration
|
||||
# https://ssl-config.mozilla.org/#server=postfix&version=3.4.14&config=modern&openssl=1.1.1d&guideline=5.6
|
||||
# generated 2023-06-13, Mozilla Guideline v5.7, Postfix 3.7.5, OpenSSL 3.0.9, modern configuration
|
||||
# https://ssl-config.mozilla.org/#server=postfix&version=3.7.5&config=modern&openssl=3.0.9&guideline=5.7
|
||||
|
||||
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1, !TLSv1.2
|
||||
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1, !TLSv1.2
|
||||
|
|
44
debian/changelog
vendored
44
debian/changelog
vendored
|
@ -1,3 +1,47 @@
|
|||
yunohost (12.0.0) unstable; urgency=low
|
||||
|
||||
- Tmp changelog to prepare Bookworm
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 04 May 2023 20:30:19 +0200
|
||||
|
||||
yunohost (11.2.4) stable; urgency=low
|
||||
|
||||
- doc: Improve --help for 'yunohost app install' ([#1702](https://github.com/yunohost/yunohost/pull/1702))
|
||||
- helpers: add new --group option for ynh_add_fpm_config to customize the Group parameter (65d25710)
|
||||
- apps: allow to use jinja {% if foobar %} blocks in their notifications/doc pages (57699289)
|
||||
- apps: BACKUP_CORE_ONLY was not set for pre-upgrade safety backups, resulting in unecessarily large pre-upgrade backups (07daa687)
|
||||
- apps: Use the existing db_name setting for database provising to ease v1->v2 transition with specific db_name ([#1704](https://github.com/yunohost/yunohost/pull/1704))
|
||||
- configpanels/forms: more edge cases with some questions not implementing some methods/attributes (b0fe49ae)
|
||||
- diagnosis: reverse DNS check should be case-insensitive #2235 ([#1705](https://github.com/yunohost/yunohost/pull/1705))
|
||||
- i18n: Translations updated for Galician, Indonesian, Polish, Spanish, Turkish
|
||||
|
||||
Thanks to all contributors <3 ! (Grzegorz Cichocki, José M, Kuba Bazan, ljf (zamentur), massyas, Neko Nekowazarashi, selfhoster1312, Suleyman Harmandar, taco, Tagada)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 31 Aug 2023 17:30:21 +0200
|
||||
|
||||
yunohost (11.2.3) stable; urgency=low
|
||||
|
||||
- apps: fix another case of no attribute 'value' due to config panels/questions refactoring (4fda8ed49)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 22 Jul 2023 16:48:22 +0200
|
||||
|
||||
yunohost (11.2.2) stable; urgency=low
|
||||
|
||||
- domains: Gandi's `api_protocol` field should be a `select` type ([#1693](https://github.com/yunohost/yunohost/pull/1693))
|
||||
- configpanel: fix .value call for readonly-type options (e1ceb084)
|
||||
- i18n: Translations updated for French, Galician
|
||||
|
||||
Thanks to all contributors <3 ! (axolotle, José M, ppr, tituspijean)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Wed, 19 Jul 2023 02:35:28 +0200
|
||||
|
||||
yunohost (11.2.1) stable; urgency=low
|
||||
|
||||
- doc: fix resource doc generation .. not sure why this line that removed legit indent was there (ced222ea)
|
||||
- apps: hotfix for funky issue, apps getting named 'undefined' (781f924e)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 17 Jul 2023 21:13:54 +0200
|
||||
|
||||
yunohost (11.2) stable; urgency=low
|
||||
|
||||
- dyndns: add support for recovery passwords ([#1475](https://github.com/YunoHost/yunohost/pull/1475))
|
||||
|
|
25
debian/control
vendored
25
debian/control
vendored
|
@ -2,7 +2,7 @@ Source: yunohost
|
|||
Section: utils
|
||||
Priority: extra
|
||||
Maintainer: YunoHost Contributors <contrib@yunohost.org>
|
||||
Build-Depends: debhelper (>=9), debhelper-compat (= 13), dh-python, python3-all (>= 3.7), python3-yaml, python3-jinja2
|
||||
Build-Depends: debhelper (>=9), debhelper-compat (= 13), dh-python, python3-all (>= 3.11), python3-yaml, python3-jinja2
|
||||
Standards-Version: 3.9.6
|
||||
Homepage: https://yunohost.org/
|
||||
|
||||
|
@ -14,10 +14,10 @@ Depends: ${python3:Depends}, ${misc:Depends}
|
|||
, python3-psutil, python3-requests, python3-dnspython, python3-openssl
|
||||
, python3-miniupnpc, python3-dbus, python3-jinja2
|
||||
, python3-toml, python3-packaging, python3-publicsuffix2
|
||||
, python3-ldap, python3-zeroconf (>= 0.36), python3-lexicon,
|
||||
, python3-ldap, python3-zeroconf (>= 0.47), python3-lexicon,
|
||||
, python3-cryptography, python3-jwt
|
||||
, python-is-python3
|
||||
, nginx, nginx-extras (>=1.18)
|
||||
, nginx, nginx-extras (>=1.22)
|
||||
, apt, apt-transport-https, apt-utils, dirmngr
|
||||
, openssh-server, iptables, fail2ban, bind9-dnsutils
|
||||
, openssl, ca-certificates, netcat-openbsd, iproute2
|
||||
|
@ -33,23 +33,18 @@ Depends: ${python3:Depends}, ${misc:Depends}
|
|||
Recommends: yunohost-admin
|
||||
, ntp, inetutils-ping | iputils-ping
|
||||
, bash-completion, rsyslog
|
||||
, php7.4-common, php7.4-fpm, php7.4-ldap, php7.4-intl
|
||||
, mariadb-server, php7.4-mysql
|
||||
, php7.4-gd, php7.4-curl, php-php-gettext
|
||||
, python3-pip
|
||||
, unattended-upgrades
|
||||
, libdbd-ldap-perl, libnet-dns-perl
|
||||
, metronome (>=3.14.0)
|
||||
Conflicts: iptables-persistent
|
||||
, apache2
|
||||
, bind9
|
||||
, nginx-extras (>= 1.19)
|
||||
, openssl (>= 1.1.1o-0)
|
||||
, slapd (>= 2.4.58)
|
||||
, dovecot-core (>= 1:2.3.14)
|
||||
, redis-server (>= 5:6.1)
|
||||
, fail2ban (>= 0.11.3)
|
||||
, iptables (>= 1.8.8)
|
||||
, nginx-extras (>= 1.23)
|
||||
, openssl (>= 3.1)
|
||||
, slapd (>= 2.6)
|
||||
, dovecot-core (>= 1:2.4)
|
||||
, redis-server (>= 5:7.1)
|
||||
, fail2ban (>= 1.1)
|
||||
, iptables (>= 1.8.10)
|
||||
Description: manageable and configured self-hosting server
|
||||
YunoHost aims to make self-hosting accessible to everyone. It configures
|
||||
an email, Web and IM server alongside a LDAP base. It also provides
|
||||
|
|
|
@ -62,8 +62,6 @@ for c in ResourceClasses:
|
|||
|
||||
|
||||
for resource_id, doc in sorted(ResourceDocString.items()):
|
||||
doc = doc.replace("\n ", "\n")
|
||||
|
||||
print("----------------")
|
||||
print("")
|
||||
print(f"## {resource_id.replace('_', ' ').title()}")
|
||||
|
|
|
@ -210,6 +210,9 @@ ynh_mysql_setup_db() {
|
|||
# If $db_pwd is not provided, use new_db_pwd instead for db_pwd
|
||||
db_pwd="${db_pwd:-$new_db_pwd}"
|
||||
|
||||
# Dirty patch for super-legacy apps
|
||||
dpkg --list | grep -q "^ii mariadb-server" || { ynh_print_warn "Packager: you called ynh_mysql_setup_db without declaring a dependency to mariadb-server. Please add it to your apt dependencies !"; ynh_apt install mariadb-server; }
|
||||
|
||||
ynh_mysql_create_db "$db_name" "$db_user" "$db_pwd"
|
||||
ynh_app_setting_set --app=$app --key=mysqlpwd --value=$db_pwd
|
||||
}
|
||||
|
|
170
helpers/php
170
helpers/php
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
readonly YNH_DEFAULT_PHP_VERSION=7.4
|
||||
readonly YNH_DEFAULT_PHP_VERSION=8.2
|
||||
# Declare the actual PHP version to use.
|
||||
# A packager willing to use another version of PHP can override the variable into its _common.sh.
|
||||
YNH_PHP_VERSION=${YNH_PHP_VERSION:-$YNH_DEFAULT_PHP_VERSION}
|
||||
|
@ -70,16 +70,15 @@ YNH_PHP_VERSION=${YNH_PHP_VERSION:-$YNH_DEFAULT_PHP_VERSION}
|
|||
ynh_add_fpm_config() {
|
||||
local _globalphpversion=${phpversion-:}
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=vufpd
|
||||
local -A args_array=([v]=phpversion= [u]=usage= [f]=footprint= [p]=package= [d]=dedicated_service)
|
||||
local legacy_args=vufg
|
||||
local -A args_array=([v]=phpversion= [u]=usage= [f]=footprint= [g]=group=)
|
||||
local group
|
||||
local phpversion
|
||||
local usage
|
||||
local footprint
|
||||
local package
|
||||
local dedicated_service
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
package=${package:-}
|
||||
group=${group:-}
|
||||
|
||||
# The default behaviour is to use the template.
|
||||
local autogenconf=false
|
||||
|
@ -105,8 +104,6 @@ ynh_add_fpm_config() {
|
|||
fi
|
||||
|
||||
fi
|
||||
# Do not use a dedicated service by default
|
||||
dedicated_service=${dedicated_service:-0}
|
||||
|
||||
# Set the default PHP-FPM version by default
|
||||
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
|
||||
|
@ -130,45 +127,16 @@ ynh_add_fpm_config() {
|
|||
fi
|
||||
fi
|
||||
|
||||
# Legacy args (packager should just list their php dependency as regular apt dependencies...
|
||||
if [ -n "$package" ]; then
|
||||
# Install the additionnal packages from the default repository
|
||||
ynh_print_warn --message "Argument --package of ynh_add_fpm_config is deprecated and to be removed in the future"
|
||||
ynh_install_app_dependencies "$package"
|
||||
fi
|
||||
|
||||
if [ $dedicated_service -eq 1 ]; then
|
||||
ynh_print_warn --message "Argument --dedicated_service of ynh_add_fpm_config is deprecated and to be removed in the future"
|
||||
local fpm_service="${app}-phpfpm"
|
||||
local fpm_config_dir="/etc/php/$phpversion/dedicated-fpm"
|
||||
else
|
||||
local fpm_service="php${phpversion}-fpm"
|
||||
local fpm_config_dir="/etc/php/$phpversion/fpm"
|
||||
fi
|
||||
local fpm_service="php${phpversion}-fpm"
|
||||
local fpm_config_dir="/etc/php/$phpversion/fpm"
|
||||
|
||||
# Create the directory for FPM pools
|
||||
mkdir --parents "$fpm_config_dir/pool.d"
|
||||
|
||||
ynh_app_setting_set --app=$app --key=fpm_config_dir --value="$fpm_config_dir"
|
||||
ynh_app_setting_set --app=$app --key=fpm_service --value="$fpm_service"
|
||||
ynh_app_setting_set --app=$app --key=fpm_dedicated_service --value="$dedicated_service"
|
||||
ynh_app_setting_set --app=$app --key=phpversion --value=$phpversion
|
||||
|
||||
# Migrate from mutual PHP service to dedicated one.
|
||||
if [ $dedicated_service -eq 1 ]; then
|
||||
local old_fpm_config_dir="/etc/php/$phpversion/fpm"
|
||||
# If a config file exist in the common pool, move it.
|
||||
if [ -e "$old_fpm_config_dir/pool.d/$app.conf" ]; then
|
||||
ynh_print_info --message="Migrate to a dedicated php-fpm service for $app."
|
||||
# Create a backup of the old file before migration
|
||||
ynh_backup_if_checksum_is_different --file="$old_fpm_config_dir/pool.d/$app.conf"
|
||||
# Remove the old PHP config file
|
||||
ynh_secure_remove --file="$old_fpm_config_dir/pool.d/$app.conf"
|
||||
# Reload PHP to release the socket and allow the dedicated service to use it
|
||||
ynh_systemd_action --service_name=php${phpversion}-fpm --action=reload
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $autogenconf == "false" ]; then
|
||||
# Usage 1, use the template in conf/php-fpm.conf
|
||||
local phpfpm_path="$YNH_APP_BASEDIR/conf/php-fpm.conf"
|
||||
|
@ -180,12 +148,13 @@ ynh_add_fpm_config() {
|
|||
# Define the values to use for the configuration of PHP.
|
||||
ynh_get_scalable_phpfpm --usage=$usage --footprint=$footprint
|
||||
|
||||
local phpfpm_group=$([[ -n "$group" ]] && echo "$group" || echo "$app")
|
||||
local phpfpm_path="$YNH_APP_BASEDIR/conf/php-fpm.conf"
|
||||
echo "
|
||||
[__APP__]
|
||||
|
||||
user = __APP__
|
||||
group = __APP__
|
||||
group = __PHPFPM_GROUP__
|
||||
|
||||
chdir = __INSTALL_DIR__
|
||||
|
||||
|
@ -221,56 +190,13 @@ pm.process_idle_timeout = 10s
|
|||
local finalphpconf="$fpm_config_dir/pool.d/$app.conf"
|
||||
ynh_add_config --template="$phpfpm_path" --destination="$finalphpconf"
|
||||
|
||||
if [ -e "$YNH_APP_BASEDIR/conf/php-fpm.ini" ]; then
|
||||
ynh_print_warn --message="Packagers ! Please do not use a separate php ini file, merge your directives in the pool file instead."
|
||||
ynh_add_config --template="php-fpm.ini" --destination="$fpm_config_dir/conf.d/20-$app.ini"
|
||||
fi
|
||||
|
||||
if [ $dedicated_service -eq 1 ]; then
|
||||
# Create a dedicated php-fpm.conf for the service
|
||||
local globalphpconf=$fpm_config_dir/php-fpm-$app.conf
|
||||
|
||||
echo "[global]
|
||||
pid = /run/php/php__PHPVERSION__-fpm-__APP__.pid
|
||||
error_log = /var/log/php/fpm-php.__APP__.log
|
||||
syslog.ident = php-fpm-__APP__
|
||||
include = __FINALPHPCONF__
|
||||
" >$YNH_APP_BASEDIR/conf/php-fpm-$app.conf
|
||||
|
||||
ynh_add_config --template="php-fpm-$app.conf" --destination="$globalphpconf"
|
||||
|
||||
# Create a config for a dedicated PHP-FPM service for the app
|
||||
echo "[Unit]
|
||||
Description=PHP __PHPVERSION__ FastCGI Process Manager for __APP__
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
PIDFile=/run/php/php__PHPVERSION__-fpm-__APP__.pid
|
||||
ExecStart=/usr/sbin/php-fpm__PHPVERSION__ --nodaemonize --fpm-config __GLOBALPHPCONF__
|
||||
ExecReload=/bin/kill -USR2 \$MAINPID
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
" >$YNH_APP_BASEDIR/conf/$fpm_service
|
||||
|
||||
# Create this dedicated PHP-FPM service
|
||||
ynh_add_systemd_config --service=$fpm_service --template=$fpm_service
|
||||
# Integrate the service in YunoHost admin panel
|
||||
yunohost service add $fpm_service --log /var/log/php/fpm-php.$app.log --description "Php-fpm dedicated to $app"
|
||||
# Configure log rotate
|
||||
ynh_use_logrotate --logfile=/var/log/php
|
||||
# Restart the service, as this service is either stopped or only for this app
|
||||
ynh_systemd_action --service_name=$fpm_service --action=restart
|
||||
else
|
||||
# Validate that the new php conf doesn't break php-fpm entirely
|
||||
if ! php-fpm${phpversion} --test 2>/dev/null; then
|
||||
php-fpm${phpversion} --test || true
|
||||
ynh_secure_remove --file="$finalphpconf"
|
||||
ynh_die --message="The new configuration broke php-fpm?"
|
||||
fi
|
||||
ynh_systemd_action --service_name=$fpm_service --action=reload
|
||||
# Validate that the new php conf doesn't break php-fpm entirely
|
||||
if ! php-fpm${phpversion} --test 2>/dev/null; then
|
||||
php-fpm${phpversion} --test || true
|
||||
ynh_secure_remove --file="$finalphpconf"
|
||||
ynh_die --message="The new configuration broke php-fpm?"
|
||||
fi
|
||||
ynh_systemd_action --service_name=$fpm_service --action=reload
|
||||
}
|
||||
|
||||
# Remove the dedicated PHP-FPM config
|
||||
|
@ -281,8 +207,6 @@ WantedBy=multi-user.target
|
|||
ynh_remove_fpm_config() {
|
||||
local fpm_config_dir=$(ynh_app_setting_get --app=$app --key=fpm_config_dir)
|
||||
local fpm_service=$(ynh_app_setting_get --app=$app --key=fpm_service)
|
||||
local dedicated_service=$(ynh_app_setting_get --app=$app --key=fpm_dedicated_service)
|
||||
dedicated_service=${dedicated_service:-0}
|
||||
# Get the version of PHP used by this app
|
||||
local phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
|
||||
|
||||
|
@ -296,69 +220,7 @@ ynh_remove_fpm_config() {
|
|||
fi
|
||||
|
||||
ynh_secure_remove --file="$fpm_config_dir/pool.d/$app.conf"
|
||||
if [ -e $fpm_config_dir/conf.d/20-$app.ini ]; then
|
||||
ynh_secure_remove --file="$fpm_config_dir/conf.d/20-$app.ini"
|
||||
fi
|
||||
|
||||
if [ $dedicated_service -eq 1 ]; then
|
||||
# Remove the dedicated service PHP-FPM service for the app
|
||||
ynh_remove_systemd_config --service=$fpm_service
|
||||
# Remove the global PHP-FPM conf
|
||||
ynh_secure_remove --file="$fpm_config_dir/php-fpm-$app.conf"
|
||||
# Remove the service from the list of services known by YunoHost
|
||||
yunohost service remove $fpm_service
|
||||
elif ynh_package_is_installed --package="php${phpversion}-fpm"; then
|
||||
ynh_systemd_action --service_name=$fpm_service --action=reload
|
||||
fi
|
||||
|
||||
# If the PHP version used is not the default version for YunoHost
|
||||
# The second part with YNH_APP_PURGE is an ugly hack to guess that we're inside the remove script
|
||||
# (we don't actually care about its value, we just check its not empty hence it exists)
|
||||
if [ "$phpversion" != "$YNH_DEFAULT_PHP_VERSION" ] && [ -n "${YNH_APP_PURGE:-}" ] && dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
|
||||
# Remove app dependencies ... but ideally should happen via an explicit call from packager
|
||||
ynh_remove_app_dependencies
|
||||
fi
|
||||
}
|
||||
|
||||
# Install another version of PHP.
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# Legacy, to be remove on bullseye
|
||||
#
|
||||
# usage: ynh_install_php --phpversion=phpversion [--package=packages]
|
||||
# | arg: -v, --phpversion= - Version of PHP to install.
|
||||
# | arg: -p, --package= - Additionnal PHP packages to install
|
||||
#
|
||||
# Requires YunoHost version 3.8.1 or higher.
|
||||
ynh_install_php() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=vp
|
||||
local -A args_array=([v]=phpversion= [p]=package=)
|
||||
local phpversion
|
||||
local package
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
package=${package:-}
|
||||
|
||||
if [ "$phpversion" == "$YNH_DEFAULT_PHP_VERSION" ]; then
|
||||
ynh_die --message="Do not use ynh_install_php to install php$YNH_DEFAULT_PHP_VERSION"
|
||||
fi
|
||||
|
||||
ynh_install_app_dependencies "$package"
|
||||
}
|
||||
|
||||
# Remove the specific version of PHP used by the app.
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# Legacy, to be remove on bullseye
|
||||
#
|
||||
# usage: ynh_remove_php
|
||||
#
|
||||
# Requires YunoHost version 3.8.1 or higher.
|
||||
ynh_remove_php () {
|
||||
ynh_remove_app_dependencies
|
||||
ynh_systemd_action --service_name=$fpm_service --action=reload
|
||||
}
|
||||
|
||||
# Define the values to configure PHP-FPM
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
PSQL_ROOT_PWD_FILE=/etc/yunohost/psql
|
||||
PSQL_VERSION=13
|
||||
PSQL_VERSION=15
|
||||
|
||||
# Open a connection as a user
|
||||
#
|
||||
|
|
|
@ -18,11 +18,7 @@ ynh_app_setting_get() {
|
|||
ynh_handle_getopts_args "$@"
|
||||
app="${app:-$_globalapp}"
|
||||
|
||||
if [[ $key =~ (unprotected|protected|skipped)_ ]]; then
|
||||
yunohost app setting $app $key
|
||||
else
|
||||
ynh_app_setting "get" "$app" "$key"
|
||||
fi
|
||||
ynh_app_setting "get" "$app" "$key"
|
||||
}
|
||||
|
||||
# Set an application setting
|
||||
|
@ -45,11 +41,7 @@ ynh_app_setting_set() {
|
|||
ynh_handle_getopts_args "$@"
|
||||
app="${app:-$_globalapp}"
|
||||
|
||||
if [[ $key =~ (unprotected|protected|skipped)_ ]]; then
|
||||
yunohost app setting $app $key -v $value
|
||||
else
|
||||
ynh_app_setting "set" "$app" "$key" "$value"
|
||||
fi
|
||||
ynh_app_setting "set" "$app" "$key" "$value"
|
||||
}
|
||||
|
||||
# Delete an application setting
|
||||
|
@ -70,11 +62,7 @@ ynh_app_setting_delete() {
|
|||
ynh_handle_getopts_args "$@"
|
||||
app="${app:-$_globalapp}"
|
||||
|
||||
if [[ "$key" =~ (unprotected|skipped|protected)_ ]]; then
|
||||
yunohost app setting $app $key -d
|
||||
else
|
||||
ynh_app_setting "delete" "$app" "$key"
|
||||
fi
|
||||
ynh_app_setting "delete" "$app" "$key"
|
||||
}
|
||||
|
||||
# Small "hard-coded" interface to avoid calling "yunohost app" directly each
|
||||
|
|
|
@ -75,7 +75,7 @@ fi
|
|||
# usage: ynh_setup_source --dest_dir=dest_dir [--source_id=source_id] [--keep="file1 file2"] [--full_replace]
|
||||
# | arg: -d, --dest_dir= - Directory where to setup sources
|
||||
# | arg: -s, --source_id= - Name of the source, defaults to `main` (when the sources resource exists in manifest.toml) or (legacy) `app` otherwise
|
||||
# | arg: -k, --keep= - Space-separated list of files/folders that will be backup/restored in $dest_dir, such as a config file you don't want to overwrite. For example 'conf.json secrets.json logs/'
|
||||
# | arg: -k, --keep= - Space-separated list of files/folders that will be backup/restored in $dest_dir, such as a config file you don't want to overwrite. For example 'conf.json secrets.json logs' (no trailing `/` for folders)
|
||||
# | arg: -r, --full_replace= - Remove previous sources before installing new sources
|
||||
#
|
||||
# #### New 'sources' resources
|
||||
|
@ -244,9 +244,11 @@ ynh_setup_source() {
|
|||
|
||||
if [ "$src_format" = "docker" ]; then
|
||||
src_platform="${src_platform:-"linux/$YNH_ARCH"}"
|
||||
elif test -e "$local_src"; then
|
||||
cp $local_src $src_filename
|
||||
else
|
||||
if test -e "$local_src"; then
|
||||
cp $local_src $src_filename
|
||||
fi
|
||||
|
||||
[ -n "$src_url" ] || ynh_die "Couldn't parse SOURCE_URL from $src_file_path ?"
|
||||
|
||||
# If the file was prefetched but somehow doesn't match the sum, rm and redownload it
|
||||
|
|
|
@ -9,5 +9,5 @@ source /usr/share/yunohost/helpers
|
|||
# Backup destination
|
||||
backup_dir="${1}/data/xmpp"
|
||||
|
||||
ynh_backup /var/lib/metronome "${backup_dir}/var_lib_metronome"
|
||||
ynh_backup /var/xmpp-upload/ "${backup_dir}/var_xmpp-upload"
|
||||
[[ ! -d /var/lib/metronome ]] || ynh_backup /var/lib/metronome "${backup_dir}/var_lib_metronome" --not_mandatory
|
||||
[[ ! -d /var/xmpp-upload ]] || ynh_backup /var/xmpp-upload/ "${backup_dir}/var_xmpp-upload" --not_mandatory
|
||||
|
|
|
@ -11,7 +11,7 @@ do_pre_regen() {
|
|||
|
||||
# Add sury
|
||||
mkdir -p ${pending_dir}/etc/apt/sources.list.d/
|
||||
echo "deb https://packages.sury.org/php/ $(lsb_release --codename --short) main" > "${pending_dir}/etc/apt/sources.list.d/extra_php_version.list"
|
||||
echo "deb [signed-by=/etc/apt/trusted.gpg.d/extra_php_version.gpg] https://packages.sury.org/php/ $(lsb_release --codename --short) main" > "${pending_dir}/etc/apt/sources.list.d/extra_php_version.list"
|
||||
|
||||
# Ban some packages from sury
|
||||
echo "
|
||||
|
@ -23,19 +23,33 @@ Pin-Priority: 500" >>"${pending_dir}/etc/apt/preferences.d/extra_php_version"
|
|||
for package in $packages_to_refuse_from_sury; do
|
||||
echo "
|
||||
Package: $package
|
||||
Pin: origin \"packages.sury.org\"
|
||||
Pin: origin \"packages.sury.org\"
|
||||
Pin-Priority: -1" >>"${pending_dir}/etc/apt/preferences.d/extra_php_version"
|
||||
done
|
||||
|
||||
# Add yarn
|
||||
echo "deb [signed-by=/etc/apt/trusted.gpg.d/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > "${pending_dir}/etc/apt/sources.list.d/yarn.list"
|
||||
|
||||
# Ban everything from Yarn except Yarn
|
||||
echo "
|
||||
Package: *
|
||||
Pin: origin \"dl.yarnpkg.com\"
|
||||
Pin-Priority: -1
|
||||
|
||||
Package: yarn
|
||||
Pin: origin \"dl.yarnpkg.com\"
|
||||
Pin-Priority: 500" >>"${pending_dir}/etc/apt/preferences.d/yarn"
|
||||
|
||||
# Ban apache2, bind9
|
||||
echo "
|
||||
|
||||
# PLEASE READ THIS WARNING AND DON'T EDIT THIS FILE
|
||||
|
||||
# You are probably reading this file because you tried to install apache2 or
|
||||
# You are probably reading this file because you tried to install apache2 or
|
||||
# bind9. These 2 packages conflict with YunoHost.
|
||||
|
||||
# Installing apache2 will break nginx and break the entire YunoHost ecosystem
|
||||
# on your server, therefore don't remove those lines!
|
||||
# on your server, therefore don't remove those lines!
|
||||
|
||||
# You have been warned.
|
||||
|
||||
|
@ -69,6 +83,12 @@ do_post_regen() {
|
|||
wget --timeout 900 --quiet "https://packages.sury.org/php/apt.gpg" --output-document=- | gpg --dearmor >"/etc/apt/trusted.gpg.d/extra_php_version.gpg"
|
||||
fi
|
||||
|
||||
# Similar to Sury
|
||||
if [[ ! -s /etc/apt/trusted.gpg.d/yarn.gpg ]]
|
||||
then
|
||||
wget --timeout 900 --quiet "https://dl.yarnpkg.com/debian/pubkey.gpg" --output-document=- | gpg --dearmor >"/etc/apt/trusted.gpg.d/yarn.gpg"
|
||||
fi
|
||||
|
||||
# Make sure php7.4 is the default version when using php in cli
|
||||
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION
|
||||
then
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
backup_dir="$1/data/xmpp"
|
||||
|
||||
cp -a $backup_dir/var_lib_metronome/. /var/lib/metronome
|
||||
cp -a $backup_dir/var_xmpp-upload/. /var/xmpp-upload
|
||||
if [[ -e $backup_dir/var_lib_metronome/ ]]
|
||||
then
|
||||
cp -a $backup_dir/var_lib_metronome/. /var/lib/metronome
|
||||
fi
|
||||
|
||||
if [[ -e $backup_dir/var_xmpp-upload ]]
|
||||
then
|
||||
cp -a $backup_dir/var_xmpp-upload/. /var/xmpp-upload
|
||||
fi
|
||||
|
|
|
@ -588,7 +588,20 @@
|
|||
"migration_0024_rebuild_python_venv_disclaimer_rebuild": "Rebuilding the virtualenv will be attempted for the following apps (NB: the operation may take some time!): {rebuild_apps}",
|
||||
"migration_0024_rebuild_python_venv_failed": "Failed to rebuild the Python virtualenv for {app}. The app may not work as long as this is not resolved. You should fix the situation by forcing the upgrade of this app using `yunohost app upgrade --force {app}`.",
|
||||
"migration_0024_rebuild_python_venv_in_progress": "Now attempting to rebuild the Python virtualenv for `{app}`",
|
||||
"migration_description_0021_migrate_to_bullseye": "Upgrade the system to Debian Bullseye and YunoHost 11.x",
|
||||
"migration_0027_cleaning_up": "Cleaning up cache and packages not useful anymore...",
|
||||
"migration_0027_hgjghjghjgeneral_warning": "Please note that this migration is a delicate operation. The YunoHost team did its best to review and test it, but the migration might still break parts of the system or its apps.\n\nTherefore, it is recommended to:\n - Perform a backup of any critical data or app. More info on https://yunohost.org/backup;\n - Be patient after launching the migration: Depending on your Internet connection and hardware, it might take up to a few hours for everything to upgrade.",
|
||||
"migration_0027_main_upgrade": "Starting main upgrade...",
|
||||
"migration_0027_modified_files": "Please note that the following files were found to be manually modified and might be overwritten following the upgrade: {manually_modified_files}",
|
||||
"migration_0027_not_buster2": "The current Debian distribution is not Bullseye! If you already ran the Bullseye->Bookworm migration, then this error is symptomatic of the fact that the migration procedure was not 100% succesful (otherwise YunoHost would have flagged it as completed). It is recommended to investigate what happened with the support team, who will need the **full** log of the `migration, which can be found in Tools > Logs in the webadmin.",
|
||||
"migration_0027_not_enough_free_space": "Free space is pretty low in /var/! You should have at least 1GB free to run this migration.",
|
||||
"migration_0027_patch_yunohost_conflicts": "Applying patch to workaround conflict issue...",
|
||||
"migration_0027_patching_sources_list": "Patching the sources.lists...",
|
||||
"migration_0027_problematic_apps_warning": "Please note that the following possibly problematic installed apps were detected. It looks like those were not installed from the YunoHost app catalog, or are not flagged as 'working'. Consequently, it cannot be guaranteed that they will still work after the upgrade: {problematic_apps}",
|
||||
"migration_0027_start": "Starting migration to Bookworm",
|
||||
"migration_0027_still_on_buster_after_main_upgrade": "Something went wrong during the main upgrade, the system appears to still be on Debian Bullseye",
|
||||
"migration_0027_system_not_fully_up_to_date": "Your system is not fully up-to-date. Please perform a regular upgrade before running the migration to Bookworm.",
|
||||
"migration_0027_yunohost_upgrade": "Starting YunoHost core upgrade...",
|
||||
"migration_description_0021_migrate_to_bullseye": "Upgrade the system to Debian Bookworm and YunoHost 12",
|
||||
"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",
|
||||
"migration_description_0024_rebuild_python_venv": "Repair Python app after bullseye migration",
|
||||
|
|
|
@ -522,8 +522,8 @@
|
|||
"diagnosis_mail_outgoing_port_25_blocked_relay_vpn": "Algunos proveedores de internet no le permitirán desbloquear el puerto 25 porque no les importa la Neutralidad de la Red.<br> - Algunos proporcionan una alternativa usando <a href='https://yunohost.org/#/email_configure_relay'>un relay como servidor de correo</a> lo que implica que el relay podrá espiar tu tráfico de correo.<br>- Una alternativa buena para la privacidad es utilizar una VPN *con una IP pública dedicada* para evitar estas limitaciones. Mira en <a href='https://yunohost.org/#/vpn_advantage'>https://yunohost.org/#/vpn_advantage</a><br>- Otra alternativa es cambiar de proveedor de internet a <a href='https://yunohost.org/#/isp'>uno más amable con la Neutralidad de la Red</a>",
|
||||
"diagnosis_backports_in_sources_list": "Parece que apt (el gestor de paquetes) está configurado para usar el repositorio backports. A menos que realmente sepas lo que estás haciendo, desaconsejamos absolutamente instalar paquetes desde backports, ya que pueden provocar comportamientos intestables o conflictos en el sistema.",
|
||||
"diagnosis_basesystem_hardware_model": "El modelo de servidor es {model}",
|
||||
"additional_urls_already_removed": "La URL adicional '{url}' ya se ha eliminado para el permiso «{permission}»",
|
||||
"additional_urls_already_added": "La URL adicional '{url}' ya se ha añadido para el permiso «{permission}»",
|
||||
"additional_urls_already_removed": "URL adicional '{url}' ya eliminada en la URL adicional para permiso «{permission}»",
|
||||
"additional_urls_already_added": "URL adicional '{url}' ya añadida en la URL adicional para permiso «{permission}»",
|
||||
"config_apply_failed": "Falló la aplicación de la nueva configuración: {error}",
|
||||
"app_restore_script_failed": "Ha ocurrido un error dentro del script de restauración de aplicaciones",
|
||||
"app_config_unable_to_apply": "No se pudieron aplicar los valores del panel configuración.",
|
||||
|
@ -747,5 +747,10 @@
|
|||
"global_settings_setting_smtp_relay_host": "Host de retransmisión SMTP",
|
||||
"migration_0024_rebuild_python_venv_disclaimer_rebuild": "Se intentará reconstruir el virtualenv para las siguientes apps (NB: ¡la operación puede llevar algún tiempo!): {rebuild_apps}",
|
||||
"migration_description_0025_global_settings_to_configpanel": "Migración de la nomenclatura de ajustes globales heredada a la nomenclatura nueva y moderna",
|
||||
"registrar_infos": "Información sobre el registrador"
|
||||
}
|
||||
"registrar_infos": "Información sobre el registrador",
|
||||
"app_failed_to_download_asset": "Error al descargar el recurso '{source_id}' ({url}) para {app}: {out}",
|
||||
"app_corrupt_source": "YunoHost ha podido descargar el recurso '{source_id}' ({url}) para {app}, pero no coincide con la suma de comprobación esperada. Esto puede significar que ocurrió un fallo de red en tu servidor, o que el recurso ha sido modificado por el responsable de la aplicación (¿o un actor malicioso?) y los responsables de empaquetar esta aplicación para YunoHost necesitan investigar y actualizar el manifesto de la aplicación para reflejar estos cambios. \n Suma de control sha256 esperada: {expected_sha256}\n Suma de control sha256 descargada: {computed_sha256}\n Tamaño del archivo descargado: {size}",
|
||||
"app_change_url_failed": "No es possible cambiar la URL para {app}: {error}",
|
||||
"app_change_url_require_full_domain": "{app} no se puede mover a esta nueva URL porque requiere un dominio completo (es decir, con una ruta = /)",
|
||||
"app_change_url_script_failed": "Se ha producido un error en el script de modificación de la url"
|
||||
}
|
||||
|
|
|
@ -527,7 +527,7 @@
|
|||
"pattern_email_forward": "L'adresse électronique doit être valide, le symbole '+' étant accepté (par exemple : johndoe+yunohost@exemple.com)",
|
||||
"global_settings_setting_smtp_relay_password": "Mot de passe du relais SMTP",
|
||||
"diagnosis_package_installed_from_sury": "Des paquets du système devraient être rétrogradé de version",
|
||||
"additional_urls_already_added": "URL supplémentaire '{url}' déjà ajoutée pour la permission '{permission}'",
|
||||
"additional_urls_already_added": "L'URL supplémentaire '{url}' a déjà été ajoutée pour la permission '{permission}'",
|
||||
"unknown_main_domain_path": "Domaine ou chemin inconnu pour '{app}'. Vous devez spécifier un domaine et un chemin pour pouvoir spécifier une URL pour l'autorisation.",
|
||||
"show_tile_cant_be_enabled_for_regex": "Vous ne pouvez pas activer 'show_tile' pour le moment, cela car l'URL de l'autorisation '{permission}' est une expression régulière",
|
||||
"show_tile_cant_be_enabled_for_url_not_defined": "Vous ne pouvez pas activer 'show_tile' pour le moment, car vous devez d'abord définir une URL pour l'autorisation '{permission}'",
|
||||
|
@ -536,7 +536,7 @@
|
|||
"permission_protected": "L'autorisation {permission} est protégée. Vous ne pouvez pas ajouter ou supprimer le groupe visiteurs à/de cette autorisation.",
|
||||
"invalid_regex": "Regex non valide : '{regex}'",
|
||||
"app_label_deprecated": "Cette commande est obsolète ! Veuillez utiliser la nouvelle commande 'yunohost user permission update' pour gérer l'étiquette de l'application.",
|
||||
"additional_urls_already_removed": "URL supplémentaire '{url}' déjà supprimées pour la permission '{permission}'",
|
||||
"additional_urls_already_removed": "L'URL supplémentaire '{url}' a déjà été supprimée pour la permission '{permission}'",
|
||||
"invalid_number": "Doit être un nombre",
|
||||
"diagnosis_basesystem_hardware_model": "Le modèle/architecture du serveur est {model}",
|
||||
"diagnosis_backports_in_sources_list": "Il semble que le gestionnaire de paquet APT soit configuré pour utiliser le dépôt des rétro-portages (backports). A moins que vous ne sachiez vraiment ce que vous faites, nous vous déconseillons fortement d'installer des paquets provenant du dépôt 'backports', car cela risque de créer des instabilités ou des conflits sur votre système.",
|
||||
|
@ -766,5 +766,21 @@
|
|||
"group_mailalias_add": "L'alias de courrier électronique '{mail}' sera ajouté au groupe '{group}'",
|
||||
"group_user_add": "L'utilisateur '{user}' sera ajouté au groupe '{group}'",
|
||||
"group_user_remove": "L'utilisateur '{user}' sera retiré du groupe '{group}'",
|
||||
"group_mailalias_remove": "L'alias de courrier électronique '{mail}' sera supprimé du groupe '{group}'"
|
||||
"group_mailalias_remove": "L'alias de courrier électronique '{mail}' sera supprimé du groupe '{group}'",
|
||||
"ask_dyndns_recovery_password_explain": "Veuillez choisir un mot de passe de récupération pour votre domaine DynDNS, au cas où vous devriez le réinitialiser plus tard.",
|
||||
"ask_dyndns_recovery_password": "Mot de passe de récupération DynDNS",
|
||||
"ask_dyndns_recovery_password_explain_during_unsubscribe": "Veuillez saisir le mot de passe de récupération pour ce domaine DynDNS.",
|
||||
"dyndns_no_recovery_password": "Aucun mot de passe de récupération n'a été spécifié ! Si vous perdez le contrôle de ce domaine, vous devrez contacter un administrateur de l'équipe YunoHost !",
|
||||
"dyndns_subscribed": "Domaine DynDNS souscrit/enregistré",
|
||||
"dyndns_subscribe_failed": "Impossible de souscrire/de s'enregistrer au domaine DynDNS : {erreur}",
|
||||
"dyndns_unsubscribe_failed": "Impossible de se désinscrire du domaine DynDNS : {erreur}",
|
||||
"dyndns_unsubscribed": "Désinscription du domaine DynDNS",
|
||||
"dyndns_unsubscribe_denied": "Échec de la désinscription du domaine : informations d'identification non valides",
|
||||
"dyndns_unsubscribe_already_unsubscribed": "Le domaine est déjà désabonné/retiré",
|
||||
"dyndns_set_recovery_password_denied": "Échec de la définition du mot de passe de récupération : mot de passe non valide",
|
||||
"dyndns_set_recovery_password_unknown_domain": "Échec de la définition du mot de passe de récupération : le domaine n'est pas enregistré",
|
||||
"dyndns_set_recovery_password_invalid_password": "Échec de la définition du mot de passe de récupération : le mot de passe n'est pas assez fort/solide",
|
||||
"dyndns_set_recovery_password_failed": "Échec de la définition du mot de passe de récupération : {erreur}",
|
||||
"dyndns_set_recovery_password_success": "Mot de passe de récupération défini/configuré !",
|
||||
"log_dyndns_unsubscribe": "Se désabonner d'un sous-domaine YunoHost '{}'"
|
||||
}
|
||||
|
|
|
@ -612,7 +612,7 @@
|
|||
"domain_config_auth_consumer_key": "Chave consumidora",
|
||||
"log_domain_dns_push": "Enviar rexistros DNS para o dominio '{}'",
|
||||
"other_available_options": "... e outras {n} opcións dispoñibles non mostradas",
|
||||
"domain_dns_registrar_yunohost": "Este dominio un dos de nohost.me / nohost.st / ynh.fr e a configuración DNS xestionaa directamente YunoHost se máis requisitos. (mira o comando 'yunohost dyndns update')",
|
||||
"domain_dns_registrar_yunohost": "Este dominio é un dos de nohost.me / nohost.st / ynh.fr e a configuración DNS xestionaa directamente YunoHost sen máis requisitos. (mira o comando 'yunohost dyndns update')",
|
||||
"domain_dns_registrar_supported": "YunoHost detectou automáticamente que este dominio está xestionado pola rexistradora **{registrar}**. Se queres, YunoHost pode configurar automáticamente as súas zonas DNS, se proporcionas as credenciais de acceso á API. Podes ver a documentación sobre como obter as credenciais da API nesta páxina: https://yunohost.org/registrar_api_{registrar}. (Tamén podes configurar manualmente os rexistros DNS seguindo a documentación en https://yunohost.org/dns )",
|
||||
"domain_dns_push_partial_failure": "Actualización parcial dos rexistros DNS: informouse dalgúns avisos/erros.",
|
||||
"domain_config_auth_token": "Token de autenticación",
|
||||
|
@ -654,7 +654,7 @@
|
|||
"global_settings_setting_admin_strength": "Fortaleza do contrasinal de Admin",
|
||||
"global_settings_setting_user_strength": "Fortaleza do contrasinal da usuaria",
|
||||
"global_settings_setting_postfix_compatibility_help": "Compromiso entre compatibilidade e seguridade para o servidor Postfix. Aféctalle ao cifrado (e outros aspectos da seguridade)",
|
||||
"global_settings_setting_ssh_compatibility_help": "Compromiso entre compatibilidade e seguridade para o servidor SSH. Aféctalle ao cifrado (e outros aspectos da seguridade)",
|
||||
"global_settings_setting_ssh_compatibility_help": "Compromiso entre compatibilidade e seguridade para o servidor SSH. Aféctalle ao cifrado (e outros aspectos da seguridade). Le https://infosec.mozilla.org/guidelines/openssh for more info.",
|
||||
"global_settings_setting_ssh_password_authentication_help": "Permitir autenticación con contrasinal para SSH",
|
||||
"global_settings_setting_ssh_port": "Porto SSH",
|
||||
"global_settings_setting_webadmin_allowlist_help": "Enderezos IP con permiso para acceder á webadmin. Separados por vírgulas.",
|
||||
|
@ -766,5 +766,21 @@
|
|||
"group_mailalias_add": "Vaise engadir o alias de correo '{mail}' ao grupo '{group}'",
|
||||
"group_mailalias_remove": "Vaise quitar o alias de email '{mail}' do grupo '{group}'",
|
||||
"group_user_add": "Vaise engadir a '{user}' ao grupo '{grupo}'",
|
||||
"group_user_remove": "Vaise quitar a '{user}' do grupo '{grupo}'"
|
||||
"group_user_remove": "Vaise quitar a '{user}' do grupo '{grupo}'",
|
||||
"ask_dyndns_recovery_password_explain": "Elixe un contrasinal de recuperación para o teu dominio DynDNS, por se precisas restablecelo no futuro.",
|
||||
"ask_dyndns_recovery_password": "Contrasinal de recuperación DynDNS",
|
||||
"ask_dyndns_recovery_password_explain_during_unsubscribe": "Escribe o contrasinal de recuperación para este dominio DynDNS.",
|
||||
"dyndns_no_recovery_password": "Non se estableceu un contrasinal de recuperación! Se perdes o control sobre dominio precisarás contactar coa administración do equipo YunoHost!",
|
||||
"dyndns_subscribed": "Tes unha subscrición a un dominio DynDNS",
|
||||
"dyndns_subscribe_failed": "Non te subscribiches ao dominio DynDNS: {error}",
|
||||
"dyndns_unsubscribe_failed": "Non se retirou a subscrición ao dominio DynDNS: {error}",
|
||||
"dyndns_unsubscribed": "Retirada a subscrición ao dominio DynDNS",
|
||||
"dyndns_unsubscribe_denied": "Fallo ao intentar retirar subscrición: credenciais incorrectas",
|
||||
"dyndns_unsubscribe_already_unsubscribed": "Non tes unha subscrición ao dominio",
|
||||
"dyndns_set_recovery_password_denied": "Fallou o establecemento do contrasinal de recuperación: chave non válida",
|
||||
"dyndns_set_recovery_password_unknown_domain": "Fallo ao establecer o contrasinal de recuperación: dominio non rexistrado",
|
||||
"dyndns_set_recovery_password_invalid_password": "Fallo ao establecer contrasinal de recuperación: o contrasinal non é suficientemente forte",
|
||||
"dyndns_set_recovery_password_failed": "Fallo ao establecer o contrasinal de recuperación: {error}",
|
||||
"dyndns_set_recovery_password_success": "Estableceuse o contrasinal de recuperación!",
|
||||
"log_dyndns_unsubscribe": "Retirar subscrición para o subdominio YunoHost '{}'"
|
||||
}
|
||||
|
|
|
@ -391,5 +391,54 @@
|
|||
"log_letsencrypt_cert_renew": "Memperbarui sertifikat Let's Encrypt '{}'",
|
||||
"log_selfsigned_cert_install": "Memasang sertifikat ditandai sendiri pada domain '{}'",
|
||||
"log_user_permission_reset": "Mengatur ulang izin '{}'",
|
||||
"domain_config_xmpp": "Pesan Langsung (XMPP)"
|
||||
"domain_config_xmpp": "Pesan Langsung (XMPP)",
|
||||
"diagnosis_http_connection_error": "Masalah jaringan: tidak dapat terhubung dengan domain yang diminta, sangat mungkin terputus.",
|
||||
"dyndns_ip_updated": "IP Anda diperbarui di DynDNS",
|
||||
"ask_dyndns_recovery_password_explain": "Pilih kata sandi pemulihan untuk domain DynDNS Anda.",
|
||||
"ask_dyndns_recovery_password": "Kata sandi pemulihan DynDNS",
|
||||
"backup_output_directory_not_empty": "Anda harus memilih direktori yang kosong",
|
||||
"service_reload_or_restart_failed": "Tidak dapat memuat atau memulai ulang layanan '{service}'\n\nLog layanan baru-baru ini:{logs}",
|
||||
"service_reload_failed": "Tidak dapat memuat ulang layanan '{service}'\n\nLog layanan baru-baru ini:{logs}",
|
||||
"service_start_failed": "Tidak dapat memulai layanan '{service}'\n\nLog layanan baru-baru ini: {logs}",
|
||||
"diagnosis_apps_deprecated_practices": "Versi aplikasi yang dipasang ini masih menggunakan praktik pengemasan yang lama. Anda lebih baik untuk memperbarui aplikasi tersebut.",
|
||||
"diagnosis_dns_bad_conf": "Beberapa rekaman DNS untuk domain {domain} ada yang tidak ada atau salah (kategori {category})",
|
||||
"diagnosis_dns_good_conf": "Rekaman DNS untuk domain {domain} sudah diatur dengan benar (kategori {category})",
|
||||
"dyndns_unavailable": "Domain '{domain}' tidak tersedia.",
|
||||
"dyndns_set_recovery_password_denied": "Tidak dapat menyetel kata sandi pemulihan: tidak valid",
|
||||
"dyndns_set_recovery_password_unknown_domain": "Tidak dapat menyetel kata sandi pemulihan: domain belum terdaftar",
|
||||
"dyndns_set_recovery_password_invalid_password": "Tidak dapat menyetel kata sandi pemulihan: kata sandi tidak cukup kuat",
|
||||
"dyndns_set_recovery_password_failed": "Tidak dapat menyetel kata sandi pemulihan: {error}",
|
||||
"dyndns_set_recovery_password_success": "Kata sandi pemulihan berhasil disetel!",
|
||||
"file_does_not_exist": "Berkas {path} tidak ada.",
|
||||
"firewall_reload_failed": "Tidak dapat memuat ulang tembok api",
|
||||
"firewall_reloaded": "Tembok api dimuat ulang",
|
||||
"migration_description_0023_postgresql_11_to_13": "Migrasi basis data dari PostgreSQL 11 ke 13",
|
||||
"service_enabled": "Layanan '{service}' akan secara mandiri dimulai saat pemulaian.",
|
||||
"service_reloaded_or_restarted": "Layanan {service} dimuat atau dimulai ulang",
|
||||
"service_stopped": "Layanan '{service}' diberhentikan",
|
||||
"service_unknown": "Layanan yang tidak diketahui: '{service}'",
|
||||
"updating_apt_cache": "Mengambil pembaruan yang tersedia untuk paket sistem...",
|
||||
"group_mailalias_remove": "Alias surel '{mail}' akan dihapus dari kelompok '{group}'",
|
||||
"migration_description_0021_migrate_to_bullseye": "Peningkatan sistem ke Debian Bullseye dan YunoHost 11.x",
|
||||
"migration_description_0024_rebuild_python_venv": "Memperbaiki aplikasi Python setelah migrasi Bullseye",
|
||||
"service_disable_failed": "Tidak dapat membuat layanan '{service}' dimulai saat pemulaian.\n\nLog layanan baru-baru ini:{logs}",
|
||||
"service_disabled": "Layanan '{service}' tidak akan dimulai kembali saat pemulaian.",
|
||||
"tools_upgrade_failed": "Tidak dapat memperbarui paket: {packages_list}",
|
||||
"global_settings_setting_nginx_redirect_to_https": "Paksa HTTPS",
|
||||
"backup_archive_system_part_not_available": "Segmen '{part}' tidak tersedia di cadangan ini",
|
||||
"backup_output_directory_forbidden": "Pilih direktori yang berbeda. Cadangan tidak dapat dibuat di /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var, atau subfolder dari /home/yunohost.backup/archives",
|
||||
"ask_dyndns_recovery_password_explain_during_unsubscribe": "Masukkan kata sandi pemulihan untuk domain DynDNS ini.",
|
||||
"backup_output_symlink_dir_broken": "Direktori arsip Anda '{path}' rusak penautannya. Mungkin Anda lupa untuk menambatkan ulang atau memasukkan kembali penyimpanan tujuan penautan direktori arsip tersebut.",
|
||||
"diagnosis_apps_not_in_app_catalog": "Aplikasi ini tidak ada di katalog aplikasi YunoHost. Jika aplikasi ini ada di sana sebelumnya dan dihapus, Anda disarankan untuk melepas aplikasi ini dikarenakan ini tidak akan menerima pembaruan dan mungkin bisa menghancurkan integritas dan keamanan sistem Anda.",
|
||||
"dyndns_ip_update_failed": "Tidak dapat memperbarui IP Anda di DynDNS",
|
||||
"service_restarted": "Layanan {service} dimulai ulang",
|
||||
"service_started": "Layanan '{service}' dimulai",
|
||||
"service_stop_failed": "Tidak dapat menghentikan layanan '{service}'\n\nLog layanan baru-baru ini: {logs}",
|
||||
"apps_catalog_failed_to_download": "Tidak dapat mengunduh katalog aplikasi {apps_catalog}: {error}",
|
||||
"backup_archive_corrupted": "Sepertinya arsip cadangan '{archive}' rusak: {error}",
|
||||
"diagnosis_found_errors": "{errors} masalah signifikan ditemukan terkait dengan {category}!",
|
||||
"restore_system_part_failed": "Tidak dapat memulihkan segmen '{part}'",
|
||||
"service_enable_failed": "Tidak dapat membuat layanan '{service}' dimulai mandiri saat pemulaian.\n\nLog layanan baru-baru ini:{logs}",
|
||||
"service_not_reloading_because_conf_broken": "Tidak memuat atau memulai ulang layanan '{name}' karena konfigurasinya rusak: {errors}",
|
||||
"service_reloaded": "Layanan {service} dimuat ulang"
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
"backup_applying_method_custom": "Wywołuję niestandardową metodę tworzenia kopii zapasowych '{method}'...",
|
||||
"app_remove_after_failed_install": "Usuwanie aplikacji po niepowodzeniu instalacji...",
|
||||
"app_upgrade_script_failed": "Wystąpił błąd w skrypcie aktualizacji aplikacji",
|
||||
"apps_catalog_init_success": "Zainicjowano system katalogu aplikacji!",
|
||||
"apps_catalog_init_success": "System katalogu aplikacji został zainicjowany!",
|
||||
"apps_catalog_obsolete_cache": "Pamięć podręczna katalogu aplikacji jest pusta lub przestarzała.",
|
||||
"app_extraction_failed": "Nie można wyodrębnić plików instalacyjnych",
|
||||
"app_packaging_format_not_supported": "Ta aplikacja nie może zostać zainstalowana, ponieważ jej format opakowania nie jest obsługiwany przez twoją wersję YunoHost. Prawdopodobnie powinieneś rozważyć aktualizację swojego systemu.",
|
||||
|
@ -183,7 +183,7 @@
|
|||
"app_failed_to_download_asset": "Nie udało się pobrać zasobu '{source_id}' ({url}) dla {app}: {out}",
|
||||
"backup_with_no_backup_script_for_app": "Aplikacja '{app}' nie posiada skryptu kopii zapasowej. Ignorowanie.",
|
||||
"backup_with_no_restore_script_for_app": "Aplikacja {app} nie posiada skryptu przywracania, co oznacza, że nie będzie można automatycznie przywrócić kopii zapasowej tej aplikacji.",
|
||||
"certmanager_acme_not_configured_for_domain": "Wyzwanie ACME nie może zostać uruchomione dla domeny {domain}, ponieważ jej konfiguracja nginx nie zawiera odpowiedniego fragmentu kodu... Upewnij się, że konfiguracja nginx jest aktualna, używając polecenia yunohost tools regen-conf nginx --dry-run --with-diff.",
|
||||
"certmanager_acme_not_configured_for_domain": "Wyzwanie ACME nie może być teraz uruchomione dla {domain}, ponieważ jego konfiguracja nginx nie zawiera odpowiedniego fragmentu kodu… Upewnij się, że twoja konfiguracja nginx jest aktualna, używając `yunohost tools regen-conf nginx --dry-run --with-diff`.",
|
||||
"certmanager_domain_dns_ip_differs_from_public_ip": "Rekordy DNS dla domeny '{domain}' różnią się od adresu IP tego serwera. Sprawdź kategorię 'Rekordy DNS' (podstawowe) w diagnozie, aby uzyskać więcej informacji. Jeśli niedawno dokonałeś zmiany rekordu A, poczekaj, aż zostanie on zaktualizowany (można skorzystać z narzędzi online do sprawdzania propagacji DNS). (Jeśli wiesz, co robisz, użyj opcji '--no-checks', aby wyłączyć te sprawdzania.)",
|
||||
"confirm_app_install_danger": "UWAGA! Ta aplikacja jest wciąż w fazie eksperymentalnej (jeśli nie działa jawnie)! Prawdopodobnie NIE powinieneś jej instalować, chyba że wiesz, co robisz. NIE ZOSTANIE udzielone wsparcie, jeśli ta aplikacja nie będzie działać poprawnie lub spowoduje uszkodzenie systemu... Jeśli mimo to jesteś gotów podjąć to ryzyko, wpisz '{answers}",
|
||||
"confirm_app_install_thirdparty": "UWAGA! Ta aplikacja nie jest częścią katalogu aplikacji YunoHost. Instalowanie aplikacji innych firm może naruszyć integralność i bezpieczeństwo systemu. Prawdopodobnie NIE powinieneś jej instalować, chyba że wiesz, co robisz. NIE ZOSTANIE udzielone wsparcie, jeśli ta aplikacja nie będzie działać poprawnie lub spowoduje uszkodzenie systemu... Jeśli mimo to jesteś gotów podjąć to ryzyko, wpisz '{answers}'",
|
||||
|
@ -192,19 +192,19 @@
|
|||
"config_no_panel": "Nie znaleziono panelu konfiguracji.",
|
||||
"config_unknown_filter_key": "Klucz filtru '{filter_key}' jest niepoprawny.",
|
||||
"config_validate_email": "Proszę podać poprawny adres e-mail",
|
||||
"backup_hook_unknown": "Nieznany jest hook kopii zapasowej '{hook}'.",
|
||||
"backup_no_uncompress_archive_dir": "Nie istnieje taki katalog nieskompresowanego archiwum.",
|
||||
"backup_output_symlink_dir_broken": "Twój katalog archiwum '{path}' to uszkodzony dowiązanie symboliczne. Być może zapomniałeś o ponownym zamontowaniu lub podłączeniu nośnika przechowującego, do którego on wskazuje.",
|
||||
"backup_system_part_failed": "Nie można wykonać kopii zapasowej części systemu '{part}'",
|
||||
"backup_hook_unknown": "Nieznany jest hook kopii zapasowej '{hook}'",
|
||||
"backup_no_uncompress_archive_dir": "Nie istnieje taki katalog nieskompresowanego archiwum",
|
||||
"backup_output_symlink_dir_broken": "Twój katalog archiwum ‘{path}’ to uszkodzony symlink. Być może zapomniałeś o ponownym zamontowaniu lub podłączeniu nośnika przechowującego, do którego on wskazuje.",
|
||||
"backup_system_part_failed": "Nie udało się wykonać kopii zapasowej części systemu ‘{part}’",
|
||||
"config_validate_color": "Powinien być poprawnym szesnastkowym kodem koloru RGB.",
|
||||
"config_validate_date": "Data powinna być poprawna w formacie RRRR-MM-DD",
|
||||
"config_validate_time": "Podaj poprawny czas w formacie GG:MM",
|
||||
"certmanager_domain_not_diagnosed_yet": "Nie ma jeszcze wyników diagnozy dla domeny {domain}. Proszę ponownie uruchomić diagnozę dla kategorii 'Rekordy DNS' i 'Strona internetowa' w sekcji diagnozy, aby sprawdzić, czy domena jest gotowa do użycia Let's Encrypt. (Jeśli wiesz, co robisz, użyj opcji '--no-checks', aby wyłączyć te sprawdzania.)",
|
||||
"certmanager_cannot_read_cert": "Wystąpił problem podczas próby otwarcia bieżącego certyfikatu dla domeny {domain} (plik: {file}), przyczyna: {reason}",
|
||||
"certmanager_no_cert_file": "Nie można odczytać pliku certyfikatu dla domeny {domain} (plik: {file}).",
|
||||
"certmanager_self_ca_conf_file_not_found": "Nie można znaleźć pliku konfiguracyjnego dla autorytetu samopodpisującego (plik: {file})",
|
||||
"backup_running_hooks": "Uruchamianie hooków kopii zapasowej...",
|
||||
"backup_permission": "Uprawnienia kopii zapasowej dla aplikacji {app}",
|
||||
"certmanager_no_cert_file": "Nie można odczytać pliku certyfikatu dla domeny {domain} (plik: {file})",
|
||||
"certmanager_self_ca_conf_file_not_found": "Nie można znaleźć pliku konfiguracyjnego dla samodzielnie podpisanego upoważnienia do (file: {file})",
|
||||
"backup_running_hooks": "Uruchamianie kopii zapasowej hooków...",
|
||||
"backup_permission": "Uprawnienia do tworzenia kopii zapasowej dla aplikacji {app}",
|
||||
"certmanager_domain_cert_not_selfsigned": "Certyfikat dla domeny {domain} nie jest samopodpisany. Czy na pewno chcesz go zastąpić? (Użyj opcji '--force', aby to zrobić.)",
|
||||
"config_action_disabled": "Nie można uruchomić akcji '{action}', ponieważ jest ona wyłączona. Upewnij się, że spełnione są jej ograniczenia. Pomoc: {help}",
|
||||
"config_action_failed": "Nie udało się uruchomić akcji '{action}': {error}",
|
||||
|
@ -214,7 +214,7 @@
|
|||
"confirm_app_insufficient_ram": "UWAGA! Ta aplikacja wymaga {required} pamięci RAM do zainstalowania/aktualizacji, a obecnie dostępne jest tylko {current}. Nawet jeśli aplikacja mogłaby działać, proces instalacji/aktualizacji wymaga dużej ilości pamięci RAM, więc serwer może się zawiesić i niepowodzenie może być katastrofalne. Jeśli mimo to jesteś gotów podjąć to ryzyko, wpisz '{answers}'",
|
||||
"app_not_upgraded_broken_system": "Aplikacja '{failed_app}' nie powiodła się w procesie aktualizacji i spowodowała uszkodzenie systemu. W rezultacie anulowane zostały aktualizacje następujących aplikacji: {apps}",
|
||||
"app_not_upgraded_broken_system_continue": "Aplikacja '{failed_app}' nie powiodła się w procesie aktualizacji i spowodowała uszkodzenie systemu (parametr --continue-on-failure jest ignorowany). W rezultacie anulowane zostały aktualizacje następujących aplikacji: {apps}",
|
||||
"certmanager_domain_http_not_working": "Domena {domain} wydaje się niedostępna przez HTTP. Sprawdź kategorię 'Strona internetowa' diagnostyki, aby uzyskać więcej informacji. (Jeśli wiesz, co robisz, użyj opcji '--no-checks', aby wyłączyć te sprawdzania.)",
|
||||
"certmanager_domain_http_not_working": "Domena {domain} nie wydaje się być dostępna przez HTTP. Sprawdź kategorię 'Strona internetowa' diagnostyki, aby uzyskać więcej informacji. (Jeśli wiesz, co robisz, użyj opcji '--no-checks', aby wyłączyć te sprawdzania.)",
|
||||
"migration_0021_system_not_fully_up_to_date": "Twój system nie jest w pełni zaktualizowany! Proszę, wykonaj zwykłą aktualizację oprogramowania zanim rozpoczniesz migrację na system Bullseye.",
|
||||
"global_settings_setting_smtp_relay_port": "Port przekaźnika SMTP",
|
||||
"domain_config_cert_renew": "Odnów certyfikat Let's Encrypt",
|
||||
|
@ -274,5 +274,12 @@
|
|||
"global_settings_setting_smtp_allow_ipv6_help": "Zezwól na wykorzystywanie IPv7 do odbierania i wysyłania maili",
|
||||
"global_settings_setting_ssh_password_authentication": "Logowanie hasłem",
|
||||
"diagnosis_backports_in_sources_list": "Wygląda na to że apt (menedżer pakietów) został skonfigurowany tak, aby wykorzystywać repozytorium backported. Nie zalecamy wykorzystywania repozytorium backported, ponieważ może powodować problemy ze stabilnością i/lub konflikty z konfiguracją. No chyba, że wiesz co robisz.",
|
||||
"domain_config_xmpp_help": "Uwaga: niektóre funkcje XMPP będą wymagały aktualizacji rekordów DNS i odnowienia certyfikatu Lets Encrypt w celu ich włączenia"
|
||||
"domain_config_xmpp_help": "Uwaga: niektóre funkcje XMPP będą wymagały aktualizacji rekordów DNS i odnowienia certyfikatu Lets Encrypt w celu ich włączenia",
|
||||
"ask_dyndns_recovery_password_explain": "Proszę wybrać hasło odzyskiwania dla swojej domeny DynDNS, na wypadek gdybyś musiał go później zresetować.",
|
||||
"ask_dyndns_recovery_password_explain_during_unsubscribe": "Proszę wprowadzić hasło odzyskiwania dla tej domeny DynDNS.",
|
||||
"certmanager_unable_to_parse_self_CA_name": "Nie można spasować nazwy organu samopodpisywanego (pliku: {file})",
|
||||
"app_corrupt_source": "YunoHost był w stanie pobrać zasób ‘{source_id}’ ({url}) dla {app}, ale zasób nie pasuje do oczekiwanego sumy kontrolnej. Może to oznaczać, że na twoim serwerze wystąpiła tymczasowa awaria sieci, LUB zasób został jakoś zmieniony przez dostawcę usługi (lub złośliwego aktora?) i pakowacze YunoHost muszą zbadać sprawę i zaktualizować manifest aplikacji, aby odzwierciedlić tę zmianę. \nOczekiwana suma kontrolna sha256: {expected_sha256} \nPobrana suma kontrolna sha256: {computed_sha256} \nRozmiar pobranego pliku: {size}”",
|
||||
"ask_dyndns_recovery_password": "Hasło odzyskiwania DynDNS",
|
||||
"certmanager_hit_rate_limit": "Zbyt wiele certyfikatów zostało ostatnio wydanych dla tej dokładnej grupy domen {domain}. Spróbuj ponownie później. Zobacz https://letsencrypt.org/docs/rate-limits/ aby uzyskać więcej informacji",
|
||||
"apps_failed_to_upgrade_line": "\n * {app_id} (aby zobaczyć odpowiedni dziennik, wykonaj ‘yunohost log show {operation_logger_name}’)"
|
||||
}
|
||||
|
|
|
@ -15,5 +15,10 @@
|
|||
"additional_urls_already_added": "Ek URL '{url}' zaten '{permission}' izni için ek URL'ye eklendi",
|
||||
"additional_urls_already_removed": "Ek URL '{url}', '{permission}' izni için ek URL'de zaten kaldırıldı",
|
||||
"app_action_cannot_be_ran_because_required_services_down": "Bu eylemi gerçekleştirmek için şu servisler çalışıyor olmalıdır: {services}. Devam etmek için onları yeniden başlatın (ve muhtemelen neden çalışmadığını araştırın).",
|
||||
"app_arch_not_supported": "Bu uygulama yalnızca {required} işlemci mimarisi üzerine kurulabilir ancak sunucunuzun işlemci mimarisi {current}."
|
||||
}
|
||||
"app_arch_not_supported": "Bu uygulama yalnızca {required} işlemci mimarisi üzerine kurulabilir ancak sunucunuzun işlemci mimarisi {current}.",
|
||||
"app_argument_choice_invalid": "'{name}'' için geçerli bir değer giriniz '{value}' mevcut seçimlerin arasında değil ({choices})",
|
||||
"app_change_url_failed": "{app}: {error} için url değiştirilemedi",
|
||||
"app_argument_required": "'{name}' değeri gerekli",
|
||||
"app_argument_invalid": "'{name}': {error} için geçerli bir değer giriniz",
|
||||
"app_argument_password_no_default": "'{name}': çözümlenirken bir hata meydana geldi. Parola argümanı güvenlik nedeniyle varsayılan değer alamaz"
|
||||
}
|
||||
|
|
|
@ -70,26 +70,10 @@ user:
|
|||
help: The full name of the user. For example 'Camille Dupont'
|
||||
extra:
|
||||
ask: ask_fullname
|
||||
required: False
|
||||
required: True
|
||||
pattern: &pattern_fullname
|
||||
- !!str ^([^\W_]{1,30}[ ,.'-]{0,3})+$
|
||||
- "pattern_fullname"
|
||||
-f:
|
||||
full: --firstname
|
||||
help: Deprecated. Use --fullname instead.
|
||||
extra:
|
||||
required: False
|
||||
pattern: &pattern_firstname
|
||||
- !!str ^([^\W\d_]{1,30}[ ,.'-]{0,3})+$
|
||||
- "pattern_firstname"
|
||||
-l:
|
||||
full: --lastname
|
||||
help: Deprecated. Use --fullname instead.
|
||||
extra:
|
||||
required: False
|
||||
pattern: &pattern_lastname
|
||||
- !!str ^([^\W\d_]{1,30}[ ,.'-]{0,3})+$
|
||||
- "pattern_lastname"
|
||||
-p:
|
||||
full: --password
|
||||
help: User password
|
||||
|
@ -147,16 +131,6 @@ user:
|
|||
help: The full name of the user. For example 'Camille Dupont'
|
||||
extra:
|
||||
pattern: *pattern_fullname
|
||||
-f:
|
||||
full: --firstname
|
||||
help: Deprecated. Use --fullname instead.
|
||||
extra:
|
||||
pattern: *pattern_firstname
|
||||
-l:
|
||||
full: --lastname
|
||||
help: Deprecated. Use --fullname instead.
|
||||
extra:
|
||||
pattern: *pattern_lastname
|
||||
-m:
|
||||
full: --mail
|
||||
extra:
|
||||
|
@ -553,17 +527,6 @@ domain:
|
|||
help: If removing a DynDNS domain, unsubscribe from the DynDNS service with a password
|
||||
extra:
|
||||
pattern: *pattern_password
|
||||
|
||||
|
||||
### domain_dns_conf()
|
||||
dns-conf:
|
||||
deprecated: true
|
||||
action_help: Generate sample DNS configuration for a domain
|
||||
arguments:
|
||||
domain:
|
||||
help: Target domain
|
||||
extra:
|
||||
pattern: *pattern_domain
|
||||
|
||||
### domain_maindomain()
|
||||
main-domain:
|
||||
|
@ -578,54 +541,6 @@ domain:
|
|||
extra:
|
||||
pattern: *pattern_domain
|
||||
|
||||
### certificate_status()
|
||||
cert-status:
|
||||
deprecated: true
|
||||
action_help: List status of current certificates (all by default).
|
||||
arguments:
|
||||
domain_list:
|
||||
help: Domains to check
|
||||
nargs: "*"
|
||||
--full:
|
||||
help: Show more details
|
||||
action: store_true
|
||||
|
||||
### certificate_install()
|
||||
cert-install:
|
||||
deprecated: true
|
||||
action_help: Install Let's Encrypt certificates for given domains (all by default).
|
||||
arguments:
|
||||
domain_list:
|
||||
help: Domains for which to install the certificates
|
||||
nargs: "*"
|
||||
--force:
|
||||
help: Install even if current certificate is not self-signed
|
||||
action: store_true
|
||||
--no-checks:
|
||||
help: Does not perform any check that your domain seems correctly configured (DNS, reachability) before attempting to install. (Not recommended)
|
||||
action: store_true
|
||||
--self-signed:
|
||||
help: Install self-signed certificate instead of Let's Encrypt
|
||||
action: store_true
|
||||
|
||||
### certificate_renew()
|
||||
cert-renew:
|
||||
deprecated: true
|
||||
action_help: Renew the Let's Encrypt certificates for given domains (all by default).
|
||||
arguments:
|
||||
domain_list:
|
||||
help: Domains for which to renew the certificates
|
||||
nargs: "*"
|
||||
--force:
|
||||
help: Ignore the validity threshold (30 days)
|
||||
action: store_true
|
||||
--email:
|
||||
help: Send an email to root with logs if some renewing fails
|
||||
action: store_true
|
||||
--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
|
||||
|
||||
### domain_url_available()
|
||||
url-available:
|
||||
hide_in_help: True
|
||||
|
@ -934,14 +849,14 @@ app:
|
|||
help: Custom name for the app
|
||||
-a:
|
||||
full: --args
|
||||
help: Serialized arguments for app script (i.e. "domain=domain.tld&path=/path")
|
||||
help: Serialized arguments for app script (i.e. "domain=domain.tld&path=/path&init_main_permission=visitors")
|
||||
-n:
|
||||
full: --no-remove-on-failure
|
||||
help: Debug option to avoid removing the app on a failed installation
|
||||
action: store_true
|
||||
-f:
|
||||
full: --force
|
||||
help: Do not ask confirmation if the app is not safe to use (low quality, experimental or 3rd party)
|
||||
help: Do not ask confirmation if the app is not safe to use (low quality, experimental or 3rd party), or when the app displays a post-install notification
|
||||
action: store_true
|
||||
|
||||
### app_remove()
|
||||
|
@ -980,7 +895,7 @@ app:
|
|||
action: store_true
|
||||
-c:
|
||||
full: --continue-on-failure
|
||||
help: Continue to upgrade apps event if one or more upgrade failed
|
||||
help: Continue to upgrade apps even if one or more upgrade failed
|
||||
action: store_true
|
||||
|
||||
### app_change_url()
|
||||
|
|
|
@ -227,7 +227,7 @@
|
|||
redact = true
|
||||
|
||||
[gandi.api_protocol]
|
||||
type = "string"
|
||||
type = "select"
|
||||
choices.rpc = "RPC"
|
||||
choices.rest = "REST"
|
||||
default = "rest"
|
||||
|
|
|
@ -144,17 +144,11 @@ def init_logging(interface="cli", debug=False, quiet=False, logdir="/var/log/yun
|
|||
"version": 1,
|
||||
"disable_existing_loggers": True,
|
||||
"formatters": {
|
||||
"console": {
|
||||
"format": "%(relativeCreated)-5d %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s"
|
||||
"tty-debug": {
|
||||
"format": "%(relativeCreated)-4d %(level_with_color)s %(message)s"
|
||||
},
|
||||
"tty-debug": {"format": "%(relativeCreated)-4d %(fmessage)s"},
|
||||
"precise": {
|
||||
"format": "%(asctime)-15s %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s"
|
||||
},
|
||||
},
|
||||
"filters": {
|
||||
"action": {
|
||||
"()": "moulinette.utils.log.ActionFilter",
|
||||
"format": "%(asctime)-15s %(levelname)-8s %(name)s.%(funcName)s - %(message)s"
|
||||
},
|
||||
},
|
||||
"handlers": {
|
||||
|
@ -175,7 +169,6 @@ def init_logging(interface="cli", debug=False, quiet=False, logdir="/var/log/yun
|
|||
"class": "logging.FileHandler",
|
||||
"formatter": "precise",
|
||||
"filename": logfile,
|
||||
"filters": ["action"],
|
||||
},
|
||||
},
|
||||
"loggers": {
|
||||
|
|
266
src/app.py
266
src/app.py
|
@ -28,9 +28,9 @@ import tempfile
|
|||
import copy
|
||||
from typing import List, Tuple, Dict, Any, Iterator, Optional
|
||||
from packaging import version
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import Moulinette, m18n
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.process import run_commands, check_output
|
||||
from moulinette.utils.filesystem import (
|
||||
read_file,
|
||||
|
@ -71,7 +71,7 @@ from yunohost.app_catalog import ( # noqa
|
|||
APPS_CATALOG_LOGOS,
|
||||
)
|
||||
|
||||
logger = getActionLogger("yunohost.app")
|
||||
logger = getLogger("yunohost.app")
|
||||
|
||||
APPS_SETTING_PATH = "/etc/yunohost/apps/"
|
||||
APP_TMP_WORKDIRS = "/var/cache/yunohost/app_tmp_work_dirs"
|
||||
|
@ -186,11 +186,17 @@ def app_info(app, full=False, upgradable=False):
|
|||
ret["from_catalog"] = from_catalog
|
||||
|
||||
# Hydrate app notifications and doc
|
||||
rendered_doc = {}
|
||||
for pagename, content_per_lang in ret["manifest"]["doc"].items():
|
||||
for lang, content in content_per_lang.items():
|
||||
ret["manifest"]["doc"][pagename][lang] = _hydrate_app_template(
|
||||
content, settings
|
||||
)
|
||||
rendered_content = _hydrate_app_template(content, settings)
|
||||
# Rendered content may be empty because of conditional blocks
|
||||
if not rendered_content:
|
||||
continue
|
||||
if pagename not in rendered_doc:
|
||||
rendered_doc[pagename] = {}
|
||||
rendered_doc[pagename][lang] = rendered_content
|
||||
ret["manifest"]["doc"] = rendered_doc
|
||||
|
||||
# Filter dismissed notification
|
||||
ret["manifest"]["notifications"] = {
|
||||
|
@ -201,9 +207,16 @@ def app_info(app, full=False, upgradable=False):
|
|||
|
||||
# Hydrate notifications (also filter uneeded post_upgrade notification based on version)
|
||||
for step, notifications in ret["manifest"]["notifications"].items():
|
||||
rendered_notifications = {}
|
||||
for name, content_per_lang in notifications.items():
|
||||
for lang, content in content_per_lang.items():
|
||||
notifications[name][lang] = _hydrate_app_template(content, settings)
|
||||
rendered_content = _hydrate_app_template(content, settings)
|
||||
if not rendered_content:
|
||||
continue
|
||||
if name not in rendered_notifications:
|
||||
rendered_notifications[name] = {}
|
||||
rendered_notifications[name][lang] = rendered_content
|
||||
ret["manifest"]["notifications"][step] = rendered_notifications
|
||||
|
||||
ret["is_webapp"] = "domain" in settings and "path" in settings
|
||||
|
||||
|
@ -238,8 +251,8 @@ def _app_upgradable(app_infos):
|
|||
# Determine upgradability
|
||||
|
||||
app_in_catalog = app_infos.get("from_catalog")
|
||||
installed_version = version.parse(app_infos.get("version", "0~ynh0"))
|
||||
version_in_catalog = version.parse(
|
||||
installed_version = _parse_app_version(app_infos.get("version", "0~ynh0"))
|
||||
version_in_catalog = _parse_app_version(
|
||||
app_infos.get("from_catalog", {}).get("manifest", {}).get("version", "0~ynh0")
|
||||
)
|
||||
|
||||
|
@ -254,25 +267,7 @@ def _app_upgradable(app_infos):
|
|||
):
|
||||
return "bad_quality"
|
||||
|
||||
# If the app uses the standard version scheme, use it to determine
|
||||
# upgradability
|
||||
if "~ynh" in str(installed_version) and "~ynh" in str(version_in_catalog):
|
||||
if installed_version < version_in_catalog:
|
||||
return "yes"
|
||||
else:
|
||||
return "no"
|
||||
|
||||
# Legacy stuff for app with old / non-standard version numbers...
|
||||
|
||||
# In case there is neither update_time nor install_time, we assume the app can/has to be upgraded
|
||||
if not app_infos["from_catalog"].get("lastUpdate") or not app_infos[
|
||||
"from_catalog"
|
||||
].get("git"):
|
||||
return "url_required"
|
||||
|
||||
settings = app_infos["settings"]
|
||||
local_update_time = settings.get("update_time", settings.get("install_time", 0))
|
||||
if app_infos["from_catalog"]["lastUpdate"] > local_update_time:
|
||||
if installed_version < version_in_catalog:
|
||||
return "yes"
|
||||
else:
|
||||
return "no"
|
||||
|
@ -617,9 +612,11 @@ def app_upgrade(
|
|||
# Manage upgrade type and avoid any upgrade if there is nothing to do
|
||||
upgrade_type = "UNKNOWN"
|
||||
# Get current_version and new version
|
||||
app_new_version = version.parse(manifest.get("version", "?"))
|
||||
app_current_version = version.parse(app_dict.get("version", "?"))
|
||||
if "~ynh" in str(app_current_version) and "~ynh" in str(app_new_version):
|
||||
app_new_version_raw = manifest.get("version", "?")
|
||||
app_current_version_raw = app_dict.get("version", "?")
|
||||
app_new_version = _parse_app_version(app_new_version_raw)
|
||||
app_current_version = _parse_app_version(app_current_version_raw)
|
||||
if "~ynh" in str(app_current_version_raw) and "~ynh" in str(app_new_version_raw):
|
||||
if app_current_version >= app_new_version and not force:
|
||||
# In case of upgrade from file or custom repository
|
||||
# No new version available
|
||||
|
@ -639,10 +636,10 @@ def app_upgrade(
|
|||
upgrade_type = "UPGRADE_FORCED"
|
||||
else:
|
||||
app_current_version_upstream, app_current_version_pkg = str(
|
||||
app_current_version
|
||||
app_current_version_raw
|
||||
).split("~ynh")
|
||||
app_new_version_upstream, app_new_version_pkg = str(
|
||||
app_new_version
|
||||
app_new_version_raw
|
||||
).split("~ynh")
|
||||
if app_current_version_upstream == app_new_version_upstream:
|
||||
upgrade_type = "UPGRADE_PACKAGE"
|
||||
|
@ -672,7 +669,7 @@ def app_upgrade(
|
|||
settings = _get_app_settings(app_instance_name)
|
||||
notifications = _filter_and_hydrate_notifications(
|
||||
manifest["notifications"]["PRE_UPGRADE"],
|
||||
current_version=app_current_version,
|
||||
current_version=app_current_version_raw,
|
||||
data=settings,
|
||||
)
|
||||
_display_notifications(notifications, force=force)
|
||||
|
@ -694,9 +691,17 @@ def app_upgrade(
|
|||
safety_backup_name = f"{app_instance_name}-pre-upgrade2"
|
||||
other_safety_backup_name = f"{app_instance_name}-pre-upgrade1"
|
||||
|
||||
backup_create(
|
||||
name=safety_backup_name, apps=[app_instance_name], system=None
|
||||
)
|
||||
tweaked_backup_core_only = False
|
||||
if "BACKUP_CORE_ONLY" not in os.environ:
|
||||
tweaked_backup_core_only = True
|
||||
os.environ["BACKUP_CORE_ONLY"] = "1"
|
||||
try:
|
||||
backup_create(
|
||||
name=safety_backup_name, apps=[app_instance_name], system=None
|
||||
)
|
||||
finally:
|
||||
if tweaked_backup_core_only:
|
||||
del os.environ["BACKUP_CORE_ONLY"]
|
||||
|
||||
if safety_backup_name in backup_list()["archives"]:
|
||||
# if the backup suceeded, delete old safety backup to save space
|
||||
|
@ -729,8 +734,8 @@ def app_upgrade(
|
|||
|
||||
env_dict_more = {
|
||||
"YNH_APP_UPGRADE_TYPE": upgrade_type,
|
||||
"YNH_APP_MANIFEST_VERSION": str(app_new_version),
|
||||
"YNH_APP_CURRENT_VERSION": str(app_current_version),
|
||||
"YNH_APP_MANIFEST_VERSION": str(app_new_version_raw),
|
||||
"YNH_APP_CURRENT_VERSION": str(app_current_version_raw),
|
||||
}
|
||||
|
||||
if manifest["packaging_format"] < 2:
|
||||
|
@ -788,7 +793,7 @@ def app_upgrade(
|
|||
and not no_safety_backup
|
||||
):
|
||||
logger.warning(
|
||||
"Upgrade failed ... attempting to restore the satefy backup (Yunohost first need to remove the app for this) ..."
|
||||
"Upgrade failed ... attempting to restore the safety backup (Yunohost first need to remove the app for this) ..."
|
||||
)
|
||||
|
||||
app_remove(app_instance_name, force_workdir=extracted_app_folder)
|
||||
|
@ -913,7 +918,7 @@ def app_upgrade(
|
|||
settings = _get_app_settings(app_instance_name)
|
||||
notifications = _filter_and_hydrate_notifications(
|
||||
manifest["notifications"]["POST_UPGRADE"],
|
||||
current_version=app_current_version,
|
||||
current_version=app_current_version_raw,
|
||||
data=settings,
|
||||
)
|
||||
if Moulinette.interface.type == "cli":
|
||||
|
@ -1098,7 +1103,7 @@ def app_install(
|
|||
args = {
|
||||
question.id: question.value
|
||||
for question in questions
|
||||
if question.value is not None
|
||||
if not question.readonly and question.value is not None
|
||||
}
|
||||
|
||||
# Validate domain / path availability for webapps
|
||||
|
@ -1157,6 +1162,10 @@ def app_install(
|
|||
recursive=True,
|
||||
)
|
||||
|
||||
# Hotfix for bug in the webadmin while we fix the actual issue :D
|
||||
if label == "undefined":
|
||||
label = None
|
||||
|
||||
# Override manifest name by given label
|
||||
# This info is also later picked-up by the 'permission' resource initialization
|
||||
if label:
|
||||
|
@ -1512,119 +1521,6 @@ def app_setting(app, key, value=None, delete=False):
|
|||
"""
|
||||
app_settings = _get_app_settings(app) or {}
|
||||
|
||||
#
|
||||
# Legacy permission setting management
|
||||
# (unprotected, protected, skipped_uri/regex)
|
||||
#
|
||||
|
||||
is_legacy_permission_setting = any(
|
||||
key.startswith(word + "_") for word in ["unprotected", "protected", "skipped"]
|
||||
)
|
||||
|
||||
if is_legacy_permission_setting:
|
||||
from yunohost.permission import (
|
||||
user_permission_list,
|
||||
user_permission_update,
|
||||
permission_create,
|
||||
permission_delete,
|
||||
permission_url,
|
||||
)
|
||||
|
||||
permissions = user_permission_list(full=True, apps=[app])["permissions"]
|
||||
key_ = key.split("_")[0]
|
||||
permission_name = f"{app}.legacy_{key_}_uris"
|
||||
permission = permissions.get(permission_name)
|
||||
|
||||
# GET
|
||||
if value is None and not delete:
|
||||
return (
|
||||
",".join(permission.get("uris", []) + permission["additional_urls"])
|
||||
if permission
|
||||
else None
|
||||
)
|
||||
|
||||
# DELETE
|
||||
if delete:
|
||||
# If 'is_public' setting still exists, we interpret this as
|
||||
# coming from a legacy app (because new apps shouldn't manage the
|
||||
# is_public state themselves anymore...)
|
||||
#
|
||||
# In that case, we interpret the request for "deleting
|
||||
# unprotected/skipped" setting as willing to make the app
|
||||
# private
|
||||
if (
|
||||
"is_public" in app_settings
|
||||
and "visitors" in permissions[app + ".main"]["allowed"]
|
||||
):
|
||||
if key.startswith("unprotected_") or key.startswith("skipped_"):
|
||||
user_permission_update(app + ".main", remove="visitors")
|
||||
|
||||
if permission:
|
||||
permission_delete(permission_name)
|
||||
|
||||
# SET
|
||||
else:
|
||||
urls = value
|
||||
# If the request is about the root of the app (/), ( = the vast majority of cases)
|
||||
# we interpret this as a change for the main permission
|
||||
# (i.e. allowing/disallowing visitors)
|
||||
if urls == "/":
|
||||
if key.startswith("unprotected_") or key.startswith("skipped_"):
|
||||
permission_url(app + ".main", url="/", sync_perm=False)
|
||||
user_permission_update(app + ".main", add="visitors")
|
||||
else:
|
||||
user_permission_update(app + ".main", remove="visitors")
|
||||
else:
|
||||
urls = urls.split(",")
|
||||
if key.endswith("_regex"):
|
||||
urls = ["re:" + url for url in urls]
|
||||
|
||||
if permission:
|
||||
# In case of new regex, save the urls, to add a new time in the additional_urls
|
||||
# In case of new urls, we do the same thing but inversed
|
||||
if key.endswith("_regex"):
|
||||
# List of urls to save
|
||||
current_urls_or_regex = [
|
||||
url
|
||||
for url in permission["additional_urls"]
|
||||
if not url.startswith("re:")
|
||||
]
|
||||
else:
|
||||
# List of regex to save
|
||||
current_urls_or_regex = [
|
||||
url
|
||||
for url in permission["additional_urls"]
|
||||
if url.startswith("re:")
|
||||
]
|
||||
|
||||
new_urls = urls + current_urls_or_regex
|
||||
# We need to clear urls because in the old setting the new setting override the old one and dont just add some urls
|
||||
permission_url(permission_name, clear_urls=True, sync_perm=False)
|
||||
permission_url(permission_name, add_url=new_urls)
|
||||
else:
|
||||
from yunohost.utils.legacy import legacy_permission_label
|
||||
|
||||
# Let's create a "special" permission for the legacy settings
|
||||
permission_create(
|
||||
permission=permission_name,
|
||||
# FIXME find a way to limit to only the user allowed to the main permission
|
||||
allowed=["all_users"]
|
||||
if key.startswith("protected_")
|
||||
else ["all_users", "visitors"],
|
||||
url=None,
|
||||
additional_urls=urls,
|
||||
auth_header=not key.startswith("skipped_"),
|
||||
label=legacy_permission_label(app, key.split("_")[0]),
|
||||
show_tile=False,
|
||||
protected=True,
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
#
|
||||
# Regular setting management
|
||||
#
|
||||
|
||||
# GET
|
||||
if value is None and not delete:
|
||||
return app_settings.get(key, None)
|
||||
|
@ -1639,8 +1535,6 @@ def app_setting(app, key, value=None, delete=False):
|
|||
|
||||
# SET
|
||||
else:
|
||||
if key in ["redirected_urls", "redirected_regex"]:
|
||||
value = yaml.safe_load(value)
|
||||
app_settings[key] = value
|
||||
|
||||
_set_app_settings(app, app_settings)
|
||||
|
@ -1989,20 +1883,6 @@ def _get_app_settings(app):
|
|||
logger.error(m18n.n("app_not_correctly_installed", app=app))
|
||||
return {}
|
||||
|
||||
# Stupid fix for legacy bullshit
|
||||
# In the past, some setups did not have proper normalization for app domain/path
|
||||
# Meaning some setups (as of January 2021) still have path=/foobar/ (with a trailing slash)
|
||||
# resulting in stupid issue unless apps using ynh_app_normalize_path_stuff
|
||||
# So we yolofix the settings if such an issue is found >_>
|
||||
# A simple call to `yunohost app list` (which happens quite often) should be enough
|
||||
# to migrate all app settings ... so this can probably be removed once we're past Bullseye...
|
||||
if settings.get("path") != "/" and (
|
||||
settings.get("path", "").endswith("/")
|
||||
or not settings.get("path", "/").startswith("/")
|
||||
):
|
||||
settings["path"] = "/" + settings["path"].strip("/")
|
||||
_set_app_settings(app, settings)
|
||||
|
||||
# Make the app id available as $app too
|
||||
settings["app"] = app
|
||||
|
||||
|
@ -2026,6 +1906,20 @@ def _set_app_settings(app, settings):
|
|||
yaml.safe_dump(settings, f, default_flow_style=False)
|
||||
|
||||
|
||||
def _parse_app_version(v):
|
||||
|
||||
if v == "?":
|
||||
return (0,0)
|
||||
|
||||
try:
|
||||
if "~" in v:
|
||||
return (version.parse(v.split("~")[0]), int(v.split("~")[1].replace("ynh", "")))
|
||||
else:
|
||||
return (version.parse(v), 0)
|
||||
except Exception as e:
|
||||
raise YunohostError(f"Failed to parse app version '{v}' : {e}", raw_msg=True)
|
||||
|
||||
|
||||
def _get_manifest_of_app(path):
|
||||
"Get app manifest stored in json or in toml"
|
||||
|
||||
|
@ -2223,6 +2117,13 @@ def _parse_app_doc_and_notifications(path):
|
|||
|
||||
|
||||
def _hydrate_app_template(template, data):
|
||||
|
||||
# Apply jinja for stuff like {% if .. %} blocks,
|
||||
# but only if there's indeed an if block (to try to reduce overhead or idk)
|
||||
if "{%" in template:
|
||||
from jinja2 import Template
|
||||
template = Template(template).render(**data)
|
||||
|
||||
stuff_to_replace = set(re.findall(r"__[A-Z0-9]+?[A-Z0-9_]*?[A-Z0-9]*?__", template))
|
||||
|
||||
for stuff in stuff_to_replace:
|
||||
|
@ -2231,7 +2132,7 @@ def _hydrate_app_template(template, data):
|
|||
if varname in data:
|
||||
template = template.replace(stuff, str(data[varname]))
|
||||
|
||||
return template
|
||||
return template.strip()
|
||||
|
||||
|
||||
def _convert_v1_manifest_to_v2(manifest):
|
||||
|
@ -2905,6 +2806,7 @@ def _make_environment_for_app_script(
|
|||
app_id, app_instance_nb = _parse_app_instance_name(app)
|
||||
|
||||
env_dict = {
|
||||
"YNH_DEFAULT_PHP_VERSION": "8.2",
|
||||
"YNH_APP_ID": app_id,
|
||||
"YNH_APP_INSTANCE_NAME": app,
|
||||
"YNH_APP_INSTANCE_NUMBER": str(app_instance_nb),
|
||||
|
@ -3043,10 +2945,10 @@ def _assert_system_is_sane_for_app(manifest, when):
|
|||
|
||||
services = manifest.get("services", [])
|
||||
|
||||
# Some apps use php-fpm, php5-fpm or php7.x-fpm which is now php7.4-fpm
|
||||
# Some apps use php-fpm, php5-fpm or php7.x-fpm which is now php8.2-fpm
|
||||
def replace_alias(service):
|
||||
if service in ["php-fpm", "php5-fpm", "php7.0-fpm", "php7.3-fpm"]:
|
||||
return "php7.4-fpm"
|
||||
if service in ["php-fpm", "php5-fpm", "php7.0-fpm", "php7.3-fpm", "php7.4-fpm"]:
|
||||
return "php8.2-fpm"
|
||||
else:
|
||||
return service
|
||||
|
||||
|
@ -3055,7 +2957,7 @@ def _assert_system_is_sane_for_app(manifest, when):
|
|||
# We only check those, mostly to ignore "custom" services
|
||||
# (added by apps) and because those are the most popular
|
||||
# services
|
||||
service_filter = ["nginx", "php7.4-fpm", "mysql", "postfix"]
|
||||
service_filter = ["nginx", "php8.2-fpm", "mysql", "postfix"]
|
||||
services = [str(s) for s in services if s in service_filter]
|
||||
|
||||
if "nginx" not in services:
|
||||
|
@ -3131,14 +3033,9 @@ def _notification_is_dismissed(name, settings):
|
|||
def _filter_and_hydrate_notifications(notifications, current_version=None, data={}):
|
||||
def is_version_more_recent_than_current_version(name, current_version):
|
||||
current_version = str(current_version)
|
||||
# Boring code to handle the fact that "0.1 < 9999~ynh1" is False
|
||||
return _parse_app_version(name) > _parse_app_version(current_version)
|
||||
|
||||
if "~" in name:
|
||||
return version.parse(name) > version.parse(current_version)
|
||||
else:
|
||||
return version.parse(name) > version.parse(current_version.split("~")[0])
|
||||
|
||||
return {
|
||||
out = {
|
||||
# Should we render the markdown maybe? idk
|
||||
name: _hydrate_app_template(_value_for_locale(content_per_lang), data)
|
||||
for name, content_per_lang in notifications.items()
|
||||
|
@ -3147,6 +3044,9 @@ def _filter_and_hydrate_notifications(notifications, current_version=None, data=
|
|||
or is_version_more_recent_than_current_version(name, current_version)
|
||||
}
|
||||
|
||||
# Filter out empty notifications (notifications may be empty because of if blocks)
|
||||
return {name:content for name, content in out.items() if content and content.strip()}
|
||||
|
||||
|
||||
def _display_notifications(notifications, force=False):
|
||||
if not notifications:
|
||||
|
@ -3223,7 +3123,7 @@ def regen_mail_app_user_config_for_dovecot_and_postfix(only=None):
|
|||
if dovecot:
|
||||
hashed_password = _hash_user_password(settings["mail_pwd"])
|
||||
dovecot_passwd.append(
|
||||
f"{app}:{hashed_password}::::::allow_nets=127.0.0.1/24"
|
||||
f"{app}:{hashed_password}::::::allow_nets=::1,127.0.0.1/24,local"
|
||||
)
|
||||
if postfix:
|
||||
mail_user = settings.get("mail_user", app)
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
import os
|
||||
import re
|
||||
import hashlib
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import m18n
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.network import download_json
|
||||
from moulinette.utils.filesystem import (
|
||||
read_json,
|
||||
|
@ -34,7 +34,7 @@ from moulinette.utils.filesystem import (
|
|||
from yunohost.utils.i18n import _value_for_locale
|
||||
from yunohost.utils.error import YunohostError
|
||||
|
||||
logger = getActionLogger("yunohost.app_catalog")
|
||||
logger = getLogger("yunohost.app_catalog")
|
||||
|
||||
APPS_CATALOG_CACHE = "/var/cache/yunohost/repo"
|
||||
APPS_CATALOG_LOGOS = "/usr/share/yunohost/applogos"
|
||||
|
|
|
@ -30,10 +30,10 @@ from glob import glob
|
|||
from collections import OrderedDict
|
||||
from functools import reduce
|
||||
from packaging import version
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import Moulinette, m18n
|
||||
from moulinette.utils.text import random_ascii
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import (
|
||||
read_file,
|
||||
mkdir,
|
||||
|
@ -84,7 +84,7 @@ APP_MARGIN_SPACE_SIZE = 100 # In MB
|
|||
CONF_MARGIN_SPACE_SIZE = 10 # IN MB
|
||||
POSTINSTALL_ESTIMATE_SPACE_SIZE = 5 # In MB
|
||||
MB_ALLOWED_TO_ORGANIZE = 10
|
||||
logger = getActionLogger("yunohost.backup")
|
||||
logger = getLogger("yunohost.backup")
|
||||
|
||||
|
||||
class BackupRestoreTargetsManager:
|
||||
|
@ -1204,7 +1204,7 @@ class RestoreManager:
|
|||
|
||||
def _patch_legacy_php_versions_in_csv_file(self):
|
||||
"""
|
||||
Apply dirty patch to redirect php5 and php7.0 files to php7.4
|
||||
Apply dirty patch to redirect php5 and php7.x files to php8.2
|
||||
"""
|
||||
from yunohost.utils.legacy import LEGACY_PHP_VERSION_REPLACEMENTS
|
||||
|
||||
|
|
|
@ -21,11 +21,10 @@ import sys
|
|||
import shutil
|
||||
import subprocess
|
||||
from glob import glob
|
||||
|
||||
from logging import getLogger
|
||||
from datetime import datetime
|
||||
|
||||
from moulinette import m18n
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import read_file, chown, chmod
|
||||
from moulinette.utils.process import check_output
|
||||
|
||||
|
@ -38,7 +37,7 @@ from yunohost.service import _run_service_command
|
|||
from yunohost.regenconf import regen_conf
|
||||
from yunohost.log import OperationLogger
|
||||
|
||||
logger = getActionLogger("yunohost.certmanager")
|
||||
logger = getLogger("yunohost.certmanager")
|
||||
|
||||
CERT_FOLDER = "/etc/yunohost/certs/"
|
||||
TMP_FOLDER = "/var/www/.well-known/acme-challenge-private/"
|
||||
|
|
|
@ -215,6 +215,11 @@ class MyDiagnoser(Diagnoser):
|
|||
for part in current
|
||||
if not part.startswith("ip4:") and not part.startswith("ip6:")
|
||||
}
|
||||
if "v=DMARC1" in r["value"]:
|
||||
for param in current:
|
||||
key, value = param.split("=")
|
||||
if key == "p":
|
||||
return value in ["none", "quarantine", "reject"]
|
||||
return expected == current
|
||||
elif r["type"] == "MX":
|
||||
# For MX, we want to ignore the priority
|
||||
|
|
|
@ -43,7 +43,7 @@ class MyDiagnoser(Diagnoser):
|
|||
dependencies: List[str] = ["ip"]
|
||||
|
||||
def run(self):
|
||||
self.ehlo_domain = _get_maindomain()
|
||||
self.ehlo_domain = _get_maindomain().lower()
|
||||
self.mail_domains = domain_list()["domains"]
|
||||
self.ipversions, self.ips = self.get_ips_checked()
|
||||
|
||||
|
@ -132,7 +132,7 @@ class MyDiagnoser(Diagnoser):
|
|||
summary=summary,
|
||||
details=[summary + "_details"],
|
||||
)
|
||||
elif r["helo"] != self.ehlo_domain:
|
||||
elif r["helo"].lower() != self.ehlo_domain:
|
||||
yield dict(
|
||||
meta={"test": "mail_ehlo", "ipversion": ipversion},
|
||||
data={"wrong_ehlo": r["helo"], "right_ehlo": self.ehlo_domain},
|
||||
|
@ -185,7 +185,7 @@ class MyDiagnoser(Diagnoser):
|
|||
rdns_domain = ""
|
||||
if len(value) > 0:
|
||||
rdns_domain = value[0][:-1] if value[0].endswith(".") else value[0]
|
||||
if rdns_domain != self.ehlo_domain:
|
||||
if rdns_domain.lower() != self.ehlo_domain:
|
||||
details = [
|
||||
"diagnosis_mail_fcrdns_different_from_ehlo_domain_details"
|
||||
] + details
|
||||
|
@ -194,7 +194,7 @@ class MyDiagnoser(Diagnoser):
|
|||
data={
|
||||
"ip": ip,
|
||||
"ehlo_domain": self.ehlo_domain,
|
||||
"rdns_domain": rdns_domain,
|
||||
"rdns_domain": rdns_domain.lower(),
|
||||
},
|
||||
status="ERROR",
|
||||
summary="diagnosis_mail_fcrdns_different_from_ehlo_domain",
|
||||
|
|
|
@ -21,6 +21,7 @@ import os
|
|||
import time
|
||||
import glob
|
||||
from importlib import import_module
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import m18n, Moulinette
|
||||
from moulinette.utils import log
|
||||
|
@ -33,7 +34,7 @@ from moulinette.utils.filesystem import (
|
|||
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
|
||||
logger = log.getActionLogger("yunohost.diagnosis")
|
||||
logger = getLogger("yunohost.diagnosis")
|
||||
|
||||
DIAGNOSIS_CACHE = "/var/cache/yunohost/diagnosis/"
|
||||
DIAGNOSIS_CONFIG_FILE = "/etc/yunohost/diagnosis.yml"
|
||||
|
|
|
@ -19,12 +19,11 @@
|
|||
import os
|
||||
import re
|
||||
import time
|
||||
|
||||
from logging import getLogger
|
||||
from difflib import SequenceMatcher
|
||||
from collections import OrderedDict
|
||||
|
||||
from moulinette import m18n, Moulinette
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import read_file, write_to_file, read_toml, mkdir
|
||||
|
||||
from yunohost.domain import (
|
||||
|
@ -42,7 +41,7 @@ from yunohost.settings import settings_get
|
|||
from yunohost.log import is_unit_operation
|
||||
from yunohost.hook import hook_callback
|
||||
|
||||
logger = getActionLogger("yunohost.domain")
|
||||
logger = getLogger("yunohost.domain")
|
||||
|
||||
DOMAIN_REGISTRAR_LIST_PATH = "/usr/share/yunohost/registrar_list.toml"
|
||||
|
||||
|
|
|
@ -20,10 +20,10 @@ import os
|
|||
import time
|
||||
from typing import List, Optional
|
||||
from collections import OrderedDict
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import m18n, Moulinette
|
||||
from moulinette.core import MoulinetteError
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import write_to_file, read_yaml, write_to_yaml, rm
|
||||
|
||||
from yunohost.app import (
|
||||
|
@ -39,7 +39,7 @@ from yunohost.utils.error import YunohostError, YunohostValidationError
|
|||
from yunohost.utils.dns import is_yunohost_dyndns_domain
|
||||
from yunohost.log import is_unit_operation
|
||||
|
||||
logger = getActionLogger("yunohost.domain")
|
||||
logger = getLogger("yunohost.domain")
|
||||
|
||||
DOMAIN_SETTINGS_DIR = "/etc/yunohost/domains"
|
||||
|
||||
|
@ -175,11 +175,12 @@ def domain_info(domain):
|
|||
|
||||
from yunohost.app import app_info
|
||||
from yunohost.dns import _get_registar_settings
|
||||
from yunohost.certificate import certificate_status
|
||||
|
||||
_assert_domain_exists(domain)
|
||||
|
||||
registrar, _ = _get_registar_settings(domain)
|
||||
certificate = domain_cert_status([domain], full=True)["certificates"][domain]
|
||||
certificate = certificate_status([domain], full=True)["certificates"][domain]
|
||||
|
||||
apps = []
|
||||
for app in _installed_apps():
|
||||
|
@ -865,10 +866,6 @@ def domain_cert_renew(domain_list, force=False, no_checks=False, email=False):
|
|||
return certificate_renew(domain_list, force, no_checks, email)
|
||||
|
||||
|
||||
def domain_dns_conf(domain):
|
||||
return domain_dns_suggest(domain)
|
||||
|
||||
|
||||
def domain_dns_suggest(domain):
|
||||
from yunohost.dns import domain_dns_suggest
|
||||
|
||||
|
|
|
@ -22,10 +22,10 @@ import glob
|
|||
import base64
|
||||
import subprocess
|
||||
import hashlib
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import Moulinette, m18n
|
||||
from moulinette.core import MoulinetteError
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import write_to_file, rm, chown, chmod
|
||||
from moulinette.utils.network import download_json
|
||||
|
||||
|
@ -36,7 +36,7 @@ from yunohost.utils.dns import dig, is_yunohost_dyndns_domain
|
|||
from yunohost.log import is_unit_operation
|
||||
from yunohost.regenconf import regen_conf
|
||||
|
||||
logger = getActionLogger("yunohost.dyndns")
|
||||
logger = getLogger("yunohost.dyndns")
|
||||
|
||||
DYNDNS_PROVIDER = "dyndns.yunohost.org"
|
||||
DYNDNS_DNS_AUTH = ["ns0.yunohost.org", "ns1.yunohost.org"]
|
||||
|
|
|
@ -19,16 +19,16 @@
|
|||
import os
|
||||
import yaml
|
||||
import miniupnpc
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import m18n
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
from moulinette.utils import process
|
||||
from moulinette.utils.log import getActionLogger
|
||||
|
||||
FIREWALL_FILE = "/etc/yunohost/firewall.yml"
|
||||
UPNP_CRON_JOB = "/etc/cron.d/yunohost-firewall-upnp"
|
||||
|
||||
logger = getActionLogger("yunohost.firewall")
|
||||
logger = getLogger("yunohost.firewall")
|
||||
|
||||
|
||||
def firewall_allow(
|
||||
|
@ -402,7 +402,13 @@ def firewall_upnp(action="status", no_refresh=False):
|
|||
|
||||
# Discover UPnP device(s)
|
||||
logger.debug("discovering UPnP devices...")
|
||||
nb_dev = upnpc.discover()
|
||||
try:
|
||||
nb_dev = upnpc.discover()
|
||||
except Exception:
|
||||
logger.warning("Failed to find any UPnP device on the network")
|
||||
nb_dev = -1
|
||||
enabled = False
|
||||
|
||||
logger.debug("found %d UPnP device(s)", int(nb_dev))
|
||||
if nb_dev < 1:
|
||||
logger.error(m18n.n("upnp_dev_not_found"))
|
||||
|
|
|
@ -23,16 +23,16 @@ import tempfile
|
|||
import mimetypes
|
||||
from glob import iglob
|
||||
from importlib import import_module
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import m18n, Moulinette
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
from moulinette.utils import log
|
||||
from moulinette.utils.filesystem import read_yaml, cp
|
||||
|
||||
HOOK_FOLDER = "/usr/share/yunohost/hooks/"
|
||||
CUSTOM_HOOK_FOLDER = "/etc/yunohost/hooks.d/"
|
||||
|
||||
logger = log.getActionLogger("yunohost.hook")
|
||||
logger = getLogger("yunohost.hook")
|
||||
|
||||
|
||||
def hook_add(app, file):
|
||||
|
@ -359,6 +359,7 @@ def hook_exec(
|
|||
r"Removing obsolete dictionary files",
|
||||
r"Creating new PostgreSQL cluster",
|
||||
r"/usr/lib/postgresql/13/bin/initdb",
|
||||
r"/usr/lib/postgresql/15/bin/initdb",
|
||||
r"The files belonging to this database system will be owned by user",
|
||||
r"This user must also own the server process.",
|
||||
r"The database cluster will be initialized with locale",
|
||||
|
@ -366,6 +367,7 @@ def hook_exec(
|
|||
r"The default text search configuration will be set to",
|
||||
r"Data page checksums are disabled.",
|
||||
r"fixing permissions on existing directory /var/lib/postgresql/13/main ... ok",
|
||||
r"fixing permissions on existing directory /var/lib/postgresql/15/main ... ok",
|
||||
r"creating subdirectories \.\.\. ok",
|
||||
r"selecting dynamic .* \.\.\. ",
|
||||
r"selecting default .* \.\.\. ",
|
||||
|
|
|
@ -32,10 +32,9 @@ from moulinette import m18n, Moulinette
|
|||
from moulinette.core import MoulinetteError
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
from yunohost.utils.system import get_ynh_package_version
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import read_file, read_yaml
|
||||
|
||||
logger = getActionLogger("yunohost.log")
|
||||
logger = getLogger("yunohost.log")
|
||||
|
||||
CATEGORIES_PATH = "/var/log/yunohost/categories/"
|
||||
OPERATIONS_PATH = "/var/log/yunohost/categories/operation/"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import glob
|
||||
import os
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import m18n
|
||||
from yunohost.utils.error import YunohostError
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.process import check_output, call_async_output
|
||||
from moulinette.utils.filesystem import read_file, rm, write_to_file
|
||||
|
||||
|
@ -22,7 +22,7 @@ from yunohost.utils.system import (
|
|||
)
|
||||
from yunohost.service import _get_services, _save_services
|
||||
|
||||
logger = getActionLogger("yunohost.migration")
|
||||
logger = getLogger("yunohost.migration")
|
||||
|
||||
N_CURRENT_DEBIAN = 10
|
||||
N_CURRENT_YUNOHOST = 4
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import os
|
||||
import glob
|
||||
from shutil import copy2
|
||||
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from logging import getLogger
|
||||
|
||||
from yunohost.app import _is_installed
|
||||
from yunohost.utils.legacy import _patch_legacy_php_versions_in_settings
|
||||
from yunohost.tools import Migration
|
||||
from yunohost.service import _run_service_command
|
||||
|
||||
logger = getActionLogger("yunohost.migration")
|
||||
logger = getLogger("yunohost.migration")
|
||||
|
||||
OLDPHP_POOLS = "/etc/php/7.3/fpm/pool.d"
|
||||
NEWPHP_POOLS = "/etc/php/7.4/fpm/pool.d"
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import subprocess
|
||||
import time
|
||||
import os
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import m18n
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
from moulinette.utils.log import getActionLogger
|
||||
|
||||
from yunohost.tools import Migration
|
||||
from yunohost.utils.system import free_space_in_directory, space_used_by_directory
|
||||
|
||||
logger = getActionLogger("yunohost.migration")
|
||||
logger = getLogger("yunohost.migration")
|
||||
|
||||
|
||||
class MyMigration(Migration):
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import os
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import m18n
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.process import call_async_output
|
||||
|
||||
from yunohost.tools import Migration, tools_migrations_state
|
||||
from moulinette.utils.filesystem import rm
|
||||
|
||||
|
||||
logger = getActionLogger("yunohost.migration")
|
||||
logger = getLogger("yunohost.migration")
|
||||
|
||||
VENV_REQUIREMENTS_SUFFIX = ".requirements_backup_for_bullseye_upgrade.txt"
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import os
|
||||
from logging import getLogger
|
||||
|
||||
from yunohost.utils.error import YunohostError
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import read_json, write_to_yaml
|
||||
|
||||
from yunohost.tools import Migration
|
||||
from yunohost.utils.legacy import translate_legacy_settings_to_configpanel_settings
|
||||
|
||||
logger = getActionLogger("yunohost.migration")
|
||||
logger = getLogger("yunohost.migration")
|
||||
|
||||
SETTINGS_PATH = "/etc/yunohost/settings.yml"
|
||||
OLD_SETTINGS_PATH = "/etc/yunohost/settings.json"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from moulinette.utils.log import getActionLogger
|
||||
from logging import getLogger
|
||||
|
||||
from yunohost.tools import Migration
|
||||
|
||||
logger = getActionLogger("yunohost.migration")
|
||||
logger = getLogger("yunohost.migration")
|
||||
|
||||
###################################################
|
||||
# Tools used also for restoration
|
||||
|
|
|
@ -20,13 +20,13 @@ import re
|
|||
import copy
|
||||
import grp
|
||||
import random
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import m18n
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
from yunohost.log import is_unit_operation
|
||||
|
||||
logger = getActionLogger("yunohost.user")
|
||||
logger = getLogger("yunohost.user")
|
||||
|
||||
SYSTEM_PERMS = ["mail", "xmpp", "sftp", "ssh"]
|
||||
|
||||
|
|
|
@ -20,12 +20,12 @@ import os
|
|||
import yaml
|
||||
import shutil
|
||||
import hashlib
|
||||
|
||||
from logging import getLogger
|
||||
from difflib import unified_diff
|
||||
from datetime import datetime
|
||||
|
||||
from moulinette import m18n
|
||||
from moulinette.utils import log, filesystem
|
||||
from moulinette.utils.filesystem import mkdir
|
||||
from moulinette.utils.process import check_output
|
||||
|
||||
from yunohost.utils.error import YunohostError
|
||||
|
@ -37,7 +37,7 @@ BACKUP_CONF_DIR = os.path.join(BASE_CONF_PATH, "backup")
|
|||
PENDING_CONF_DIR = os.path.join(BASE_CONF_PATH, "pending")
|
||||
REGEN_CONF_FILE = "/etc/yunohost/regenconf.yml"
|
||||
|
||||
logger = log.getActionLogger("yunohost.regenconf")
|
||||
logger = getLogger("yunohost.regenconf")
|
||||
|
||||
|
||||
# FIXME : those ain't just services anymore ... what are we supposed to do with this ...
|
||||
|
@ -102,7 +102,7 @@ def regen_conf(
|
|||
for name in names:
|
||||
shutil.rmtree(os.path.join(PENDING_CONF_DIR, name), ignore_errors=True)
|
||||
else:
|
||||
filesystem.mkdir(PENDING_CONF_DIR, 0o755, True)
|
||||
mkdir(PENDING_CONF_DIR, 0o755, True)
|
||||
|
||||
# Execute hooks for pre-regen
|
||||
# element 2 and 3 with empty string is because of legacy...
|
||||
|
@ -111,7 +111,7 @@ def regen_conf(
|
|||
def _pre_call(name, priority, path, args):
|
||||
# create the pending conf directory for the category
|
||||
category_pending_path = os.path.join(PENDING_CONF_DIR, name)
|
||||
filesystem.mkdir(category_pending_path, 0o755, True, uid="root")
|
||||
mkdir(category_pending_path, 0o755, True, uid="root")
|
||||
|
||||
# return the arguments to pass to the script
|
||||
return pre_args + [
|
||||
|
@ -622,7 +622,7 @@ def _process_regen_conf(system_conf, new_conf=None, save=True):
|
|||
backup_dir = os.path.dirname(backup_path)
|
||||
|
||||
if not os.path.isdir(backup_dir):
|
||||
filesystem.mkdir(backup_dir, 0o755, True)
|
||||
mkdir(backup_dir, 0o755, True)
|
||||
|
||||
shutil.copy2(system_conf, backup_path)
|
||||
logger.debug(
|
||||
|
@ -637,7 +637,7 @@ def _process_regen_conf(system_conf, new_conf=None, save=True):
|
|||
system_dir = os.path.dirname(system_conf)
|
||||
|
||||
if not os.path.isdir(system_dir):
|
||||
filesystem.mkdir(system_dir, 0o755, True)
|
||||
mkdir(system_dir, 0o755, True)
|
||||
|
||||
shutil.copyfile(new_conf, system_conf)
|
||||
logger.debug(m18n.n("regenconf_file_updated", conf=system_conf))
|
||||
|
|
|
@ -21,14 +21,13 @@ import os
|
|||
import time
|
||||
import yaml
|
||||
import subprocess
|
||||
|
||||
from logging import getLogger
|
||||
from glob import glob
|
||||
from datetime import datetime
|
||||
|
||||
from moulinette import m18n
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
from moulinette.utils.process import check_output
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import (
|
||||
read_file,
|
||||
append_to_file,
|
||||
|
@ -42,7 +41,7 @@ MOULINETTE_LOCK = "/var/run/moulinette_yunohost.lock"
|
|||
SERVICES_CONF = "/etc/yunohost/services.yml"
|
||||
SERVICES_CONF_BASE = "/usr/share/yunohost/conf/yunohost/services.yml"
|
||||
|
||||
logger = getActionLogger("yunohost.service")
|
||||
logger = getLogger("yunohost.service")
|
||||
|
||||
|
||||
def service_add(
|
||||
|
|
|
@ -18,18 +18,18 @@
|
|||
#
|
||||
import os
|
||||
import subprocess
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import m18n
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
from yunohost.utils.configpanel import ConfigPanel
|
||||
from yunohost.utils.form import BaseOption
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from yunohost.regenconf import regen_conf
|
||||
from yunohost.firewall import firewall_reload
|
||||
from yunohost.log import is_unit_operation
|
||||
from yunohost.utils.legacy import translate_legacy_settings_to_configpanel_settings
|
||||
|
||||
logger = getActionLogger("yunohost.settings")
|
||||
logger = getLogger("yunohost.settings")
|
||||
|
||||
SETTINGS_PATH = "/etc/yunohost/settings.yml"
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
import pytest
|
||||
from unittest.mock import Mock
|
||||
|
||||
import moulinette
|
||||
from moulinette import m18n, Moulinette
|
||||
|
@ -23,11 +24,15 @@ def get_test_apps_dir():
|
|||
|
||||
|
||||
@contextmanager
|
||||
def message(mocker, key, **kwargs):
|
||||
mocker.spy(m18n, "n")
|
||||
def message(key, **kwargs):
|
||||
m = Mock(wraps=m18n.n)
|
||||
old_m18n = m18n.n
|
||||
m18n.n = m
|
||||
yield
|
||||
m18n.n.assert_any_call(key, **kwargs)
|
||||
|
||||
try:
|
||||
m.assert_any_call(key, **kwargs)
|
||||
finally:
|
||||
m18n.n = old_m18n
|
||||
|
||||
@contextmanager
|
||||
def raiseYunohostError(mocker, key, **kwargs):
|
||||
|
|
|
@ -5,6 +5,8 @@ import requests_mock
|
|||
import glob
|
||||
import shutil
|
||||
|
||||
from .conftest import message
|
||||
|
||||
from moulinette import m18n
|
||||
from moulinette.utils.filesystem import read_json, write_to_json, write_to_yaml
|
||||
|
||||
|
@ -258,13 +260,12 @@ def test_apps_catalog_load_with_conflicts_between_lists(mocker):
|
|||
assert "bar" in app_dict.keys()
|
||||
|
||||
|
||||
def test_apps_catalog_load_with_oudated_api_version(mocker):
|
||||
def test_apps_catalog_load_with_outdated_api_version():
|
||||
# Initialize ...
|
||||
_initialize_apps_catalog_system()
|
||||
|
||||
# Update
|
||||
with requests_mock.Mocker() as m:
|
||||
mocker.spy(m18n, "n")
|
||||
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_CATALOG)
|
||||
_update_apps_catalog()
|
||||
|
||||
|
@ -282,10 +283,8 @@ def test_apps_catalog_load_with_oudated_api_version(mocker):
|
|||
with requests_mock.Mocker() as m:
|
||||
# Mock the server response with a dummy apps catalog
|
||||
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_CATALOG)
|
||||
|
||||
mocker.spy(m18n, "n")
|
||||
app_dict = _load_apps_catalog()["apps"]
|
||||
m18n.n.assert_any_call("apps_catalog_update_success")
|
||||
with message("apps_catalog_update_success"):
|
||||
app_dict = _load_apps_catalog()["apps"]
|
||||
|
||||
assert "foo" in app_dict.keys()
|
||||
assert "bar" in app_dict.keys()
|
||||
|
|
|
@ -394,9 +394,9 @@ def test_legacy_app_install_private(secondary_domain):
|
|||
assert app_is_not_installed(secondary_domain, "legacy_app")
|
||||
|
||||
|
||||
def test_legacy_app_install_unknown_domain(mocker):
|
||||
def test_legacy_app_install_unknown_domain():
|
||||
with pytest.raises(YunohostError):
|
||||
with message(mocker, "app_argument_invalid"):
|
||||
with message("app_argument_invalid"):
|
||||
install_legacy_app("whatever.nope", "/legacy")
|
||||
|
||||
assert app_is_not_installed("whatever.nope", "legacy_app")
|
||||
|
@ -423,12 +423,12 @@ def test_legacy_app_install_multiple_instances(secondary_domain):
|
|||
assert app_is_not_installed(secondary_domain, "legacy_app__2")
|
||||
|
||||
|
||||
def test_legacy_app_install_path_unavailable(mocker, secondary_domain):
|
||||
def test_legacy_app_install_path_unavailable(secondary_domain):
|
||||
# These will be removed in teardown
|
||||
install_legacy_app(secondary_domain, "/legacy")
|
||||
|
||||
with pytest.raises(YunohostError):
|
||||
with message(mocker, "app_location_unavailable"):
|
||||
with message("app_location_unavailable"):
|
||||
install_legacy_app(secondary_domain, "/")
|
||||
|
||||
assert app_is_installed(secondary_domain, "legacy_app")
|
||||
|
@ -444,19 +444,19 @@ def test_legacy_app_install_with_nginx_down(mocker, secondary_domain):
|
|||
install_legacy_app(secondary_domain, "/legacy")
|
||||
|
||||
|
||||
def test_legacy_app_failed_install(mocker, secondary_domain):
|
||||
def test_legacy_app_failed_install(secondary_domain):
|
||||
# This will conflict with the folder that the app
|
||||
# attempts to create, making the install fail
|
||||
mkdir("/var/www/legacy_app/", 0o750)
|
||||
|
||||
with pytest.raises(YunohostError):
|
||||
with message(mocker, "app_install_script_failed"):
|
||||
with message("app_install_script_failed"):
|
||||
install_legacy_app(secondary_domain, "/legacy")
|
||||
|
||||
assert app_is_not_installed(secondary_domain, "legacy_app")
|
||||
|
||||
|
||||
def test_legacy_app_failed_remove(mocker, secondary_domain):
|
||||
def test_legacy_app_failed_remove(secondary_domain):
|
||||
install_legacy_app(secondary_domain, "/legacy")
|
||||
|
||||
# The remove script runs with set -eu and attempt to remove this
|
||||
|
@ -488,52 +488,52 @@ def test_full_domain_app_with_conflicts(mocker, secondary_domain):
|
|||
install_full_domain_app(secondary_domain)
|
||||
|
||||
|
||||
def test_systemfuckedup_during_app_install(mocker, secondary_domain):
|
||||
def test_systemfuckedup_during_app_install(secondary_domain):
|
||||
with pytest.raises(YunohostError):
|
||||
with message(mocker, "app_install_failed"):
|
||||
with message(mocker, "app_action_broke_system"):
|
||||
with message("app_install_failed"):
|
||||
with message("app_action_broke_system"):
|
||||
install_break_yo_system(secondary_domain, breakwhat="install")
|
||||
|
||||
assert app_is_not_installed(secondary_domain, "break_yo_system")
|
||||
|
||||
|
||||
def test_systemfuckedup_during_app_remove(mocker, secondary_domain):
|
||||
def test_systemfuckedup_during_app_remove(secondary_domain):
|
||||
install_break_yo_system(secondary_domain, breakwhat="remove")
|
||||
|
||||
with pytest.raises(YunohostError):
|
||||
with message(mocker, "app_action_broke_system"):
|
||||
with message(mocker, "app_removed"):
|
||||
with message("app_action_broke_system"):
|
||||
with message("app_removed"):
|
||||
app_remove("break_yo_system")
|
||||
|
||||
assert app_is_not_installed(secondary_domain, "break_yo_system")
|
||||
|
||||
|
||||
def test_systemfuckedup_during_app_install_and_remove(mocker, secondary_domain):
|
||||
def test_systemfuckedup_during_app_install_and_remove(secondary_domain):
|
||||
with pytest.raises(YunohostError):
|
||||
with message(mocker, "app_install_failed"):
|
||||
with message(mocker, "app_action_broke_system"):
|
||||
with message("app_install_failed"):
|
||||
with message("app_action_broke_system"):
|
||||
install_break_yo_system(secondary_domain, breakwhat="everything")
|
||||
|
||||
assert app_is_not_installed(secondary_domain, "break_yo_system")
|
||||
|
||||
|
||||
def test_systemfuckedup_during_app_upgrade(mocker, secondary_domain):
|
||||
def test_systemfuckedup_during_app_upgrade(secondary_domain):
|
||||
install_break_yo_system(secondary_domain, breakwhat="upgrade")
|
||||
|
||||
with pytest.raises(YunohostError):
|
||||
with message(mocker, "app_action_broke_system"):
|
||||
with message("app_action_broke_system"):
|
||||
app_upgrade(
|
||||
"break_yo_system",
|
||||
file=os.path.join(get_test_apps_dir(), "break_yo_system_ynh"),
|
||||
)
|
||||
|
||||
|
||||
def test_failed_multiple_app_upgrade(mocker, secondary_domain):
|
||||
def test_failed_multiple_app_upgrade(secondary_domain):
|
||||
install_legacy_app(secondary_domain, "/legacy")
|
||||
install_break_yo_system(secondary_domain, breakwhat="upgrade")
|
||||
|
||||
with pytest.raises(YunohostError):
|
||||
with message(mocker, "app_not_upgraded"):
|
||||
with message("app_not_upgraded"):
|
||||
app_upgrade(
|
||||
["break_yo_system", "legacy_app"],
|
||||
file={
|
||||
|
|
|
@ -217,10 +217,6 @@ def test_normalize_permission_path_with_bad_regex():
|
|||
)
|
||||
|
||||
# Full Regex
|
||||
with pytest.raises(YunohostError):
|
||||
_validate_and_sanitize_permission_url(
|
||||
"re:" + maindomain + "/yolo?+/", maindomain + "/path", "test_permission"
|
||||
)
|
||||
with pytest.raises(YunohostError):
|
||||
_validate_and_sanitize_permission_url(
|
||||
"re:" + maindomain + "/yolo[1-9]**/",
|
||||
|
|
|
@ -49,8 +49,8 @@ def setup_function(function):
|
|||
for m in function.__dict__.get("pytestmark", [])
|
||||
}
|
||||
|
||||
if "with_wordpress_archive_from_4p2" in markers:
|
||||
add_archive_wordpress_from_4p2()
|
||||
if "with_wordpress_archive_from_11p2" in markers:
|
||||
add_archive_wordpress_from_11p2()
|
||||
assert len(backup_list()["archives"]) == 1
|
||||
|
||||
if "with_legacy_app_installed" in markers:
|
||||
|
@ -72,8 +72,8 @@ def setup_function(function):
|
|||
)
|
||||
assert app_is_installed("backup_recommended_app")
|
||||
|
||||
if "with_system_archive_from_4p2" in markers:
|
||||
add_archive_system_from_4p2()
|
||||
if "with_system_archive_from_11p2" in markers:
|
||||
add_archive_system_from_11p2()
|
||||
assert len(backup_list()["archives"]) == 1
|
||||
|
||||
if "with_permission_app_installed" in markers:
|
||||
|
@ -148,7 +148,7 @@ def app_is_installed(app):
|
|||
def backup_test_dependencies_are_met():
|
||||
# Dummy test apps (or backup archives)
|
||||
assert os.path.exists(
|
||||
os.path.join(get_test_apps_dir(), "backup_wordpress_from_4p2")
|
||||
os.path.join(get_test_apps_dir(), "backup_wordpress_from_11p2")
|
||||
)
|
||||
assert os.path.exists(os.path.join(get_test_apps_dir(), "legacy_app_ynh"))
|
||||
assert os.path.exists(
|
||||
|
@ -211,23 +211,23 @@ def install_app(app, path, additionnal_args=""):
|
|||
)
|
||||
|
||||
|
||||
def add_archive_wordpress_from_4p2():
|
||||
def add_archive_wordpress_from_11p2():
|
||||
os.system("mkdir -p /home/yunohost.backup/archives")
|
||||
|
||||
os.system(
|
||||
"cp "
|
||||
+ os.path.join(get_test_apps_dir(), "backup_wordpress_from_4p2/backup.tar")
|
||||
+ " /home/yunohost.backup/archives/backup_wordpress_from_4p2.tar"
|
||||
+ os.path.join(get_test_apps_dir(), "backup_wordpress_from_11p2/backup.tar")
|
||||
+ " /home/yunohost.backup/archives/backup_wordpress_from_11p2.tar"
|
||||
)
|
||||
|
||||
|
||||
def add_archive_system_from_4p2():
|
||||
def add_archive_system_from_11p2():
|
||||
os.system("mkdir -p /home/yunohost.backup/archives")
|
||||
|
||||
os.system(
|
||||
"cp "
|
||||
+ os.path.join(get_test_apps_dir(), "backup_system_from_4p2/backup.tar")
|
||||
+ " /home/yunohost.backup/archives/backup_system_from_4p2.tar"
|
||||
+ os.path.join(get_test_apps_dir(), "backup_system_from_11p2/backup.tar")
|
||||
+ " /home/yunohost.backup/archives/backup_system_from_11p2.tar"
|
||||
)
|
||||
|
||||
|
||||
|
@ -236,10 +236,10 @@ def add_archive_system_from_4p2():
|
|||
#
|
||||
|
||||
|
||||
def test_backup_only_ldap(mocker):
|
||||
def test_backup_only_ldap():
|
||||
# Create the backup
|
||||
name = random_ascii(8)
|
||||
with message(mocker, "backup_created", name=name):
|
||||
with message("backup_created", name=name):
|
||||
backup_create(name=name, system=["conf_ldap"], apps=None)
|
||||
|
||||
archives = backup_list()["archives"]
|
||||
|
@ -253,7 +253,7 @@ def test_backup_only_ldap(mocker):
|
|||
|
||||
def test_backup_system_part_that_does_not_exists(mocker):
|
||||
# Create the backup
|
||||
with message(mocker, "backup_hook_unknown", hook="doesnt_exist"):
|
||||
with message("backup_hook_unknown", hook="doesnt_exist"):
|
||||
with raiseYunohostError(mocker, "backup_nothings_done"):
|
||||
backup_create(system=["doesnt_exist"], apps=None)
|
||||
|
||||
|
@ -263,10 +263,10 @@ def test_backup_system_part_that_does_not_exists(mocker):
|
|||
#
|
||||
|
||||
|
||||
def test_backup_and_restore_all_sys(mocker):
|
||||
def test_backup_and_restore_all_sys():
|
||||
name = random_ascii(8)
|
||||
# Create the backup
|
||||
with message(mocker, "backup_created", name=name):
|
||||
with message("backup_created", name=name):
|
||||
backup_create(name=name, system=[], apps=None)
|
||||
|
||||
archives = backup_list()["archives"]
|
||||
|
@ -284,7 +284,7 @@ def test_backup_and_restore_all_sys(mocker):
|
|||
assert not os.path.exists("/etc/ssowat/conf.json")
|
||||
|
||||
# Restore the backup
|
||||
with message(mocker, "restore_complete"):
|
||||
with message("restore_complete"):
|
||||
backup_restore(name=archives[0], force=True, system=[], apps=None)
|
||||
|
||||
# Check ssowat conf is back
|
||||
|
@ -292,22 +292,22 @@ def test_backup_and_restore_all_sys(mocker):
|
|||
|
||||
|
||||
#
|
||||
# System restore from 3.8 #
|
||||
# System restore from 11.2 #
|
||||
#
|
||||
|
||||
|
||||
@pytest.mark.with_system_archive_from_4p2
|
||||
def test_restore_system_from_Ynh4p2(monkeypatch, mocker):
|
||||
@pytest.mark.with_system_archive_from_11p2
|
||||
def test_restore_system_from_Ynh11p2(monkeypatch):
|
||||
name = random_ascii(8)
|
||||
# Backup current system
|
||||
with message(mocker, "backup_created", name=name):
|
||||
with message("backup_created", name=name):
|
||||
backup_create(name=name, system=[], apps=None)
|
||||
archives = backup_list()["archives"]
|
||||
assert len(archives) == 2
|
||||
|
||||
# Restore system archive from 3.8
|
||||
# Restore system archive from 11.2
|
||||
try:
|
||||
with message(mocker, "restore_complete"):
|
||||
with message("restore_complete"):
|
||||
backup_restore(
|
||||
name=backup_list()["archives"][1], system=[], apps=None, force=True
|
||||
)
|
||||
|
@ -336,7 +336,7 @@ def test_backup_script_failure_handling(monkeypatch, mocker):
|
|||
# with the expected error message key
|
||||
monkeypatch.setattr("yunohost.backup.hook_exec", custom_hook_exec)
|
||||
|
||||
with message(mocker, "backup_app_failed", app="backup_recommended_app"):
|
||||
with message("backup_app_failed", app="backup_recommended_app"):
|
||||
with raiseYunohostError(mocker, "backup_nothings_done"):
|
||||
backup_create(system=None, apps=["backup_recommended_app"])
|
||||
|
||||
|
@ -363,7 +363,7 @@ def test_backup_not_enough_free_space(monkeypatch, mocker):
|
|||
def test_backup_app_not_installed(mocker):
|
||||
assert not _is_installed("wordpress")
|
||||
|
||||
with message(mocker, "unbackup_app", app="wordpress"):
|
||||
with message("unbackup_app", app="wordpress"):
|
||||
with raiseYunohostError(mocker, "backup_nothings_done"):
|
||||
backup_create(system=None, apps=["wordpress"])
|
||||
|
||||
|
@ -375,14 +375,14 @@ def test_backup_app_with_no_backup_script(mocker):
|
|||
assert not os.path.exists(backup_script)
|
||||
|
||||
with message(
|
||||
mocker, "backup_with_no_backup_script_for_app", app="backup_recommended_app"
|
||||
"backup_with_no_backup_script_for_app", app="backup_recommended_app"
|
||||
):
|
||||
with raiseYunohostError(mocker, "backup_nothings_done"):
|
||||
backup_create(system=None, apps=["backup_recommended_app"])
|
||||
|
||||
|
||||
@pytest.mark.with_backup_recommended_app_installed
|
||||
def test_backup_app_with_no_restore_script(mocker):
|
||||
def test_backup_app_with_no_restore_script():
|
||||
restore_script = "/etc/yunohost/apps/backup_recommended_app/scripts/restore"
|
||||
os.system("rm %s" % restore_script)
|
||||
assert not os.path.exists(restore_script)
|
||||
|
@ -391,16 +391,16 @@ def test_backup_app_with_no_restore_script(mocker):
|
|||
# user...
|
||||
|
||||
with message(
|
||||
mocker, "backup_with_no_restore_script_for_app", app="backup_recommended_app"
|
||||
"backup_with_no_restore_script_for_app", app="backup_recommended_app"
|
||||
):
|
||||
backup_create(system=None, apps=["backup_recommended_app"])
|
||||
|
||||
|
||||
@pytest.mark.clean_opt_dir
|
||||
def test_backup_with_different_output_directory(mocker):
|
||||
def test_backup_with_different_output_directory():
|
||||
name = random_ascii(8)
|
||||
# Create the backup
|
||||
with message(mocker, "backup_created", name=name):
|
||||
with message("backup_created", name=name):
|
||||
backup_create(
|
||||
system=["conf_ynh_settings"],
|
||||
apps=None,
|
||||
|
@ -420,10 +420,10 @@ def test_backup_with_different_output_directory(mocker):
|
|||
|
||||
|
||||
@pytest.mark.clean_opt_dir
|
||||
def test_backup_using_copy_method(mocker):
|
||||
def test_backup_using_copy_method():
|
||||
# Create the backup
|
||||
name = random_ascii(8)
|
||||
with message(mocker, "backup_created", name=name):
|
||||
with message("backup_created", name=name):
|
||||
backup_create(
|
||||
system=["conf_ynh_settings"],
|
||||
apps=None,
|
||||
|
@ -439,17 +439,16 @@ def test_backup_using_copy_method(mocker):
|
|||
# App restore #
|
||||
#
|
||||
|
||||
|
||||
@pytest.mark.with_wordpress_archive_from_4p2
|
||||
@pytest.mark.with_wordpress_archive_from_11p2
|
||||
@pytest.mark.with_custom_domain("yolo.test")
|
||||
def test_restore_app_wordpress_from_Ynh4p2(mocker):
|
||||
with message(mocker, "restore_complete"):
|
||||
def test_restore_app_wordpress_from_Ynh11p2():
|
||||
with message("restore_complete"):
|
||||
backup_restore(
|
||||
system=None, name=backup_list()["archives"][0], apps=["wordpress"]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.with_wordpress_archive_from_4p2
|
||||
@pytest.mark.with_wordpress_archive_from_11p2
|
||||
@pytest.mark.with_custom_domain("yolo.test")
|
||||
def test_restore_app_script_failure_handling(monkeypatch, mocker):
|
||||
def custom_hook_exec(name, *args, **kwargs):
|
||||
|
@ -461,7 +460,7 @@ def test_restore_app_script_failure_handling(monkeypatch, mocker):
|
|||
|
||||
assert not _is_installed("wordpress")
|
||||
|
||||
with message(mocker, "app_restore_script_failed"):
|
||||
with message("app_restore_script_failed"):
|
||||
with raiseYunohostError(mocker, "restore_nothings_done"):
|
||||
backup_restore(
|
||||
system=None, name=backup_list()["archives"][0], apps=["wordpress"]
|
||||
|
@ -470,7 +469,7 @@ def test_restore_app_script_failure_handling(monkeypatch, mocker):
|
|||
assert not _is_installed("wordpress")
|
||||
|
||||
|
||||
@pytest.mark.with_wordpress_archive_from_4p2
|
||||
@pytest.mark.with_wordpress_archive_from_11p2
|
||||
def test_restore_app_not_enough_free_space(monkeypatch, mocker):
|
||||
def custom_free_space_in_directory(dirpath):
|
||||
return 0
|
||||
|
@ -489,12 +488,12 @@ def test_restore_app_not_enough_free_space(monkeypatch, mocker):
|
|||
assert not _is_installed("wordpress")
|
||||
|
||||
|
||||
@pytest.mark.with_wordpress_archive_from_4p2
|
||||
@pytest.mark.with_wordpress_archive_from_11p2
|
||||
def test_restore_app_not_in_backup(mocker):
|
||||
assert not _is_installed("wordpress")
|
||||
assert not _is_installed("yoloswag")
|
||||
|
||||
with message(mocker, "backup_archive_app_not_found", app="yoloswag"):
|
||||
with message("backup_archive_app_not_found", app="yoloswag"):
|
||||
with raiseYunohostError(mocker, "restore_nothings_done"):
|
||||
backup_restore(
|
||||
system=None, name=backup_list()["archives"][0], apps=["yoloswag"]
|
||||
|
@ -504,12 +503,12 @@ def test_restore_app_not_in_backup(mocker):
|
|||
assert not _is_installed("yoloswag")
|
||||
|
||||
|
||||
@pytest.mark.with_wordpress_archive_from_4p2
|
||||
@pytest.mark.with_wordpress_archive_from_11p2
|
||||
@pytest.mark.with_custom_domain("yolo.test")
|
||||
def test_restore_app_already_installed(mocker):
|
||||
assert not _is_installed("wordpress")
|
||||
|
||||
with message(mocker, "restore_complete"):
|
||||
with message("restore_complete"):
|
||||
backup_restore(
|
||||
system=None, name=backup_list()["archives"][0], apps=["wordpress"]
|
||||
)
|
||||
|
@ -525,22 +524,22 @@ def test_restore_app_already_installed(mocker):
|
|||
|
||||
|
||||
@pytest.mark.with_legacy_app_installed
|
||||
def test_backup_and_restore_legacy_app(mocker):
|
||||
_test_backup_and_restore_app(mocker, "legacy_app")
|
||||
def test_backup_and_restore_legacy_app():
|
||||
_test_backup_and_restore_app("legacy_app")
|
||||
|
||||
|
||||
@pytest.mark.with_backup_recommended_app_installed
|
||||
def test_backup_and_restore_recommended_app(mocker):
|
||||
_test_backup_and_restore_app(mocker, "backup_recommended_app")
|
||||
def test_backup_and_restore_recommended_app():
|
||||
_test_backup_and_restore_app("backup_recommended_app")
|
||||
|
||||
|
||||
@pytest.mark.with_backup_recommended_app_installed_with_ynh_restore
|
||||
def test_backup_and_restore_with_ynh_restore(mocker):
|
||||
_test_backup_and_restore_app(mocker, "backup_recommended_app")
|
||||
def test_backup_and_restore_with_ynh_restore():
|
||||
_test_backup_and_restore_app("backup_recommended_app")
|
||||
|
||||
|
||||
@pytest.mark.with_permission_app_installed
|
||||
def test_backup_and_restore_permission_app(mocker):
|
||||
def test_backup_and_restore_permission_app():
|
||||
res = user_permission_list(full=True)["permissions"]
|
||||
assert "permissions_app.main" in res
|
||||
assert "permissions_app.admin" in res
|
||||
|
@ -554,7 +553,7 @@ def test_backup_and_restore_permission_app(mocker):
|
|||
assert res["permissions_app.admin"]["allowed"] == ["alice"]
|
||||
assert res["permissions_app.dev"]["allowed"] == []
|
||||
|
||||
_test_backup_and_restore_app(mocker, "permissions_app")
|
||||
_test_backup_and_restore_app("permissions_app")
|
||||
|
||||
res = user_permission_list(full=True)["permissions"]
|
||||
assert "permissions_app.main" in res
|
||||
|
@ -570,10 +569,10 @@ def test_backup_and_restore_permission_app(mocker):
|
|||
assert res["permissions_app.dev"]["allowed"] == []
|
||||
|
||||
|
||||
def _test_backup_and_restore_app(mocker, app):
|
||||
def _test_backup_and_restore_app(app):
|
||||
# Create a backup of this app
|
||||
name = random_ascii(8)
|
||||
with message(mocker, "backup_created", name=name):
|
||||
with message("backup_created", name=name):
|
||||
backup_create(name=name, system=None, apps=[app])
|
||||
|
||||
archives = backup_list()["archives"]
|
||||
|
@ -590,7 +589,7 @@ def _test_backup_and_restore_app(mocker, app):
|
|||
assert app + ".main" not in user_permission_list()["permissions"]
|
||||
|
||||
# Restore the app
|
||||
with message(mocker, "restore_complete"):
|
||||
with message("restore_complete"):
|
||||
backup_restore(system=None, name=archives[0], apps=[app])
|
||||
|
||||
assert app_is_installed(app)
|
||||
|
@ -616,34 +615,34 @@ def test_restore_archive_with_no_json(mocker):
|
|||
backup_restore(name="badbackup", force=True)
|
||||
|
||||
|
||||
@pytest.mark.with_wordpress_archive_from_4p2
|
||||
@pytest.mark.with_wordpress_archive_from_11p2
|
||||
def test_restore_archive_with_bad_archive(mocker):
|
||||
# Break the archive
|
||||
os.system(
|
||||
"head -n 1000 /home/yunohost.backup/archives/backup_wordpress_from_4p2.tar > /home/yunohost.backup/archives/backup_wordpress_from_4p2_bad.tar"
|
||||
"head -n 1000 /home/yunohost.backup/archives/backup_wordpress_from_11p2.tar > /home/yunohost.backup/archives/backup_wordpress_from_11p2_bad.tar"
|
||||
)
|
||||
|
||||
assert "backup_wordpress_from_4p2_bad" in backup_list()["archives"]
|
||||
assert "backup_wordpress_from_11p2_bad" in backup_list()["archives"]
|
||||
|
||||
with raiseYunohostError(mocker, "backup_archive_corrupted"):
|
||||
backup_restore(name="backup_wordpress_from_4p2_bad", force=True)
|
||||
backup_restore(name="backup_wordpress_from_11p2_bad", force=True)
|
||||
|
||||
clean_tmp_backup_directory()
|
||||
|
||||
|
||||
def test_restore_archive_with_custom_hook(mocker):
|
||||
def test_restore_archive_with_custom_hook():
|
||||
custom_restore_hook_folder = os.path.join(CUSTOM_HOOK_FOLDER, "restore")
|
||||
os.system("touch %s/99-yolo" % custom_restore_hook_folder)
|
||||
|
||||
# Backup with custom hook system
|
||||
name = random_ascii(8)
|
||||
with message(mocker, "backup_created", name=name):
|
||||
with message("backup_created", name=name):
|
||||
backup_create(name=name, system=[], apps=None)
|
||||
archives = backup_list()["archives"]
|
||||
assert len(archives) == 1
|
||||
|
||||
# Restore system with custom hook
|
||||
with message(mocker, "restore_complete"):
|
||||
with message("restore_complete"):
|
||||
backup_restore(
|
||||
name=backup_list()["archives"][0], system=[], apps=None, force=True
|
||||
)
|
||||
|
@ -651,7 +650,7 @@ def test_restore_archive_with_custom_hook(mocker):
|
|||
os.system("rm %s/99-yolo" % custom_restore_hook_folder)
|
||||
|
||||
|
||||
def test_backup_binds_are_readonly(mocker, monkeypatch):
|
||||
def test_backup_binds_are_readonly(monkeypatch):
|
||||
def custom_mount_and_backup(self):
|
||||
self._organize_files()
|
||||
|
||||
|
@ -676,5 +675,5 @@ def test_backup_binds_are_readonly(mocker, monkeypatch):
|
|||
|
||||
# Create the backup
|
||||
name = random_ascii(8)
|
||||
with message(mocker, "backup_created", name=name):
|
||||
with message("backup_created", name=name):
|
||||
backup_create(name=name, system=[])
|
||||
|
|
|
@ -39,7 +39,7 @@ def check_changeurl_app(path):
|
|||
assert appmap[maindomain][path]["id"] == "change_url_app"
|
||||
|
||||
r = requests.get(
|
||||
"https://127.0.0.1%s/" % path, headers={"domain": maindomain}, verify=False
|
||||
"https://127.0.0.1%s/" % path, headers={"Host": maindomain}, verify=False
|
||||
)
|
||||
assert r.status_code == 200
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ def test_authenticate_with_wrong_password():
|
|||
assert expected_msg in str(exception)
|
||||
|
||||
|
||||
def test_authenticate_server_down(mocker):
|
||||
def test_authenticate_server_down():
|
||||
os.system("systemctl stop slapd && sleep 5")
|
||||
|
||||
LDAPAuth().authenticate_credentials(credentials="alice:Yunohost")
|
||||
|
|
|
@ -435,8 +435,8 @@ def test_permission_list():
|
|||
#
|
||||
|
||||
|
||||
def test_permission_create_main(mocker):
|
||||
with message(mocker, "permission_created", permission="site.main"):
|
||||
def test_permission_create_main():
|
||||
with message("permission_created", permission="site.main"):
|
||||
permission_create("site.main", allowed=["all_users"], protected=False)
|
||||
|
||||
res = user_permission_list(full=True)["permissions"]
|
||||
|
@ -446,8 +446,8 @@ def test_permission_create_main(mocker):
|
|||
assert res["site.main"]["protected"] is False
|
||||
|
||||
|
||||
def test_permission_create_extra(mocker):
|
||||
with message(mocker, "permission_created", permission="site.test"):
|
||||
def test_permission_create_extra():
|
||||
with message("permission_created", permission="site.test"):
|
||||
permission_create("site.test")
|
||||
|
||||
res = user_permission_list(full=True)["permissions"]
|
||||
|
@ -466,8 +466,8 @@ def test_permission_create_with_specific_user():
|
|||
assert res["site.test"]["allowed"] == ["alice"]
|
||||
|
||||
|
||||
def test_permission_create_with_tile_management(mocker):
|
||||
with message(mocker, "permission_created", permission="site.main"):
|
||||
def test_permission_create_with_tile_management():
|
||||
with message("permission_created", permission="site.main"):
|
||||
_permission_create_with_dummy_app(
|
||||
"site.main",
|
||||
allowed=["all_users"],
|
||||
|
@ -483,8 +483,8 @@ def test_permission_create_with_tile_management(mocker):
|
|||
assert res["site.main"]["show_tile"] is False
|
||||
|
||||
|
||||
def test_permission_create_with_tile_management_with_main_default_value(mocker):
|
||||
with message(mocker, "permission_created", permission="site.main"):
|
||||
def test_permission_create_with_tile_management_with_main_default_value():
|
||||
with message("permission_created", permission="site.main"):
|
||||
_permission_create_with_dummy_app(
|
||||
"site.main",
|
||||
allowed=["all_users"],
|
||||
|
@ -500,8 +500,8 @@ def test_permission_create_with_tile_management_with_main_default_value(mocker):
|
|||
assert res["site.main"]["show_tile"] is True
|
||||
|
||||
|
||||
def test_permission_create_with_tile_management_with_not_main_default_value(mocker):
|
||||
with message(mocker, "permission_created", permission="wiki.api"):
|
||||
def test_permission_create_with_tile_management_with_not_main_default_value():
|
||||
with message("permission_created", permission="wiki.api"):
|
||||
_permission_create_with_dummy_app(
|
||||
"wiki.api",
|
||||
allowed=["all_users"],
|
||||
|
@ -517,8 +517,8 @@ def test_permission_create_with_tile_management_with_not_main_default_value(mock
|
|||
assert res["wiki.api"]["show_tile"] is True
|
||||
|
||||
|
||||
def test_permission_create_with_urls_management_without_url(mocker):
|
||||
with message(mocker, "permission_created", permission="wiki.api"):
|
||||
def test_permission_create_with_urls_management_without_url():
|
||||
with message("permission_created", permission="wiki.api"):
|
||||
_permission_create_with_dummy_app(
|
||||
"wiki.api", allowed=["all_users"], domain=maindomain, path="/site"
|
||||
)
|
||||
|
@ -530,8 +530,8 @@ def test_permission_create_with_urls_management_without_url(mocker):
|
|||
assert res["wiki.api"]["auth_header"] is True
|
||||
|
||||
|
||||
def test_permission_create_with_urls_management_simple_domain(mocker):
|
||||
with message(mocker, "permission_created", permission="site.main"):
|
||||
def test_permission_create_with_urls_management_simple_domain():
|
||||
with message("permission_created", permission="site.main"):
|
||||
_permission_create_with_dummy_app(
|
||||
"site.main",
|
||||
allowed=["all_users"],
|
||||
|
@ -553,8 +553,8 @@ def test_permission_create_with_urls_management_simple_domain(mocker):
|
|||
|
||||
|
||||
@pytest.mark.other_domains(number=2)
|
||||
def test_permission_create_with_urls_management_multiple_domain(mocker):
|
||||
with message(mocker, "permission_created", permission="site.main"):
|
||||
def test_permission_create_with_urls_management_multiple_domain():
|
||||
with message("permission_created", permission="site.main"):
|
||||
_permission_create_with_dummy_app(
|
||||
"site.main",
|
||||
allowed=["all_users"],
|
||||
|
@ -575,14 +575,14 @@ def test_permission_create_with_urls_management_multiple_domain(mocker):
|
|||
assert res["site.main"]["auth_header"] is True
|
||||
|
||||
|
||||
def test_permission_delete(mocker):
|
||||
with message(mocker, "permission_deleted", permission="wiki.main"):
|
||||
def test_permission_delete():
|
||||
with message("permission_deleted", permission="wiki.main"):
|
||||
permission_delete("wiki.main", force=True)
|
||||
|
||||
res = user_permission_list()["permissions"]
|
||||
assert "wiki.main" not in res
|
||||
|
||||
with message(mocker, "permission_deleted", permission="blog.api"):
|
||||
with message("permission_deleted", permission="blog.api"):
|
||||
permission_delete("blog.api", force=False)
|
||||
|
||||
res = user_permission_list()["permissions"]
|
||||
|
@ -625,8 +625,8 @@ def test_permission_delete_main_without_force(mocker):
|
|||
# user side functions
|
||||
|
||||
|
||||
def test_permission_add_group(mocker):
|
||||
with message(mocker, "permission_updated", permission="wiki.main"):
|
||||
def test_permission_add_group():
|
||||
with message("permission_updated", permission="wiki.main"):
|
||||
user_permission_update("wiki.main", add="alice")
|
||||
|
||||
res = user_permission_list(full=True)["permissions"]
|
||||
|
@ -634,8 +634,8 @@ def test_permission_add_group(mocker):
|
|||
assert set(res["wiki.main"]["corresponding_users"]) == {"alice", "bob"}
|
||||
|
||||
|
||||
def test_permission_remove_group(mocker):
|
||||
with message(mocker, "permission_updated", permission="blog.main"):
|
||||
def test_permission_remove_group():
|
||||
with message("permission_updated", permission="blog.main"):
|
||||
user_permission_update("blog.main", remove="alice")
|
||||
|
||||
res = user_permission_list(full=True)["permissions"]
|
||||
|
@ -643,8 +643,8 @@ def test_permission_remove_group(mocker):
|
|||
assert res["blog.main"]["corresponding_users"] == []
|
||||
|
||||
|
||||
def test_permission_add_and_remove_group(mocker):
|
||||
with message(mocker, "permission_updated", permission="wiki.main"):
|
||||
def test_permission_add_and_remove_group():
|
||||
with message("permission_updated", permission="wiki.main"):
|
||||
user_permission_update("wiki.main", add="alice", remove="all_users")
|
||||
|
||||
res = user_permission_list(full=True)["permissions"]
|
||||
|
@ -652,9 +652,9 @@ def test_permission_add_and_remove_group(mocker):
|
|||
assert res["wiki.main"]["corresponding_users"] == ["alice"]
|
||||
|
||||
|
||||
def test_permission_add_group_already_allowed(mocker):
|
||||
def test_permission_add_group_already_allowed():
|
||||
with message(
|
||||
mocker, "permission_already_allowed", permission="blog.main", group="alice"
|
||||
"permission_already_allowed", permission="blog.main", group="alice"
|
||||
):
|
||||
user_permission_update("blog.main", add="alice")
|
||||
|
||||
|
@ -663,9 +663,9 @@ def test_permission_add_group_already_allowed(mocker):
|
|||
assert res["blog.main"]["corresponding_users"] == ["alice"]
|
||||
|
||||
|
||||
def test_permission_remove_group_already_not_allowed(mocker):
|
||||
def test_permission_remove_group_already_not_allowed():
|
||||
with message(
|
||||
mocker, "permission_already_disallowed", permission="blog.main", group="bob"
|
||||
"permission_already_disallowed", permission="blog.main", group="bob"
|
||||
):
|
||||
user_permission_update("blog.main", remove="bob")
|
||||
|
||||
|
@ -674,8 +674,8 @@ def test_permission_remove_group_already_not_allowed(mocker):
|
|||
assert res["blog.main"]["corresponding_users"] == ["alice"]
|
||||
|
||||
|
||||
def test_permission_reset(mocker):
|
||||
with message(mocker, "permission_updated", permission="blog.main"):
|
||||
def test_permission_reset():
|
||||
with message("permission_updated", permission="blog.main"):
|
||||
user_permission_reset("blog.main")
|
||||
|
||||
res = user_permission_list(full=True)["permissions"]
|
||||
|
@ -693,42 +693,42 @@ def test_permission_reset_idempotency():
|
|||
assert set(res["blog.main"]["corresponding_users"]) == {"alice", "bob"}
|
||||
|
||||
|
||||
def test_permission_change_label(mocker):
|
||||
with message(mocker, "permission_updated", permission="wiki.main"):
|
||||
def test_permission_change_label():
|
||||
with message("permission_updated", permission="wiki.main"):
|
||||
user_permission_update("wiki.main", label="New Wiki")
|
||||
|
||||
res = user_permission_list(full=True)["permissions"]
|
||||
assert res["wiki.main"]["label"] == "New Wiki"
|
||||
|
||||
|
||||
def test_permission_change_label_with_same_value(mocker):
|
||||
with message(mocker, "permission_updated", permission="wiki.main"):
|
||||
def test_permission_change_label_with_same_value():
|
||||
with message("permission_updated", permission="wiki.main"):
|
||||
user_permission_update("wiki.main", label="Wiki")
|
||||
|
||||
res = user_permission_list(full=True)["permissions"]
|
||||
assert res["wiki.main"]["label"] == "Wiki"
|
||||
|
||||
|
||||
def test_permission_switch_show_tile(mocker):
|
||||
def test_permission_switch_show_tile():
|
||||
# Note that from the actionmap the value is passed as string, not as bool
|
||||
# Try with lowercase
|
||||
with message(mocker, "permission_updated", permission="wiki.main"):
|
||||
with message("permission_updated", permission="wiki.main"):
|
||||
user_permission_update("wiki.main", show_tile="false")
|
||||
|
||||
res = user_permission_list(full=True)["permissions"]
|
||||
assert res["wiki.main"]["show_tile"] is False
|
||||
|
||||
# Try with uppercase
|
||||
with message(mocker, "permission_updated", permission="wiki.main"):
|
||||
with message("permission_updated", permission="wiki.main"):
|
||||
user_permission_update("wiki.main", show_tile="TRUE")
|
||||
|
||||
res = user_permission_list(full=True)["permissions"]
|
||||
assert res["wiki.main"]["show_tile"] is True
|
||||
|
||||
|
||||
def test_permission_switch_show_tile_with_same_value(mocker):
|
||||
def test_permission_switch_show_tile_with_same_value():
|
||||
# Note that from the actionmap the value is passed as string, not as bool
|
||||
with message(mocker, "permission_updated", permission="wiki.main"):
|
||||
with message("permission_updated", permission="wiki.main"):
|
||||
user_permission_update("wiki.main", show_tile="True")
|
||||
|
||||
res = user_permission_list(full=True)["permissions"]
|
||||
|
@ -806,7 +806,7 @@ def test_permission_main_url_regex():
|
|||
|
||||
def test_permission_main_url_bad_regex(mocker):
|
||||
with raiseYunohostError(mocker, "invalid_regex"):
|
||||
permission_url("blog.main", url="re:/[a-z]++reboy/.*")
|
||||
permission_url("blog.main", url="re:/[a-z]+++reboy/.*")
|
||||
|
||||
|
||||
@pytest.mark.other_domains(number=1)
|
||||
|
@ -837,7 +837,7 @@ def test_permission_add_additional_regex():
|
|||
|
||||
def test_permission_add_additional_bad_regex(mocker):
|
||||
with raiseYunohostError(mocker, "invalid_regex"):
|
||||
permission_url("blog.main", add_url=["re:/[a-z]++reboy/.*"])
|
||||
permission_url("blog.main", add_url=["re:/[a-z]+++reboy/.*"])
|
||||
|
||||
|
||||
def test_permission_remove_additional_url():
|
||||
|
@ -1131,7 +1131,7 @@ def test_permission_app_propagation_on_ssowat():
|
|||
def test_permission_legacy_app_propagation_on_ssowat():
|
||||
app_install(
|
||||
os.path.join(get_test_apps_dir(), "legacy_app_ynh"),
|
||||
args="domain=%s&domain_2=%s&path=%s&is_public=1"
|
||||
args="domain=%s&domain_2=%s&path=%s&is_public=0"
|
||||
% (maindomain, other_domains[0], "/legacy"),
|
||||
force=True,
|
||||
)
|
||||
|
@ -1139,12 +1139,12 @@ def test_permission_legacy_app_propagation_on_ssowat():
|
|||
# App is configured as public by default using the legacy unprotected_uri mechanics
|
||||
# It should automatically be migrated during the install
|
||||
res = user_permission_list(full=True)["permissions"]
|
||||
assert "visitors" in res["legacy_app.main"]["allowed"]
|
||||
assert "visitors" not in res["legacy_app.main"]["allowed"]
|
||||
assert "all_users" in res["legacy_app.main"]["allowed"]
|
||||
|
||||
app_webroot = "https://%s/legacy" % maindomain
|
||||
|
||||
assert can_access_webpage(app_webroot, logged_as=None)
|
||||
assert not can_access_webpage(app_webroot, logged_as=None)
|
||||
assert can_access_webpage(app_webroot, logged_as="alice")
|
||||
|
||||
# Try to update the permission and check that permissions are still consistent
|
||||
|
|
|
@ -87,7 +87,7 @@ def test_ssh_conf_unmanaged():
|
|||
assert SSHD_CONFIG in _get_conf_hashes("ssh")
|
||||
|
||||
|
||||
def test_ssh_conf_unmanaged_and_manually_modified(mocker):
|
||||
def test_ssh_conf_unmanaged_and_manually_modified():
|
||||
_force_clear_hashes([SSHD_CONFIG])
|
||||
os.system("echo ' ' >> %s" % SSHD_CONFIG)
|
||||
|
||||
|
@ -98,7 +98,7 @@ def test_ssh_conf_unmanaged_and_manually_modified(mocker):
|
|||
assert SSHD_CONFIG in _get_conf_hashes("ssh")
|
||||
assert SSHD_CONFIG in manually_modified_files()
|
||||
|
||||
with message(mocker, "regenconf_need_to_explicitly_specify_ssh"):
|
||||
with message("regenconf_need_to_explicitly_specify_ssh"):
|
||||
regen_conf(force=True)
|
||||
|
||||
assert SSHD_CONFIG in _get_conf_hashes("ssh")
|
||||
|
|
|
@ -91,8 +91,8 @@ def test_list_groups():
|
|||
#
|
||||
|
||||
|
||||
def test_create_user(mocker):
|
||||
with message(mocker, "user_created"):
|
||||
def test_create_user():
|
||||
with message("user_created"):
|
||||
user_create("albert", maindomain, "test123Ynh", fullname="Albert Good")
|
||||
|
||||
group_res = user_group_list()["groups"]
|
||||
|
@ -102,8 +102,8 @@ def test_create_user(mocker):
|
|||
assert "albert" in group_res["all_users"]["members"]
|
||||
|
||||
|
||||
def test_del_user(mocker):
|
||||
with message(mocker, "user_deleted"):
|
||||
def test_del_user():
|
||||
with message("user_deleted"):
|
||||
user_delete("alice")
|
||||
|
||||
group_res = user_group_list()["groups"]
|
||||
|
@ -112,7 +112,7 @@ def test_del_user(mocker):
|
|||
assert "alice" not in group_res["all_users"]["members"]
|
||||
|
||||
|
||||
def test_import_user(mocker):
|
||||
def test_import_user():
|
||||
import csv
|
||||
from io import StringIO
|
||||
|
||||
|
@ -157,7 +157,7 @@ def test_import_user(mocker):
|
|||
}
|
||||
)
|
||||
csv_io.seek(0)
|
||||
with message(mocker, "user_import_success"):
|
||||
with message("user_import_success"):
|
||||
user_import(csv_io, update=True, delete=True)
|
||||
|
||||
group_res = user_group_list()["groups"]
|
||||
|
@ -171,7 +171,7 @@ def test_import_user(mocker):
|
|||
assert "alice" not in group_res["dev"]["members"]
|
||||
|
||||
|
||||
def test_export_user(mocker):
|
||||
def test_export_user():
|
||||
result = user_export()
|
||||
should_be = (
|
||||
"username;firstname;lastname;password;mail;mail-alias;mail-forward;mailbox-quota;groups\r\n"
|
||||
|
@ -182,8 +182,8 @@ def test_export_user(mocker):
|
|||
assert result == should_be
|
||||
|
||||
|
||||
def test_create_group(mocker):
|
||||
with message(mocker, "group_created", group="adminsys"):
|
||||
def test_create_group():
|
||||
with message("group_created", group="adminsys"):
|
||||
user_group_create("adminsys")
|
||||
|
||||
group_res = user_group_list()["groups"]
|
||||
|
@ -192,8 +192,8 @@ def test_create_group(mocker):
|
|||
assert group_res["adminsys"]["members"] == []
|
||||
|
||||
|
||||
def test_del_group(mocker):
|
||||
with message(mocker, "group_deleted", group="dev"):
|
||||
def test_del_group():
|
||||
with message("group_deleted", group="dev"):
|
||||
user_group_delete("dev")
|
||||
|
||||
group_res = user_group_list()["groups"]
|
||||
|
@ -262,46 +262,40 @@ def test_del_group_that_does_not_exist(mocker):
|
|||
#
|
||||
|
||||
|
||||
def test_update_user(mocker):
|
||||
with message(mocker, "user_updated"):
|
||||
user_update("alice", firstname="NewName", lastname="NewLast")
|
||||
|
||||
info = user_info("alice")
|
||||
assert info["fullname"] == "NewName NewLast"
|
||||
|
||||
with message(mocker, "user_updated"):
|
||||
def test_update_user():
|
||||
with message("user_updated"):
|
||||
user_update("alice", fullname="New2Name New2Last")
|
||||
|
||||
info = user_info("alice")
|
||||
assert info["fullname"] == "New2Name New2Last"
|
||||
|
||||
|
||||
def test_update_group_add_user(mocker):
|
||||
with message(mocker, "group_updated", group="dev"):
|
||||
def test_update_group_add_user():
|
||||
with message("group_updated", group="dev"):
|
||||
user_group_update("dev", add=["bob"])
|
||||
|
||||
group_res = user_group_list()["groups"]
|
||||
assert set(group_res["dev"]["members"]) == {"alice", "bob"}
|
||||
|
||||
|
||||
def test_update_group_add_user_already_in(mocker):
|
||||
with message(mocker, "group_user_already_in_group", user="bob", group="apps"):
|
||||
def test_update_group_add_user_already_in():
|
||||
with message("group_user_already_in_group", user="bob", group="apps"):
|
||||
user_group_update("apps", add=["bob"])
|
||||
|
||||
group_res = user_group_list()["groups"]
|
||||
assert group_res["apps"]["members"] == ["bob"]
|
||||
|
||||
|
||||
def test_update_group_remove_user(mocker):
|
||||
with message(mocker, "group_updated", group="apps"):
|
||||
def test_update_group_remove_user():
|
||||
with message("group_updated", group="apps"):
|
||||
user_group_update("apps", remove=["bob"])
|
||||
|
||||
group_res = user_group_list()["groups"]
|
||||
assert group_res["apps"]["members"] == []
|
||||
|
||||
|
||||
def test_update_group_remove_user_not_already_in(mocker):
|
||||
with message(mocker, "group_user_not_in_group", user="jack", group="apps"):
|
||||
def test_update_group_remove_user_not_already_in():
|
||||
with message("group_user_not_in_group", user="jack", group="apps"):
|
||||
user_group_update("apps", remove=["jack"])
|
||||
|
||||
group_res = user_group_list()["groups"]
|
||||
|
@ -315,7 +309,7 @@ def test_update_group_remove_user_not_already_in(mocker):
|
|||
|
||||
def test_update_user_that_doesnt_exist(mocker):
|
||||
with raiseYunohostError(mocker, "user_unknown"):
|
||||
user_update("doesnt_exist", firstname="NewName", lastname="NewLast")
|
||||
user_update("doesnt_exist", fullname="Foo Bar")
|
||||
|
||||
|
||||
def test_update_group_that_doesnt_exist(mocker):
|
||||
|
|
|
@ -24,9 +24,9 @@ import time
|
|||
from importlib import import_module
|
||||
from packaging import version
|
||||
from typing import List
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import Moulinette, m18n
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.process import call_async_output
|
||||
from moulinette.utils.filesystem import read_yaml, write_to_yaml, cp, mkdir, rm, chown
|
||||
|
||||
|
@ -55,7 +55,7 @@ from yunohost.log import is_unit_operation, OperationLogger
|
|||
|
||||
MIGRATIONS_STATE_PATH = "/etc/yunohost/migrations.yaml"
|
||||
|
||||
logger = getActionLogger("yunohost.tools")
|
||||
logger = getLogger("yunohost.tools")
|
||||
|
||||
|
||||
def tools_versions():
|
||||
|
|
49
src/user.py
49
src/user.py
|
@ -25,9 +25,9 @@ import random
|
|||
import string
|
||||
import subprocess
|
||||
import copy
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import Moulinette, m18n
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.process import check_output
|
||||
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
|
@ -35,7 +35,7 @@ from yunohost.service import service_status
|
|||
from yunohost.log import is_unit_operation
|
||||
from yunohost.utils.system import binary_to_human
|
||||
|
||||
logger = getActionLogger("yunohost.user")
|
||||
logger = getLogger("yunohost.user")
|
||||
|
||||
FIELDS_FOR_IMPORT = {
|
||||
"username": r"^[a-z0-9_]+$",
|
||||
|
@ -141,33 +141,20 @@ def user_create(
|
|||
domain,
|
||||
password,
|
||||
fullname=None,
|
||||
firstname=None,
|
||||
lastname=None,
|
||||
mailbox_quota="0",
|
||||
admin=False,
|
||||
from_import=False,
|
||||
loginShell=None,
|
||||
):
|
||||
if firstname or lastname:
|
||||
logger.warning(
|
||||
"Options --firstname / --lastname of 'yunohost user create' are deprecated. We recommend using --fullname instead."
|
||||
)
|
||||
|
||||
if not fullname or not fullname.strip():
|
||||
if not firstname.strip():
|
||||
raise YunohostValidationError(
|
||||
"You should specify the fullname of the user using option -F"
|
||||
)
|
||||
lastname = (
|
||||
lastname or " "
|
||||
) # Stupid hack because LDAP requires the sn/lastname attr, but it accepts a single whitespace...
|
||||
fullname = f"{firstname} {lastname}".strip()
|
||||
else:
|
||||
fullname = fullname.strip()
|
||||
firstname = fullname.split()[0]
|
||||
lastname = (
|
||||
" ".join(fullname.split()[1:]) or " "
|
||||
) # Stupid hack because LDAP requires the sn/lastname attr, but it accepts a single whitespace...
|
||||
raise YunohostValidationError(
|
||||
"You should specify the fullname of the user using option -F"
|
||||
)
|
||||
fullname = fullname.strip()
|
||||
firstname = fullname.split()[0]
|
||||
lastname = (
|
||||
" ".join(fullname.split()[1:]) or " "
|
||||
) # Stupid hack because LDAP requires the sn/lastname attr, but it accepts a single whitespace...
|
||||
|
||||
from yunohost.domain import domain_list, _get_maindomain, _assert_domain_exists
|
||||
from yunohost.hook import hook_callback
|
||||
|
@ -364,8 +351,6 @@ def user_delete(operation_logger, username, purge=False, from_import=False):
|
|||
def user_update(
|
||||
operation_logger,
|
||||
username,
|
||||
firstname=None,
|
||||
lastname=None,
|
||||
mail=None,
|
||||
change_password=None,
|
||||
add_mailforward=None,
|
||||
|
@ -377,17 +362,15 @@ def user_update(
|
|||
fullname=None,
|
||||
loginShell=None,
|
||||
):
|
||||
if firstname or lastname:
|
||||
logger.warning(
|
||||
"Options --firstname / --lastname of 'yunohost user create' are deprecated. We recommend using --fullname instead."
|
||||
)
|
||||
|
||||
if fullname and fullname.strip():
|
||||
fullname = fullname.strip()
|
||||
firstname = fullname.split()[0]
|
||||
lastname = (
|
||||
" ".join(fullname.split()[1:]) or " "
|
||||
) # Stupid hack because LDAP requires the sn/lastname attr, but it accepts a single whitespace...
|
||||
else:
|
||||
firstname = None
|
||||
lastname = None
|
||||
|
||||
from yunohost.domain import domain_list
|
||||
from yunohost.app import app_ssowatconf
|
||||
|
@ -884,8 +867,7 @@ def user_import(operation_logger, csvfile, update=False, delete=False):
|
|||
|
||||
user_update(
|
||||
new_infos["username"],
|
||||
firstname=new_infos["firstname"],
|
||||
lastname=new_infos["lastname"],
|
||||
fullname=(new_infos["firstname"] + " " + new_infos["lastname"]).strip(),
|
||||
change_password=new_infos["password"],
|
||||
mailbox_quota=new_infos["mailbox-quota"],
|
||||
mail=new_infos["mail"],
|
||||
|
@ -930,8 +912,7 @@ def user_import(operation_logger, csvfile, update=False, delete=False):
|
|||
user["password"],
|
||||
user["mailbox-quota"],
|
||||
from_import=True,
|
||||
firstname=user["firstname"],
|
||||
lastname=user["lastname"],
|
||||
fullname=(user["firstname"] + " " + user["lastname"]).strip(),
|
||||
)
|
||||
update(user)
|
||||
result["created"] += 1
|
||||
|
|
|
@ -22,11 +22,11 @@ import re
|
|||
import urllib.parse
|
||||
from collections import OrderedDict
|
||||
from typing import Union
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import Moulinette, m18n
|
||||
from moulinette.interfaces.cli import colorize
|
||||
from moulinette.utils.filesystem import mkdir, read_toml, read_yaml, write_to_yaml
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
from yunohost.utils.form import (
|
||||
OPTIONS,
|
||||
|
@ -40,7 +40,7 @@ from yunohost.utils.form import (
|
|||
)
|
||||
from yunohost.utils.i18n import _value_for_locale
|
||||
|
||||
logger = getActionLogger("yunohost.configpanel")
|
||||
logger = getLogger("yunohost.configpanel")
|
||||
CONFIG_PANEL_VERSION_SUPPORTED = 1.0
|
||||
|
||||
|
||||
|
@ -160,11 +160,15 @@ class ConfigPanel:
|
|||
result[key] = {"ask": ask}
|
||||
if "current_value" in option:
|
||||
question_class = OPTIONS[option.get("type", OptionType.string)]
|
||||
result[key]["value"] = question_class.humanize(
|
||||
option["current_value"], option
|
||||
)
|
||||
if hasattr(question_class, "humanize"):
|
||||
result[key]["value"] = question_class.humanize(
|
||||
option["current_value"], option
|
||||
)
|
||||
else:
|
||||
result[key]["value"] = option["current_value"]
|
||||
|
||||
# FIXME: semantics, technically here this is not about a prompt...
|
||||
if question_class.hide_user_input_in_prompt:
|
||||
if getattr(question_class, "hide_user_input_in_prompt", None):
|
||||
result[key][
|
||||
"value"
|
||||
] = "**************" # Prevent displaying password in `config get`
|
||||
|
@ -610,7 +614,7 @@ class ConfigPanel:
|
|||
{
|
||||
question.id: question.value
|
||||
for question in questions
|
||||
if question.value is not None
|
||||
if not question.readonly and question.value is not None
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -25,16 +25,16 @@ import tempfile
|
|||
import urllib.parse
|
||||
from enum import Enum
|
||||
from typing import Any, Callable, Dict, List, Literal, Mapping, Optional, Union
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import Moulinette, m18n
|
||||
from moulinette.interfaces.cli import colorize
|
||||
from moulinette.utils.filesystem import read_file, write_to_file
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from yunohost.log import OperationLogger
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
from yunohost.utils.i18n import _value_for_locale
|
||||
|
||||
logger = getActionLogger("yunohost.form")
|
||||
logger = getLogger("yunohost.form")
|
||||
|
||||
Context = dict[str, Any]
|
||||
|
||||
|
|
|
@ -19,8 +19,9 @@
|
|||
import os
|
||||
import re
|
||||
import glob
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette.core import MoulinetteError
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import (
|
||||
read_file,
|
||||
write_to_file,
|
||||
|
@ -32,7 +33,7 @@ from moulinette.utils.filesystem import (
|
|||
from yunohost.utils.error import YunohostValidationError
|
||||
|
||||
|
||||
logger = getActionLogger("yunohost.legacy")
|
||||
logger = getLogger("yunohost.utils.legacy")
|
||||
|
||||
LEGACY_PERMISSION_LABEL = {
|
||||
("nextcloud", "skipped"): "api", # .well-known
|
||||
|
@ -163,32 +164,45 @@ def translate_legacy_default_app_in_ssowant_conf_json_persistent():
|
|||
|
||||
|
||||
LEGACY_PHP_VERSION_REPLACEMENTS = [
|
||||
("/etc/php5", "/etc/php/7.4"),
|
||||
("/etc/php/7.0", "/etc/php/7.4"),
|
||||
("/etc/php/7.3", "/etc/php/7.4"),
|
||||
("/var/run/php5-fpm", "/var/run/php/php7.4-fpm"),
|
||||
("/var/run/php/php7.0-fpm", "/var/run/php/php7.4-fpm"),
|
||||
("/var/run/php/php7.3-fpm", "/var/run/php/php7.4-fpm"),
|
||||
("php5", "php7.4"),
|
||||
("php7.0", "php7.4"),
|
||||
("php7.3", "php7.4"),
|
||||
('YNH_PHP_VERSION="7.3"', 'YNH_PHP_VERSION="7.4"'),
|
||||
("/etc/php5", "/etc/php/8.2"),
|
||||
("/etc/php/7.0", "/etc/php/8.2"),
|
||||
("/etc/php/7.3", "/etc/php/8.2"),
|
||||
("/etc/php/7.4", "/etc/php/8.2"),
|
||||
("/var/run/php5-fpm", "/var/run/php/php8.2-fpm"),
|
||||
("/var/run/php/php7.0-fpm", "/var/run/php/php8.2-fpm"),
|
||||
("/var/run/php/php7.3-fpm", "/var/run/php/php8.2-fpm"),
|
||||
("/var/run/php/php7.4-fpm", "/var/run/php/php8.2-fpm"),
|
||||
("php5", "php8.2"),
|
||||
("php7.0", "php8.2"),
|
||||
("php7.3", "php8.2"),
|
||||
("php7.4", "php8.2"),
|
||||
('YNH_PHP_VERSION="7.3"', 'YNH_PHP_VERSION="8.2"'),
|
||||
('YNH_PHP_VERSION="7.4"', 'YNH_PHP_VERSION="8.2"'),
|
||||
(
|
||||
'phpversion="${phpversion:-7.0}"',
|
||||
'phpversion="${phpversion:-7.4}"',
|
||||
'phpversion="${phpversion:-8.2}"',
|
||||
), # Many helpers like the composer ones use 7.0 by default ...
|
||||
(
|
||||
'phpversion="${phpversion:-7.3}"',
|
||||
'phpversion="${phpversion:-8.2}"',
|
||||
), # Many helpers like the composer ones use 7.0 by default ...
|
||||
(
|
||||
'phpversion="${phpversion:-7.4}"',
|
||||
'phpversion="${phpversion:-8.2}"',
|
||||
), # Many helpers like the composer ones use 7.0 by default ...
|
||||
(
|
||||
'"$phpversion" == "7.0"',
|
||||
'$(bc <<< "$phpversion >= 7.4") -eq 1',
|
||||
'$(bc <<< "$phpversion >= 8.2") -eq 1',
|
||||
), # patch ynh_install_php to refuse installing/removing php <= 7.3
|
||||
(
|
||||
'"$phpversion" == "7.3"',
|
||||
'$(bc <<< "$phpversion >= 7.4") -eq 1',
|
||||
'$(bc <<< "$phpversion >= 8.2") -eq 1',
|
||||
), # patch ynh_install_php to refuse installing/removing php <= 7.3
|
||||
(
|
||||
'"$phpversion" == "7.4"',
|
||||
'$(bc <<< "$phpversion >= 8.2") -eq 1',
|
||||
), # patch ynh_install_php to refuse installing/removing php <= 7.3
|
||||
|
||||
]
|
||||
|
||||
|
||||
|
@ -217,15 +231,16 @@ def _patch_legacy_php_versions(app_folder):
|
|||
def _patch_legacy_php_versions_in_settings(app_folder):
|
||||
settings = read_yaml(os.path.join(app_folder, "settings.yml"))
|
||||
|
||||
if settings.get("fpm_config_dir") in ["/etc/php/7.0/fpm", "/etc/php/7.3/fpm"]:
|
||||
settings["fpm_config_dir"] = "/etc/php/7.4/fpm"
|
||||
if settings.get("fpm_service") in ["php7.0-fpm", "php7.3-fpm"]:
|
||||
settings["fpm_service"] = "php7.4-fpm"
|
||||
if settings.get("phpversion") in ["7.0", "7.3"]:
|
||||
settings["phpversion"] = "7.4"
|
||||
if settings.get("fpm_config_dir") in ["/etc/php/7.0/fpm", "/etc/php/7.3/fpm", "/etc/php/7.4/fpm"]:
|
||||
settings["fpm_config_dir"] = "/etc/php/8.2/fpm"
|
||||
if settings.get("fpm_service") in ["php7.0-fpm", "php7.3-fpm", "php7.4-fpm"]:
|
||||
settings["fpm_service"] = "php8.2-fpm"
|
||||
if settings.get("phpversion") in ["7.0", "7.3", "7.4"]:
|
||||
settings["phpversion"] = "8.2"
|
||||
|
||||
# We delete these checksums otherwise the file will appear as manually modified
|
||||
list_to_remove = [
|
||||
"checksum__etc_php_7.4_fpm_pool",
|
||||
"checksum__etc_php_7.3_fpm_pool",
|
||||
"checksum__etc_php_7.0_fpm_pool",
|
||||
"checksum__etc_nginx_conf.d",
|
||||
|
|
|
@ -23,11 +23,11 @@ import random
|
|||
import tempfile
|
||||
import subprocess
|
||||
from typing import Dict, Any, List, Union
|
||||
from logging import getLogger
|
||||
|
||||
from moulinette import m18n
|
||||
from moulinette.utils.text import random_ascii
|
||||
from moulinette.utils.process import check_output
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import mkdir, chown, chmod, write_to_file
|
||||
from moulinette.utils.filesystem import (
|
||||
rm,
|
||||
|
@ -35,7 +35,7 @@ from moulinette.utils.filesystem import (
|
|||
from yunohost.utils.system import system_arch
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
|
||||
logger = getActionLogger("yunohost.app_resources")
|
||||
logger = getLogger("yunohost.utils.resources")
|
||||
|
||||
|
||||
class AppResourceManager:
|
||||
|
@ -1337,8 +1337,8 @@ class DatabaseAppResource(AppResource):
|
|||
|
||||
def provision_or_update(self, context: Dict = {}):
|
||||
# This is equivalent to ynh_sanitize_dbid
|
||||
db_name = self.app.replace("-", "_").replace(".", "_")
|
||||
db_user = db_name
|
||||
db_user = self.app.replace("-", "_").replace(".", "_")
|
||||
db_name = self.get_setting("db_name") or db_user
|
||||
self.set_setting("db_name", db_name)
|
||||
self.set_setting("db_user", db_user)
|
||||
|
||||
|
@ -1372,8 +1372,8 @@ class DatabaseAppResource(AppResource):
|
|||
)
|
||||
|
||||
def deprovision(self, context: Dict = {}):
|
||||
db_name = self.app.replace("-", "_").replace(".", "_")
|
||||
db_user = db_name
|
||||
db_user = self.app.replace("-", "_").replace(".", "_")
|
||||
db_name = self.get_setting("db_name") or db_user
|
||||
|
||||
if self.dbtype == "mysql":
|
||||
self._run_script(
|
||||
|
|
18
tox.ini
18
tox.ini
|
@ -1,15 +1,15 @@
|
|||
[tox]
|
||||
envlist = py39-{lint,invalidcode},py39-black-{run,check}
|
||||
envlist = py311-{lint,invalidcode},py311-black-{run,check}
|
||||
|
||||
[testenv]
|
||||
skip_install=True
|
||||
deps =
|
||||
py39-{lint,invalidcode}: flake8
|
||||
py39-black-{run,check}: black
|
||||
py39-mypy: mypy >= 0.900
|
||||
py311-{lint,invalidcode}: flake8
|
||||
py311-black-{run,check}: black
|
||||
py311-mypy: mypy >= 0.900
|
||||
commands =
|
||||
py39-lint: flake8 src doc maintenance tests --ignore E402,E501,E203,W503,E741 --exclude src/tests,src/vendor
|
||||
py39-invalidcode: flake8 src bin maintenance --exclude src/tests,src/vendor --select F,E722,W605
|
||||
py39-black-check: black --check --diff bin src doc maintenance tests
|
||||
py39-black-run: black bin src doc maintenance tests
|
||||
py39-mypy: mypy --ignore-missing-import --install-types --non-interactive --follow-imports silent src/ --exclude (acme_tiny|migrations)
|
||||
py311-lint: flake8 src doc maintenance tests --ignore E402,E501,E203,W503,E741 --exclude src/tests,src/vendor
|
||||
py311-invalidcode: flake8 src bin maintenance --exclude src/tests,src/vendor --select F,E722,W605
|
||||
py311-black-check: black --check --diff bin src doc maintenance tests
|
||||
py311-black-run: black bin src doc maintenance tests
|
||||
py311-mypy: mypy --ignore-missing-import --install-types --non-interactive --follow-imports silent src/ --exclude (acme_tiny|migrations)
|
||||
|
|
Loading…
Add table
Reference in a new issue