Misc legacy cleanup

This commit is contained in:
Alexandre Aubin 2021-05-28 02:17:40 +02:00
parent 3fa96fc91b
commit 1051dbb3cc
20 changed files with 10 additions and 1472 deletions

View file

@ -97,9 +97,6 @@ user:
pattern: &pattern_lastname
- !!str ^([^\W\d_]{1,30}[ ,.'-]{0,3})+$
- "pattern_lastname"
-m:
full: --mail
help: (Deprecated, see --domain) Main unique email address
-p:
full: --password
help: User password
@ -596,9 +593,6 @@ app:
app:
help: Name, local path or git URL of the app to fetch the manifest of
fetchlist:
deprecated: true
### app_list()
list:
action_help: List installed apps
@ -770,36 +764,6 @@ app:
new_label:
help: New app label
### app_addaccess() TODO: Write help
addaccess:
action_help: Grant access right to users (everyone by default)
deprecated: true
arguments:
apps:
nargs: "+"
-u:
full: --users
nargs: "*"
### app_removeaccess() TODO: Write help
removeaccess:
action_help: Revoke access right to users (everyone by default)
deprecated: true
arguments:
apps:
nargs: "+"
-u:
full: --users
nargs: "*"
### app_clearaccess()
clearaccess:
action_help: Reset access rights for the app
deprecated: true
arguments:
apps:
nargs: "+"
subcategories:
action:
@ -1023,13 +987,6 @@ service:
full: --log
help: Absolute path to log file to display
nargs: "+"
-t:
full: --log_type
help: Type of the log (file or systemd)
nargs: "+"
choices:
- file
- systemd
--test_status:
help: Specify a custom bash command to check the status of the service. Note that it only makes sense to specify this if the corresponding systemd service does not return the proper information already.
--test_conf:
@ -1043,9 +1000,6 @@ service:
full: --need_lock
help: Use this option to prevent deadlocks if the service does invoke yunohost commands.
action: store_true
-s:
full: --status
help: Deprecated, old option. Does nothing anymore. Possibly check the --test_status option.
### service_remove()
remove:
@ -1147,35 +1101,6 @@ service:
default: 50
type: int
### service_regen_conf()
regen-conf:
action_help: Regenerate the configuration file(s) for a service
deprecated_alias:
- regenconf
arguments:
names:
help: Services name to regenerate configuration of
nargs: "*"
metavar: NAME
-d:
full: --with-diff
help: Show differences in case of configuration changes
action: store_true
-f:
full: --force
help: >
Override all manual modifications in configuration
files
action: store_true
-n:
full: --dry-run
help: Show what would have been regenerated
action: store_true
-p:
full: --list-pending
help: List pending configuration files and exit
action: store_true
#############################
# Firewall #
#############################
@ -1351,14 +1276,6 @@ dyndns:
full: --ipv6
help: IPv6 address to send
### dyndns_installcron()
installcron:
deprecated: true
### dyndns_removecron()
removecron:
deprecated: true
#############################
# Tools #
@ -1438,12 +1355,6 @@ tools:
nargs: "?"
metavar: TARGET
default: all
--apps:
help: (Deprecated, see first positional arg) Fetch the application list to check which apps can be upgraded
action: store_true
--system:
help: (Deprecated, see first positional arg) Fetch available system packages upgrades (equivalent to apt update)
action: store_true
### tools_upgrade()
upgrade:
@ -1456,12 +1367,6 @@ tools:
- apps
- system
nargs: "?"
--apps:
help: (Deprecated, see first positional arg) Upgrade all applications
action: store_true
--system:
help: (Deprecated, see first positional arg) Upgrade only the system packages
action: store_true
### tools_shell()
shell:

View file

@ -9,7 +9,6 @@ CAN_BIND=${CAN_BIND:-1}
# | arg: -d, --dest_path= - destination file or directory inside the backup dir
# | arg: -b, --is_big - Indicate data are big (mail, video, image ...)
# | arg: -m, --not_mandatory - Indicate that if the file is missing, the backup can ignore it.
# | arg: arg - Deprecated arg
#
# This helper can be used both in a system backup hook, and in an app backup script
#
@ -303,18 +302,6 @@ ynh_restore_file () {
fi
}
# Deprecated helper since it's a dangerous one!
#
# [internal]
#
ynh_bind_or_cp() {
local AS_ROOT=${3:-0}
local NO_ROOT=0
[[ "${AS_ROOT}" = "1" ]] || NO_ROOT=1
ynh_print_warn --message="This helper is deprecated, you should use ynh_backup instead"
ynh_backup "$1" "$2" 1
}
# Calculate and store a file checksum into the app settings
#
# usage: ynh_store_file_checksum --file=file

View file

@ -503,26 +503,6 @@ ynh_get_debian_release () {
echo $(lsb_release --codename --short)
}
# Create a directory under /tmp
#
# [internal]
#
# Deprecated helper
#
# usage: ynh_mkdir_tmp
# | ret: the created directory path
ynh_mkdir_tmp() {
ynh_print_warn --message="The helper ynh_mkdir_tmp is deprecated."
ynh_print_warn --message="You should use 'mktemp -d' instead and manage permissions \
properly with chmod/chown."
local TMP_DIR=$(mktemp --directory)
# Give rights to other users could be a security risk.
# But for retrocompatibility we need it. (This helpers is deprecated)
chmod 755 $TMP_DIR
echo $TMP_DIR
}
# Remove a file or a directory securely
#
# usage: ynh_secure_remove --file=path_to_remove
@ -565,38 +545,6 @@ ynh_secure_remove () {
fi
}
# Extract a key from a plain command output
#
# [internal]
#
# (Deprecated, use --output-as json and jq instead)
ynh_get_plain_key() {
local prefix="#"
local founded=0
# We call this key_ so that it's not caught as
# an info to be redacted by the core
local key_=$1
shift
while read line
do
if [[ "$founded" == "1" ]]
then
[[ "$line" =~ ^${prefix}[^#] ]] && return
echo $line
elif [[ "$line" =~ ^${prefix}${key_}$ ]]
then
if [[ -n "${1:-}" ]]
then
prefix+="#"
key_=$1
shift
else
founded=1
fi
fi
done
}
# Read the value of a key in a ynh manifest file
#
# usage: ynh_read_manifest --manifest="manifest.json" --key="key"

View file

@ -113,11 +113,6 @@ SHELL=/bin/bash
EOF
fi
# legacy stuff to avoid yunohost reporting etckeeper as manually modified
# (this make sure that the hash is null / file is flagged as to-delete)
mkdir -p $pending_dir/etc/etckeeper
touch $pending_dir/etc/etckeeper/etckeeper.conf
# Skip ntp if inside a container (inspired from the conf of systemd-timesyncd)
mkdir -p ${pending_dir}/etc/systemd/system/ntp.service.d/
echo "
@ -242,13 +237,6 @@ for service, conf in new_services.items():
if conffiles:
services[service]['conffiles'] = conffiles
# Remove legacy /var/log/daemon.log and /var/log/syslog from log entries
# because they are too general. Instead, now the journalctl log is
# returned by default which is more relevant.
if "log" in services[service]:
if services[service]["log"] in ["/var/log/syslog", "/var/log/daemon.log"]:
del services[service]["log"]
if updated:
with open('/etc/yunohost/services.yml-new', 'w') as f:
yaml.safe_dump(services, f, default_flow_style=False)

View file

@ -7,10 +7,6 @@ set -e
do_pre_regen() {
pending_dir=$1
# If the (legacy) 'from_script' flag is here,
# we won't touch anything in the ssh config.
[[ ! -f /etc/yunohost/from_script ]] || return 0
cd /usr/share/yunohost/templates/ssh
# do not listen to IPv6 if unavailable
@ -34,10 +30,6 @@ do_pre_regen() {
do_post_regen() {
regen_conf_files=$1
# If the (legacy) 'from_script' flag is here,
# we won't touch anything in the ssh config.
[[ ! -f /etc/yunohost/from_script ]] || return 0
# If no file changed, there's nothing to do
[[ -n "$regen_conf_files" ]] || return 0

View file

@ -110,11 +110,6 @@ do_pre_regen() {
schema_dir="${ldap_dir}/schema"
mkdir -p "$ldap_dir" "$schema_dir"
# remove legacy configuration file
[ ! -f /etc/ldap/slapd-yuno.conf ] || touch "${ldap_dir}/slapd-yuno.conf"
[ ! -f /etc/ldap/slapd.conf ] || touch "${ldap_dir}/slapd.conf"
[ ! -f /etc/ldap/schema/yunohost.schema ] || touch "${schema_dir}/yunohost.schema"
cd /usr/share/yunohost/templates/slapd
# copy configuration files

View file

@ -119,20 +119,6 @@ do_post_regen() {
mkdir -p "/etc/nginx/conf.d/${domain}.d"
done
# Get rid of legacy lets encrypt snippets
for domain in $YNH_DOMAINS; do
# If the legacy letsencrypt / acme-challenge domain-specific snippet is still there
if [ -e /etc/nginx/conf.d/${domain}.d/000-acmechallenge.conf ]
then
# And if we're effectively including the new domain-independant snippet now
if grep -q "include /etc/nginx/conf.d/acme-challenge.conf.inc;" /etc/nginx/conf.d/${domain}.conf
then
# Delete the old domain-specific snippet
rm /etc/nginx/conf.d/${domain}.d/000-acmechallenge.conf
fi
fi
done
# Reload nginx if conf looks good, otherwise display error and exit unhappy
nginx -t 2>/dev/null || { nginx -t; exit 1; }
pgrep nginx && systemctl reload nginx || { journalctl --no-pager --lines=10 -u nginx >&2; exit 1; }

View file

@ -30,29 +30,6 @@ do_post_regen() {
echo "" | mysql && echo "Can't connect to mysql using unix_socket auth ... something went wrong during initial configuration of mysql !?" >&2
fi
# Legacy code to get rid of /etc/yunohost/mysql ...
# Nowadays, we can simply run mysql while being run as root of unix_socket/auth_socket is enabled...
if [ -f /etc/yunohost/mysql ]; then
# This is a trick to check if we're able to use mysql without password
# Expect instances installed in stretch to already have unix_socket
#configured, but not old instances from the jessie/wheezy era
if ! echo "" | mysql 2>/dev/null
then
password="$(cat /etc/yunohost/mysql)"
# Enable plugin unix_socket for root on localhost
mysql -u root -p"$password" <<< "GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED WITH unix_socket WITH GRANT OPTION;"
fi
# If now we're able to login without password, drop the mysql password
if echo "" | mysql 2>/dev/null
then
rm /etc/yunohost/mysql
else
echo "Can't connect to mysql using unix_socket auth ... something went wrong while trying to get rid of mysql password !?" >&2
fi
fi
# mysql is supposed to be an alias to mariadb... but in some weird case is not
# c.f. https://forum.yunohost.org/t/mysql-ne-fonctionne-pas/11661
# Playing with enable/disable allows to recreate the proper symlinks.

View file

@ -137,40 +137,13 @@ def app_search(string):
return catalog_of_apps
# Old legacy function...
def app_fetchlist():
logger.warning(
"'yunohost app fetchlist' is deprecated. Please use 'yunohost tools update --apps' instead"
)
from yunohost.tools import tools_update
tools_update(target="apps")
def app_list(full=False, installed=False, filter=None):
def app_list(full=False):
"""
List installed apps
"""
# Old legacy argument ... app_list was a combination of app_list and
# app_catalog before 3.8 ...
if installed:
logger.warning(
"Argument --installed ain't needed anymore when using 'yunohost app list'. It directly returns the list of installed apps.."
)
# Filter is a deprecated option...
if filter:
logger.warning(
"Using -f $appname in 'yunohost app list' is deprecated. Just use 'yunohost app list | grep -q 'id: $appname' to check a specific app is installed"
)
out = []
for app_id in sorted(_installed_apps()):
if filter and not app_id.startswith(filter):
continue
try:
app_info_dict = app_info(app_id, full=full)
except Exception as e:
@ -1258,64 +1231,6 @@ def app_remove(operation_logger, app):
_assert_system_is_sane_for_app(manifest, "post")
def app_addaccess(apps, users=[]):
"""
Grant access right to users (everyone by default)
Keyword argument:
users
apps
"""
from yunohost.permission import user_permission_update
output = {}
for app in apps:
permission = user_permission_update(
app + ".main", add=users, remove="all_users"
)
output[app] = permission["corresponding_users"]
return {"allowed_users": output}
def app_removeaccess(apps, users=[]):
"""
Revoke access right to users (everyone by default)
Keyword argument:
users
apps
"""
from yunohost.permission import user_permission_update
output = {}
for app in apps:
permission = user_permission_update(app + ".main", remove=users)
output[app] = permission["corresponding_users"]
return {"allowed_users": output}
def app_clearaccess(apps):
"""
Reset access rights for the app
Keyword argument:
apps
"""
from yunohost.permission import user_permission_reset
output = {}
for app in apps:
permission = user_permission_reset(app + ".main")
output[app] = permission["corresponding_users"]
return {"allowed_users": output}
@is_unit_operation()
def app_makedefault(operation_logger, app, domain=None):
"""
@ -1643,10 +1558,6 @@ def app_ssowatconf():
write_to_json("/etc/ssowat/conf.json", conf_dict, sort_keys=True, indent=4)
from .utils.legacy import translate_legacy_rules_in_ssowant_conf_json_persistent
translate_legacy_rules_in_ssowant_conf_json_persistent()
logger.debug(m18n.n("ssowat_conf_generated"))
@ -3542,36 +3453,10 @@ def _patch_legacy_helpers(app_folder):
files_to_patch.extend(glob.glob("%s/scripts/.*" % app_folder))
stuff_to_replace = {
# Replace
# sudo yunohost app initdb $db_user -p $db_pwd
# by
# ynh_mysql_setup_db --db_user=$db_user --db_name=$db_user --db_pwd=$db_pwd
"yunohost app initdb": {
"pattern": r"(sudo )?yunohost app initdb \"?(\$\{?\w+\}?)\"?\s+-p\s\"?(\$\{?\w+\}?)\"?",
"replace": r"ynh_mysql_setup_db --db_user=\2 --db_name=\2 --db_pwd=\3",
"important": True,
},
# Replace
# sudo yunohost app checkport whaterver
# by
# ynh_port_available whatever
"yunohost app checkport": {
"pattern": r"(sudo )?yunohost app checkport",
"replace": r"ynh_port_available",
"important": True,
},
# We can't migrate easily port-available
# .. but at the time of writing this code, only two non-working apps are using it.
"yunohost app initdb": {"important": True},
"yunohost app checkport": {"important": True},
"yunohost tools port-available": {"important": True},
# Replace
# yunohost app checkurl "${domain}${path_url}" -a "${app}"
# by
# ynh_webpath_register --app=${app} --domain=${domain} --path_url=${path_url}
"yunohost app checkurl": {
"pattern": r"(sudo )?yunohost app checkurl \"?(\$\{?\w+\}?)\/?(\$\{?\w+\}?)\"?\s+-a\s\"?(\$\{?\w+\}?)\"?",
"replace": r"ynh_webpath_register --app=\4 --domain=\2 --path_url=\3",
"important": True,
},
"yunohost app checkurl": {"important": True},
# Remove
# Automatic diagnosis data from YunoHost
# __PRE_TAG1__$(yunohost tools diagnosis | ...)__PRE_TAG2__"
@ -3582,26 +3467,11 @@ def _patch_legacy_helpers(app_folder):
"important": False,
},
# Old $1, $2 in backup/restore scripts...
"app=$2": {
"only_for": ["scripts/backup", "scripts/restore"],
"pattern": r"app=\$2",
"replace": r"app=$YNH_APP_INSTANCE_NAME",
"important": True,
},
"app=$2": {"only_for": ["scripts/backup", "scripts/restore"], "important": True},
# Old $1, $2 in backup/restore scripts...
"backup_dir=$1": {
"only_for": ["scripts/backup", "scripts/restore"],
"pattern": r"backup_dir=\$1",
"replace": r"backup_dir=.",
"important": True,
},
"backup_dir=$1": {"only_for": ["scripts/backup", "scripts/restore"], "important": True},
# Old $1, $2 in backup/restore scripts...
"restore_dir=$1": {
"only_for": ["scripts/restore"],
"pattern": r"restore_dir=\$1",
"replace": r"restore_dir=.",
"important": True,
},
"restore_dir=$1": {"only_for": ["scripts/restore"], "important": True},
# Old $1, $2 in install scripts...
# We ain't patching that shit because it ain't trivial to patch all args...
"domain=$1": {"only_for": ["scripts/install"], "important": True},

View file

@ -1,291 +0,0 @@
import glob
import os
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
from yunohost.tools import Migration, tools_update, tools_upgrade
from yunohost.app import unstable_apps
from yunohost.regenconf import manually_modified_files
from yunohost.utils.filesystem import free_space_in_directory
from yunohost.utils.packages import (
get_ynh_package_version,
_list_upgradable_apt_packages,
)
logger = getActionLogger("yunohost.migration")
class MyMigration(Migration):
"Upgrade the system to Debian Buster and Yunohost 4.x"
mode = "manual"
def run(self):
self.check_assertions()
logger.info(m18n.n("migration_0015_start"))
#
# Make sure certificates do not use weak signature hash algorithms (md5, sha1)
# otherwise nginx will later refuse to start which result in
# catastrophic situation
#
self.validate_and_upgrade_cert_if_necessary()
#
# Patch sources.list
#
logger.info(m18n.n("migration_0015_patching_sources_list"))
self.patch_apt_sources_list()
tools_update(target="system")
# Tell libc6 it's okay to restart system stuff during the upgrade
os.system(
"echo 'libc6 libraries/restart-without-asking boolean true' | debconf-set-selections"
)
# Don't send an email to root about the postgresql migration. It should be handled automatically after.
os.system(
"echo 'postgresql-common postgresql-common/obsolete-major seen true' | debconf-set-selections"
)
#
# Specific packages upgrades
#
logger.info(m18n.n("migration_0015_specific_upgrade"))
# Update unscd independently, was 0.53-1+yunohost on stretch (custom build of ours) but now it's 0.53-1+b1 on vanilla buster,
# which for apt appears as a lower version (hence the --allow-downgrades and the hardcoded version number)
unscd_version = check_output(
'dpkg -s unscd | grep "^Version: " | cut -d " " -f 2'
)
if "yunohost" in unscd_version:
new_version = check_output(
"LC_ALL=C apt policy unscd 2>/dev/null | grep -v '\\*\\*\\*' | grep http -B1 | head -n 1 | awk '{print $1}'"
).strip()
if new_version:
self.apt_install("unscd=%s --allow-downgrades" % new_version)
else:
logger.warning("Could not identify which version of unscd to install")
# Upgrade libpam-modules independently, small issue related to willing to overwrite a file previously provided by Yunohost
libpammodules_version = check_output(
'dpkg -s libpam-modules | grep "^Version: " | cut -d " " -f 2'
)
if not libpammodules_version.startswith("1.3"):
self.apt_install('libpam-modules -o Dpkg::Options::="--force-overwrite"')
#
# Main upgrade
#
logger.info(m18n.n("migration_0015_main_upgrade"))
apps_packages = self.get_apps_equivs_packages()
self.hold(apps_packages)
tools_upgrade(target="system", allow_yunohost_upgrade=False)
if self.debian_major_version() == 9:
raise YunohostError("migration_0015_still_on_stretch_after_main_upgrade")
# Clean the mess
logger.info(m18n.n("migration_0015_cleaning_up"))
os.system("apt autoremove --assume-yes")
os.system("apt clean --assume-yes")
#
# Yunohost upgrade
#
logger.info(m18n.n("migration_0015_yunohost_upgrade"))
self.unhold(apps_packages)
tools_upgrade(target="system")
def debian_major_version(self):
# The python module "platform" and lsb_release are not reliable because
# on some setup, they may still return Release=9 even after upgrading to
# buster ... (Apparently this is related to OVH overriding some stuff
# with /etc/lsb-release for instance -_-)
# Instead, we rely on /etc/os-release which should be the raw info from
# the distribution...
return int(
check_output(
"grep VERSION_ID /etc/os-release | head -n 1 | tr '\"' ' ' | cut -d ' ' -f2"
)
)
def yunohost_major_version(self):
return int(get_ynh_package_version("yunohost")["version"].split(".")[0])
def check_assertions(self):
# Be on stretch (9.x) and yunohost 3.x
# NB : we do both check to cover situations where the upgrade crashed
# in the middle and debian version could be > 9.x but yunohost package
# would still be in 3.x...
if (
not self.debian_major_version() == 9
and not self.yunohost_major_version() == 3
):
raise YunohostError("migration_0015_not_stretch")
# Have > 1 Go free space on /var/ ?
if free_space_in_directory("/var/") / (1024 ** 3) < 1.0:
raise YunohostError("migration_0015_not_enough_free_space")
# Check system is up to date
# (but we don't if 'stretch' is already in the sources.list ...
# which means maybe a previous upgrade crashed and we're re-running it)
if " buster " not in read_file("/etc/apt/sources.list"):
tools_update(target="system")
upgradable_system_packages = list(_list_upgradable_apt_packages())
if upgradable_system_packages:
raise YunohostError("migration_0015_system_not_fully_up_to_date")
@property
def disclaimer(self):
# Avoid having a super long disclaimer + uncessary check if we ain't
# on stretch / yunohost 3.x anymore
# NB : we do both check to cover situations where the upgrade crashed
# in the middle and debian version could be >= 10.x but yunohost package
# would still be in 3.x...
if (
not self.debian_major_version() == 9
and not self.yunohost_major_version() == 3
):
return None
# Get list of problematic apps ? I.e. not official or community+working
problematic_apps = unstable_apps()
problematic_apps = "".join(["\n - " + app for app in problematic_apps])
# Manually modified files ? (c.f. yunohost service regen-conf)
modified_files = manually_modified_files()
modified_files = "".join(["\n - " + f for f in modified_files])
message = m18n.n("migration_0015_general_warning")
message = (
"N.B.: This migration has been tested by the community over the last few months but has only been declared stable recently. If your server hosts critical services and if you are not too confident with debugging possible issues, we recommend you to wait a little bit more while we gather more feedback and polish things up. If on the other hand you are relatively confident with debugging small issues that may arise, you are encouraged to run this migration ;)! You can read about remaining known issues and feedback from the community here: https://forum.yunohost.org/t/12195\n\n"
+ message
)
if problematic_apps:
message += "\n\n" + m18n.n(
"migration_0015_problematic_apps_warning",
problematic_apps=problematic_apps,
)
if modified_files:
message += "\n\n" + m18n.n(
"migration_0015_modified_files", manually_modified_files=modified_files
)
return message
def patch_apt_sources_list(self):
sources_list = glob.glob("/etc/apt/sources.list.d/*.list")
sources_list.append("/etc/apt/sources.list")
# This :
# - replace single 'stretch' occurence by 'buster'
# - comments lines containing "backports"
# - replace 'stretch/updates' by 'strech/updates' (or same with -)
for f in sources_list:
command = (
"sed -i -e 's@ stretch @ buster @g' "
"-e '/backports/ s@^#*@#@' "
"-e 's@ stretch/updates @ buster/updates @g' "
"-e 's@ stretch-@ buster-@g' "
"{}".format(f)
)
os.system(command)
def get_apps_equivs_packages(self):
command = (
"dpkg --get-selections"
" | grep -v deinstall"
" | awk '{print $1}'"
" | { grep 'ynh-deps$' || true; }"
)
output = check_output(command)
return output.split("\n") if output else []
def hold(self, packages):
for package in packages:
os.system("apt-mark hold {}".format(package))
def unhold(self, packages):
for package in packages:
os.system("apt-mark unhold {}".format(package))
def apt_install(self, cmd):
def is_relevant(line):
return "Reading database ..." not in line.rstrip()
callbacks = (
lambda l: logger.info("+ " + l.rstrip() + "\r")
if is_relevant(l)
else logger.debug(l.rstrip() + "\r"),
lambda l: logger.warning(l.rstrip()),
)
cmd = (
"LC_ALL=C DEBIAN_FRONTEND=noninteractive APT_LISTCHANGES_FRONTEND=none apt install --quiet -o=Dpkg::Use-Pty=0 --fix-broken --assume-yes "
+ cmd
)
logger.debug("Running: %s" % cmd)
call_async_output(cmd, callbacks, shell=True)
def validate_and_upgrade_cert_if_necessary(self):
active_certs = set(
check_output("grep -roh '/.*crt.pem' /etc/nginx/").split("\n")
)
cmd = "LC_ALL=C openssl x509 -in %s -text -noout | grep -i 'Signature Algorithm:' | awk '{print $3}' | uniq"
default_crt = "/etc/yunohost/certs/yunohost.org/crt.pem"
default_key = "/etc/yunohost/certs/yunohost.org/key.pem"
default_signature = (
check_output(cmd % default_crt) if default_crt in active_certs else None
)
if default_signature is not None and (
default_signature.startswith("md5") or default_signature.startswith("sha1")
):
logger.warning(
"%s is using a pretty old certificate incompatible with newer versions of nginx ... attempting to regenerate a fresh one"
% default_crt
)
os.system("mv %s %s.old" % (default_crt, default_crt))
os.system("mv %s %s.old" % (default_key, default_key))
ret = os.system("/usr/share/yunohost/hooks/conf_regen/02-ssl init")
if ret != 0 or not os.path.exists(default_crt):
logger.error("Upgrading the certificate failed ... reverting")
os.system("mv %s.old %s" % (default_crt, default_crt))
os.system("mv %s.old %s" % (default_key, default_key))
signatures = {cert: check_output(cmd % cert) for cert in active_certs}
def cert_is_weak(cert):
sig = signatures[cert]
return sig.startswith("md5") or sig.startswith("sha1")
weak_certs = [cert for cert in signatures.keys() if cert_is_weak(cert)]
if weak_certs:
raise YunohostError(
"migration_0015_weak_certs", certs=", ".join(weak_certs)
)

View file

@ -1,83 +0,0 @@
import os
import glob
from shutil import copy2
from moulinette.utils.log import getActionLogger
from yunohost.app import _is_installed, _patch_legacy_php_versions_in_settings
from yunohost.tools import Migration
from yunohost.service import _run_service_command
logger = getActionLogger("yunohost.migration")
PHP70_POOLS = "/etc/php/7.0/fpm/pool.d"
PHP73_POOLS = "/etc/php/7.3/fpm/pool.d"
PHP70_SOCKETS_PREFIX = "/run/php/php7.0-fpm"
PHP73_SOCKETS_PREFIX = "/run/php/php7.3-fpm"
MIGRATION_COMMENT = (
"; YunoHost note : this file was automatically moved from {}".format(PHP70_POOLS)
)
class MyMigration(Migration):
"Migrate php7.0-fpm 'pool' conf files to php7.3"
dependencies = ["migrate_to_buster"]
def run(self):
# Get list of php7.0 pool files
php70_pool_files = glob.glob("{}/*.conf".format(PHP70_POOLS))
# Keep only basenames
php70_pool_files = [os.path.basename(f) for f in php70_pool_files]
# Ignore the "www.conf" (default stuff, probably don't want to touch it ?)
php70_pool_files = [f for f in php70_pool_files if f != "www.conf"]
for f in php70_pool_files:
# Copy the files to the php7.3 pool
src = "{}/{}".format(PHP70_POOLS, f)
dest = "{}/{}".format(PHP73_POOLS, f)
copy2(src, dest)
# Replace the socket prefix if it's found
c = "sed -i -e 's@{}@{}@g' {}".format(
PHP70_SOCKETS_PREFIX, PHP73_SOCKETS_PREFIX, dest
)
os.system(c)
# Also add a comment that it was automatically moved from php7.0
# (for human traceability and backward migration)
c = "sed -i '1i {}' {}".format(MIGRATION_COMMENT, dest)
os.system(c)
app_id = os.path.basename(f)[: -len(".conf")]
if _is_installed(app_id):
_patch_legacy_php_versions_in_settings(
"/etc/yunohost/apps/%s/" % app_id
)
nginx_conf_files = glob.glob("/etc/nginx/conf.d/*.d/%s.conf" % app_id)
for f in nginx_conf_files:
# Replace the socket prefix if it's found
c = "sed -i -e 's@{}@{}@g' {}".format(
PHP70_SOCKETS_PREFIX, PHP73_SOCKETS_PREFIX, f
)
os.system(c)
os.system(
"rm /etc/logrotate.d/php7.0-fpm"
) # We remove this otherwise the logrotate cron will be unhappy
# Reload/restart the php pools
_run_service_command("restart", "php7.3-fpm")
_run_service_command("enable", "php7.3-fpm")
os.system("systemctl stop php7.0-fpm")
os.system("systemctl disable php7.0-fpm")
# Reload nginx
_run_service_command("reload", "nginx")

View file

@ -1,82 +0,0 @@
import subprocess
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.filesystem import free_space_in_directory, space_used_by_directory
logger = getActionLogger("yunohost.migration")
class MyMigration(Migration):
"Migrate DBs from Postgresql 9.6 to 11 after migrating to Buster"
dependencies = ["migrate_to_buster"]
def run(self):
if not self.package_is_installed("postgresql-9.6"):
logger.warning(m18n.n("migration_0017_postgresql_96_not_installed"))
return
if not self.package_is_installed("postgresql-11"):
raise YunohostValidationError("migration_0017_postgresql_11_not_installed")
# Make sure there's a 9.6 cluster
try:
self.runcmd("pg_lsclusters | grep -q '^9.6 '")
except Exception:
logger.warning(
"It looks like there's not active 9.6 cluster, so probably don't need to run this migration"
)
return
if not space_used_by_directory(
"/var/lib/postgresql/9.6"
) > free_space_in_directory("/var/lib/postgresql"):
raise YunohostValidationError(
"migration_0017_not_enough_space", path="/var/lib/postgresql/"
)
self.runcmd("systemctl stop postgresql")
self.runcmd(
"LC_ALL=C pg_dropcluster --stop 11 main || true"
) # We do not trigger an exception if the command fails because that probably means cluster 11 doesn't exists, which is fine because it's created during the pg_upgradecluster)
self.runcmd("LC_ALL=C pg_upgradecluster -m upgrade 9.6 main")
self.runcmd("LC_ALL=C pg_dropcluster --stop 9.6 main")
self.runcmd("systemctl start postgresql")
def package_is_installed(self, package_name):
(returncode, out, err) = self.runcmd(
"dpkg --list | grep '^ii ' | grep -q -w {}".format(package_name),
raise_on_errors=False,
)
return returncode == 0
def runcmd(self, cmd, raise_on_errors=True):
logger.debug("Running command: " + cmd)
p = subprocess.Popen(
cmd,
shell=True,
executable="/bin/bash",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
out, err = p.communicate()
returncode = p.returncode
if raise_on_errors and returncode != 0:
raise YunohostError(
"Failed to run command '{}'.\nreturncode: {}\nstdout:\n{}\nstderr:\n{}\n".format(
cmd, returncode, out, err
)
)
out = out.strip().split("\n")
return (returncode, out, err)

View file

@ -1,126 +0,0 @@
import os
import subprocess
from moulinette import m18n
from yunohost.utils.error import YunohostError
from moulinette.utils.log import getActionLogger
from yunohost.firewall import firewall_reload
from yunohost.service import service_restart
from yunohost.tools import Migration
logger = getActionLogger("yunohost.migration")
class MyMigration(Migration):
"Migrate legacy iptables rules from stretch that relied on xtable and should now rely on nftable"
dependencies = ["migrate_to_buster"]
def run(self):
self.do_ipv4 = os.system("iptables -w -L >/dev/null") == 0
self.do_ipv6 = os.system("ip6tables -w -L >/dev/null") == 0
if not self.do_ipv4:
logger.warning(m18n.n("iptables_unavailable"))
if not self.do_ipv6:
logger.warning(m18n.n("ip6tables_unavailable"))
backup_folder = "/home/yunohost.backup/premigration/xtable_to_nftable/"
if not os.path.exists(backup_folder):
os.makedirs(backup_folder, 0o750)
self.backup_rules_ipv4 = os.path.join(backup_folder, "legacy_rules_ipv4")
self.backup_rules_ipv6 = os.path.join(backup_folder, "legacy_rules_ipv6")
# Backup existing legacy rules to be able to rollback
if self.do_ipv4 and not os.path.exists(self.backup_rules_ipv4):
self.runcmd(
"iptables-legacy -L >/dev/null"
) # For some reason if we don't do this, iptables-legacy-save is empty ?
self.runcmd("iptables-legacy-save > %s" % self.backup_rules_ipv4)
assert (
open(self.backup_rules_ipv4).read().strip()
), "Uhoh backup of legacy ipv4 rules is empty !?"
if self.do_ipv6 and not os.path.exists(self.backup_rules_ipv6):
self.runcmd(
"ip6tables-legacy -L >/dev/null"
) # For some reason if we don't do this, iptables-legacy-save is empty ?
self.runcmd("ip6tables-legacy-save > %s" % self.backup_rules_ipv6)
assert (
open(self.backup_rules_ipv6).read().strip()
), "Uhoh backup of legacy ipv6 rules is empty !?"
# We inject the legacy rules (iptables-legacy) into the new iptable (just "iptables")
try:
if self.do_ipv4:
self.runcmd("iptables-legacy-save | iptables-restore")
if self.do_ipv6:
self.runcmd("ip6tables-legacy-save | ip6tables-restore")
except Exception as e:
self.rollback()
raise YunohostError(
"migration_0018_failed_to_migrate_iptables_rules", error=e
)
# Reset everything in iptables-legacy
# Stolen from https://serverfault.com/a/200642
try:
if self.do_ipv4:
self.runcmd(
"iptables-legacy-save | awk '/^[*]/ { print $1 }" # Keep lines like *raw, *filter and *nat
' /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; }' # Turn all policies to accept
" /COMMIT/ { print $0; }'" # Keep the line COMMIT
" | iptables-legacy-restore"
)
if self.do_ipv6:
self.runcmd(
"ip6tables-legacy-save | awk '/^[*]/ { print $1 }" # Keep lines like *raw, *filter and *nat
' /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; }' # Turn all policies to accept
" /COMMIT/ { print $0; }'" # Keep the line COMMIT
" | ip6tables-legacy-restore"
)
except Exception as e:
self.rollback()
raise YunohostError("migration_0018_failed_to_reset_legacy_rules", error=e)
# You might be wondering "uh but is it really useful to
# iptables-legacy-save | iptables-restore considering firewall_reload()
# flush/resets everything anyway ?"
# But the answer is : firewall_reload() only resets the *filter table.
# On more complex setups (e.g. internet cube or docker) you will also
# have rules in the *nat (or maybe *raw?) sections of iptables.
firewall_reload()
service_restart("fail2ban")
def rollback(self):
if self.do_ipv4:
self.runcmd("iptables-legacy-restore < %s" % self.backup_rules_ipv4)
if self.do_ipv6:
self.runcmd("iptables-legacy-restore < %s" % self.backup_rules_ipv6)
def runcmd(self, cmd, raise_on_errors=True):
logger.debug("Running command: " + cmd)
p = subprocess.Popen(
cmd,
shell=True,
executable="/bin/bash",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
out, err = p.communicate()
returncode = p.returncode
if raise_on_errors and returncode != 0:
raise YunohostError(
"Failed to run command '{}'.\nreturncode: {}\nstdout:\n{}\nstderr:\n{}\n".format(
cmd, returncode, out, err
)
)
out = out.strip().split(b"\n")
return (returncode, out, err)

View file

@ -1,107 +0,0 @@
from moulinette import m18n
from moulinette.utils.log import getActionLogger
from yunohost.tools import Migration
from yunohost.permission import user_permission_list
from yunohost.utils.legacy import migrate_legacy_permission_settings
logger = getActionLogger("yunohost.migration")
class MyMigration(Migration):
"""
Add protected attribute in LDAP permission
"""
@Migration.ldap_migration
def run(self, backup_folder):
# Update LDAP database
self.add_new_ldap_attributes()
# Migrate old settings
migrate_legacy_permission_settings()
def add_new_ldap_attributes(self):
from yunohost.utils.ldap import _get_ldap_interface
from yunohost.regenconf import regen_conf, BACKUP_CONF_DIR
# Check if the migration can be processed
ldap_regen_conf_status = regen_conf(names=["slapd"], dry_run=True)
# By this we check if the have been customized
if ldap_regen_conf_status and ldap_regen_conf_status["slapd"]["pending"]:
logger.warning(
m18n.n(
"migration_0019_slapd_config_will_be_overwritten",
conf_backup_folder=BACKUP_CONF_DIR,
)
)
# Update LDAP schema restart slapd
logger.info(m18n.n("migration_update_LDAP_schema"))
regen_conf(names=["slapd"], force=True)
logger.info(m18n.n("migration_0019_add_new_attributes_in_ldap"))
ldap = _get_ldap_interface()
permission_list = user_permission_list(full=True)["permissions"]
for permission in permission_list:
system_perms = {
"mail": "E-mail",
"xmpp": "XMPP",
"ssh": "SSH",
"sftp": "STFP",
}
if permission.split(".")[0] in system_perms:
update = {
"authHeader": ["FALSE"],
"label": [system_perms[permission.split(".")[0]]],
"showTile": ["FALSE"],
"isProtected": ["TRUE"],
}
else:
app, subperm_name = permission.split(".")
if permission.endswith(".main"):
update = {
"authHeader": ["TRUE"],
"label": [
app
], # Note that this is later re-changed during the call to migrate_legacy_permission_settings() if a 'label' setting exists
"showTile": ["TRUE"],
"isProtected": ["FALSE"],
}
else:
update = {
"authHeader": ["TRUE"],
"label": [subperm_name.title()],
"showTile": ["FALSE"],
"isProtected": ["TRUE"],
}
ldap.update("cn=%s,ou=permission" % permission, update)
introduced_in_version = "4.1"
def run_after_system_restore(self):
# Update LDAP database
self.add_new_ldap_attributes()
def run_before_app_restore(self, app_id):
from yunohost.app import app_setting
from yunohost.utils.legacy import migrate_legacy_permission_settings
# Migrate old settings
legacy_permission_settings = [
"skipped_uris",
"unprotected_uris",
"protected_uris",
"skipped_regex",
"unprotected_regex",
"protected_regex",
]
if any(
app_setting(app_id, setting) is not None
for setting in legacy_permission_settings
):
migrate_legacy_permission_settings(app=app_id)

View file

@ -1,100 +0,0 @@
import subprocess
import os
from moulinette import m18n
from moulinette.utils.log import getActionLogger
from yunohost.tools import Migration
from yunohost.permission import user_permission_update, permission_sync_to_user
from yunohost.regenconf import manually_modified_files
logger = getActionLogger("yunohost.migration")
###################################################
# Tools used also for restoration
###################################################
class MyMigration(Migration):
"""
Add new permissions around SSH/SFTP features
"""
introduced_in_version = "4.2.2"
dependencies = ["extend_permissions_features"]
@Migration.ldap_migration
def run(self, *args):
from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface()
existing_perms_raw = ldap.search(
"ou=permission,dc=yunohost,dc=org", "(objectclass=permissionYnh)", ["cn"]
)
existing_perms = [perm["cn"][0] for perm in existing_perms_raw]
# Add SSH and SFTP permissions
if "sftp.main" not in existing_perms:
ldap.add(
"cn=sftp.main,ou=permission",
{
"cn": "sftp.main",
"gidNumber": "5004",
"objectClass": ["posixGroup", "permissionYnh"],
"groupPermission": [],
"authHeader": "FALSE",
"label": "SFTP",
"showTile": "FALSE",
"isProtected": "TRUE",
},
)
if "ssh.main" not in existing_perms:
ldap.add(
"cn=ssh.main,ou=permission",
{
"cn": "ssh.main",
"gidNumber": "5003",
"objectClass": ["posixGroup", "permissionYnh"],
"groupPermission": [],
"authHeader": "FALSE",
"label": "SSH",
"showTile": "FALSE",
"isProtected": "TRUE",
},
)
# Add a bash terminal to each users
users = ldap.search(
"ou=users,dc=yunohost,dc=org",
filter="(loginShell=*)",
attrs=["dn", "uid", "loginShell"],
)
for user in users:
if user["loginShell"][0] == "/bin/false":
dn = user["dn"][0].replace(",dc=yunohost,dc=org", "")
ldap.update(dn, {"loginShell": ["/bin/bash"]})
else:
user_permission_update(
"ssh.main", add=user["uid"][0], sync_perm=False
)
permission_sync_to_user()
# Somehow this is needed otherwise the PAM thing doesn't forget about the
# old loginShell value ?
subprocess.call(["nscd", "-i", "passwd"])
if (
"/etc/ssh/sshd_config" in manually_modified_files()
and os.system(
"grep -q '^ *AllowGroups\\|^ *AllowUsers' /etc/ssh/sshd_config"
)
!= 0
):
logger.error(m18n.n("diagnosis_sshd_config_insecure"))
def run_after_system_restore(self):
self.run()

View file

@ -375,18 +375,6 @@ def dyndns_update(
)
def dyndns_installcron():
logger.warning(
"This command is deprecated. The dyndns cron job should automatically be added/removed by the regenconf depending if there's a private key in /etc/yunohost/dyndns. You can run the regenconf yourself with 'yunohost tools regen-conf yunohost'."
)
def dyndns_removecron():
logger.warning(
"This command is deprecated. The dyndns cron job should automatically be added/removed by the regenconf depending if there's a private key in /etc/yunohost/dyndns. You can run the regenconf yourself with 'yunohost tools regen-conf yunohost'."
)
def _guess_current_dyndns_domain(dyn_host):
"""
This function tries to guess which domain should be updated by

View file

@ -48,12 +48,10 @@ def service_add(
name,
description=None,
log=None,
log_type=None,
test_status=None,
test_conf=None,
needs_exposed_ports=None,
need_lock=False,
status=None,
):
"""
Add a custom service
@ -62,12 +60,10 @@ def service_add(
name -- Service name to add
description -- description of the service
log -- Absolute path to log file to display
log_type -- (deprecated) Specify if the corresponding log is a file or a systemd log
test_status -- Specify a custom bash command to check the status of the service. N.B. : it only makes sense to specify this if the corresponding systemd service does not return the proper information.
test_conf -- Specify a custom bash command to check if the configuration of the service is valid or broken, similar to nginx -t.
needs_exposed_ports -- A list of ports that needs to be publicly exposed for the service to work as intended.
need_lock -- Use this option to prevent deadlocks if the service does invoke yunohost commands.
status -- Deprecated, doesn't do anything anymore. Use test_status instead.
"""
services = _get_services()
@ -77,15 +73,6 @@ def service_add(
if not isinstance(log, list):
log = [log]
# Deprecated log_type stuff
if log_type is not None:
logger.warning(
"/!\\ Packagers! --log_type is deprecated. You do not need to specify --log_type systemd anymore ... Yunohost now automatically fetch the journalctl of the systemd service by default."
)
# Usually when adding such a service, the service name will be provided so we remove it as it's not a log file path
if name in log:
log.remove(name)
service["log"] = log
if not description:
@ -535,29 +522,6 @@ def service_log(name, number=50):
return result
def service_regen_conf(
names=[], with_diff=False, force=False, dry_run=False, list_pending=False
):
services = _get_services()
if isinstance(names, str):
names = [names]
for name in names:
if name not in services.keys():
raise YunohostValidationError("service_unknown", service=name)
if names is []:
names = list(services.keys())
logger.warning(m18n.n("service_regen_conf_is_deprecated"))
from yunohost.regenconf import regen_conf
return regen_conf(names, with_diff, force, dry_run, list_pending)
def _run_service_command(action, service):
"""
Run services management command (start, stop, enable, disable, restart, reload)

View file

@ -329,24 +329,12 @@ def tools_regen_conf(
return regen_conf(names, with_diff, force, dry_run, list_pending)
def tools_update(target=None, apps=False, system=False):
def tools_update(target=None):
"""
Update apps & system package cache
"""
# Legacy options (--system, --apps)
if apps or system:
logger.warning(
"Using 'yunohost tools update' with --apps / --system is deprecated, just write 'yunohost tools update apps system' (no -- prefix anymore)"
)
if apps and system:
target = "all"
elif apps:
target = "apps"
else:
target = "system"
elif not target:
if not target:
target = "all"
if target not in ["system", "apps", "all"]:
@ -455,7 +443,7 @@ def _list_upgradable_apps():
@is_unit_operation()
def tools_upgrade(
operation_logger, target=None, apps=False, system=False, allow_yunohost_upgrade=True
operation_logger, target=None, allow_yunohost_upgrade=True
):
"""
Update apps & package cache, then display changelog
@ -473,21 +461,6 @@ def tools_upgrade(
if not packages.dpkg_lock_available():
raise YunohostValidationError("dpkg_lock_not_available")
# Legacy options management (--system, --apps)
if target is None:
logger.warning(
"Using 'yunohost tools upgrade' with --apps / --system is deprecated, just write 'yunohost tools upgrade apps' or 'system' (no -- prefix anymore)"
)
if (system, apps) == (True, True):
raise YunohostValidationError("tools_upgrade_cant_both")
if (system, apps) == (False, False):
raise YunohostValidationError("tools_upgrade_at_least_one")
target = "apps" if apps else "system"
if target not in ["apps", "system"]:
raise Exception(
"Uhoh ?! tools_upgrade should have 'apps' or 'system' value for argument target"

View file

@ -98,7 +98,6 @@ def user_create(
domain,
password,
mailbox_quota="0",
mail=None,
):
from yunohost.domain import domain_list, _get_maindomain
@ -109,12 +108,6 @@ def user_create(
# Ensure sufficiently complex password
assert_password_is_strong_enough("user", password)
if mail is not None:
logger.warning(
"Packagers ! Using --mail in 'yunohost user create' is deprecated ... please use --domain instead."
)
domain = mail.split("@")[-1]
# Validate domain used for email address/xmpp account
if domain is None:
if msettings.get("interface") == "api":

View file

@ -1,239 +0,0 @@
import os
from moulinette import m18n
from moulinette.utils.log import getActionLogger
from moulinette.utils.filesystem import write_to_json, read_yaml
from yunohost.user import user_list
from yunohost.app import (
_installed_apps,
_get_app_settings,
_set_app_settings,
)
from yunohost.permission import (
permission_create,
user_permission_update,
permission_sync_to_user,
)
logger = getActionLogger("yunohost.legacy")
LEGACY_PERMISSION_LABEL = {
("nextcloud", "skipped"): "api", # .well-known
("libreto", "skipped"): "pad access", # /[^/]+
("leed", "skipped"): "api", # /action.php, for cron task ...
("mailman", "protected"): "admin", # /admin
("prettynoemiecms", "protected"): "admin", # /admin
("etherpad_mypads", "skipped"): "admin", # /admin
("baikal", "protected"): "admin", # /admin/
("couchpotato", "unprotected"): "api", # /api
("freshrss", "skipped"): "api", # /api/,
("portainer", "skipped"): "api", # /api/webhooks/
("jeedom", "unprotected"): "api", # /core/api/jeeApi.php
("bozon", "protected"): "user interface", # /index.php
(
"limesurvey",
"protected",
): "admin", # /index.php?r=admin,/index.php?r=plugins,/scripts
("kanboard", "unprotected"): "api", # /jsonrpc.php
("seafile", "unprotected"): "medias", # /media
("ttrss", "skipped"): "api", # /public.php,/api,/opml.php?op=publish
("libreerp", "protected"): "admin", # /web/database/manager
("z-push", "skipped"): "api", # $domain/[Aa]uto[Dd]iscover/.*
("radicale", "skipped"): "?", # $domain$path_url
(
"jirafeau",
"protected",
): "user interface", # $domain$path_url/$","$domain$path_url/admin.php.*$
("opensondage", "protected"): "admin", # $domain$path_url/admin/
(
"lstu",
"protected",
): "user interface", # $domain$path_url/login$","$domain$path_url/logout$","$domain$path_url/api$","$domain$path_url/extensions$","$domain$path_url/stats$","$domain$path_url/d/.*$","$domain$path_url/a$","$domain$path_url/$
(
"lutim",
"protected",
): "user interface", # $domain$path_url/stats/?$","$domain$path_url/manifest.webapp/?$","$domain$path_url/?$","$domain$path_url/[d-m]/.*$
(
"lufi",
"protected",
): "user interface", # $domain$path_url/stats$","$domain$path_url/manifest.webapp$","$domain$path_url/$","$domain$path_url/d/.*$","$domain$path_url/m/.*$
(
"gogs",
"skipped",
): "api", # $excaped_domain$excaped_path/[%w-.]*/[%w-.]*/git%-receive%-pack,$excaped_domain$excaped_path/[%w-.]*/[%w-.]*/git%-upload%-pack,$excaped_domain$excaped_path/[%w-.]*/[%w-.]*/info/refs
}
def legacy_permission_label(app, permission_type):
return LEGACY_PERMISSION_LABEL.get(
(app, permission_type), "Legacy %s urls" % permission_type
)
def migrate_legacy_permission_settings(app=None):
logger.info(m18n.n("migrating_legacy_permission_settings"))
apps = _installed_apps()
if app:
if app not in apps:
logger.error(
"Can't migrate permission for app %s because it ain't installed..."
% app
)
apps = []
else:
apps = [app]
for app in apps:
settings = _get_app_settings(app) or {}
if settings.get("label"):
user_permission_update(
app + ".main", label=settings["label"], sync_perm=False
)
del settings["label"]
def _setting(name):
s = settings.get(name)
return s.split(",") if s else []
skipped_urls = [uri for uri in _setting("skipped_uris") if uri != "/"]
skipped_urls += ["re:" + regex for regex in _setting("skipped_regex")]
unprotected_urls = [uri for uri in _setting("unprotected_uris") if uri != "/"]
unprotected_urls += ["re:" + regex for regex in _setting("unprotected_regex")]
protected_urls = [uri for uri in _setting("protected_uris") if uri != "/"]
protected_urls += ["re:" + regex for regex in _setting("protected_regex")]
if skipped_urls != []:
permission_create(
app + ".legacy_skipped_uris",
additional_urls=skipped_urls,
auth_header=False,
label=legacy_permission_label(app, "skipped"),
show_tile=False,
allowed="visitors",
protected=True,
sync_perm=False,
)
if unprotected_urls != []:
permission_create(
app + ".legacy_unprotected_uris",
additional_urls=unprotected_urls,
auth_header=True,
label=legacy_permission_label(app, "unprotected"),
show_tile=False,
allowed="visitors",
protected=True,
sync_perm=False,
)
if protected_urls != []:
permission_create(
app + ".legacy_protected_uris",
additional_urls=protected_urls,
auth_header=True,
label=legacy_permission_label(app, "protected"),
show_tile=False,
allowed=[],
protected=True,
sync_perm=False,
)
legacy_permission_settings = [
"skipped_uris",
"unprotected_uris",
"protected_uris",
"skipped_regex",
"unprotected_regex",
"protected_regex",
]
for key in legacy_permission_settings:
if key in settings:
del settings[key]
_set_app_settings(app, settings)
permission_sync_to_user()
def translate_legacy_rules_in_ssowant_conf_json_persistent():
persistent_file_name = "/etc/ssowat/conf.json.persistent"
if not os.path.exists(persistent_file_name):
return
# Ugly hack because for some reason so many people have tabs in their conf.json.persistent ...
os.system(r"sed -i 's/\t/ /g' /etc/ssowat/conf.json.persistent")
# Ugly hack to try not to misarably fail migration
persistent = read_yaml(persistent_file_name)
legacy_rules = [
"skipped_urls",
"unprotected_urls",
"protected_urls",
"skipped_regex",
"unprotected_regex",
"protected_regex",
]
if not any(legacy_rule in persistent for legacy_rule in legacy_rules):
return
if not isinstance(persistent.get("permissions"), dict):
persistent["permissions"] = {}
skipped_urls = persistent.get("skipped_urls", []) + [
"re:" + r for r in persistent.get("skipped_regex", [])
]
protected_urls = persistent.get("protected_urls", []) + [
"re:" + r for r in persistent.get("protected_regex", [])
]
unprotected_urls = persistent.get("unprotected_urls", []) + [
"re:" + r for r in persistent.get("unprotected_regex", [])
]
known_users = list(user_list()["users"].keys())
for legacy_rule in legacy_rules:
if legacy_rule in persistent:
del persistent[legacy_rule]
if skipped_urls:
persistent["permissions"]["custom_skipped"] = {
"users": [],
"label": "Custom permissions - skipped",
"show_tile": False,
"auth_header": False,
"public": True,
"uris": skipped_urls
+ persistent["permissions"].get("custom_skipped", {}).get("uris", []),
}
if unprotected_urls:
persistent["permissions"]["custom_unprotected"] = {
"users": [],
"label": "Custom permissions - unprotected",
"show_tile": False,
"auth_header": True,
"public": True,
"uris": unprotected_urls
+ persistent["permissions"].get("custom_unprotected", {}).get("uris", []),
}
if protected_urls:
persistent["permissions"]["custom_protected"] = {
"users": known_users,
"label": "Custom permissions - protected",
"show_tile": False,
"auth_header": True,
"public": False,
"uris": protected_urls
+ persistent["permissions"].get("custom_protected", {}).get("uris", []),
}
write_to_json(persistent_file_name, persistent, sort_keys=True, indent=4)
logger.warning(
"YunoHost automatically translated some legacy rules in /etc/ssowat/conf.json.persistent to match the new permission system"
)