[CI] Format code

This commit is contained in:
yunohost-bot 2021-04-17 00:31:06 +00:00
parent 27c4b33065
commit 66f2613518
19 changed files with 365 additions and 182 deletions

View file

@ -77,7 +77,9 @@ class SystemResourcesDiagnoser(Diagnoser):
# Ignore /dev/loop stuff which are ~virtual partitions ? (e.g. mounted to /snap/)
disk_partitions = [
d for d in disk_partitions if d.mountpoint in ["/", "/var"] or not d.device.startswith("/dev/loop")
d
for d in disk_partitions
if d.mountpoint in ["/", "/var"] or not d.device.startswith("/dev/loop")
]
for disk_partition in disk_partitions:

View file

@ -8,6 +8,7 @@ from yunohost.diagnosis import Diagnoser
from yunohost.regenconf import _get_regenconf_infos, _calculate_hash
from moulinette.utils.filesystem import read_file
class RegenconfDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
@ -37,29 +38,30 @@ class RegenconfDiagnoser(Diagnoser):
details=["diagnosis_regenconf_manually_modified_details"],
)
if any(f["path"] == '/etc/ssh/sshd_config' for f in regenconf_modified_files) \
and os.system("grep -q '^ *AllowGroups\\|^ *AllowUsers' /etc/ssh/sshd_config") != 0:
yield dict(
meta={
"test": "sshd_config_insecure"
},
status="ERROR",
summary="diagnosis_sshd_config_insecure",
)
if (
any(f["path"] == "/etc/ssh/sshd_config" for f in regenconf_modified_files)
and os.system(
"grep -q '^ *AllowGroups\\|^ *AllowUsers' /etc/ssh/sshd_config"
)
!= 0
):
yield dict(
meta={"test": "sshd_config_insecure"},
status="ERROR",
summary="diagnosis_sshd_config_insecure",
)
# Check consistency between actual ssh port in sshd_config vs. setting
ssh_port_setting = settings_get('security.ssh.port')
ssh_port_setting = settings_get("security.ssh.port")
ssh_port_line = re.findall(
r"\bPort *([0-9]{2,5})\b", read_file("/etc/ssh/sshd_config")
)
if len(ssh_port_line) == 1 and int(ssh_port_line[0]) != ssh_port_setting:
yield dict(
meta={
"test": "sshd_config_port_inconsistency"
},
status="WARNING",
summary="diagnosis_sshd_config_inconsistent",
details=["diagnosis_sshd_config_inconsistent_details"],
meta={"test": "sshd_config_port_inconsistency"},
status="WARNING",
summary="diagnosis_sshd_config_inconsistent",
details=["diagnosis_sshd_config_inconsistent_details"],
)
def manually_modified_files(self):

View file

@ -90,56 +90,54 @@ def init_logging(interface="cli", debug=False, quiet=False, logdir="/var/log/yun
os.makedirs(logdir, 0o750)
logging_configuration = {
'version': 1,
'disable_existing_loggers': True,
'formatters': {
'console': {
'format': '%(relativeCreated)-5d %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s'
"version": 1,
"disable_existing_loggers": True,
"formatters": {
"console": {
"format": "%(relativeCreated)-5d %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s"
},
'tty-debug': {
'format': '%(relativeCreated)-4d %(fmessage)s'
},
'precise': {
'format': '%(asctime)-15s %(levelname)-8s %(name)s %(funcName)s - %(fmessage)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',
"filters": {
"action": {
"()": "moulinette.utils.log.ActionFilter",
},
},
'handlers': {
'cli': {
'level': 'DEBUG' if debug else 'INFO',
'class': 'moulinette.interfaces.cli.TTYHandler',
'formatter': 'tty-debug' if debug else '',
"handlers": {
"cli": {
"level": "DEBUG" if debug else "INFO",
"class": "moulinette.interfaces.cli.TTYHandler",
"formatter": "tty-debug" if debug else "",
},
'api': {
'level': 'DEBUG' if debug else 'INFO',
'class': 'moulinette.interfaces.api.APIQueueHandler',
"api": {
"level": "DEBUG" if debug else "INFO",
"class": "moulinette.interfaces.api.APIQueueHandler",
},
'file': {
'class': 'logging.FileHandler',
'formatter': 'precise',
'filename': logfile,
'filters': ['action'],
"file": {
"class": "logging.FileHandler",
"formatter": "precise",
"filename": logfile,
"filters": ["action"],
},
},
'loggers': {
'yunohost': {
'level': 'DEBUG',
'handlers': ['file', interface] if not quiet else ['file'],
'propagate': False,
"loggers": {
"yunohost": {
"level": "DEBUG",
"handlers": ["file", interface] if not quiet else ["file"],
"propagate": False,
},
'moulinette': {
'level': 'DEBUG',
'handlers': ['file', interface] if not quiet else ['file'],
'propagate': False,
"moulinette": {
"level": "DEBUG",
"handlers": ["file", interface] if not quiet else ["file"],
"propagate": False,
},
},
'root': {
'level': 'DEBUG',
'handlers': ['file', interface] if debug else ['file'],
"root": {
"level": "DEBUG",
"handlers": ["file", interface] if debug else ["file"],
},
}
@ -150,7 +148,9 @@ def init_logging(interface="cli", debug=False, quiet=False, logdir="/var/log/yun
# Logging configuration for API #
else:
# We use a WatchedFileHandler instead of regular FileHandler to possibly support log rotation etc
logging_configuration["handlers"]["file"]["class"] = 'logging.handlers.WatchedFileHandler'
logging_configuration["handlers"]["file"][
"class"
] = "logging.handlers.WatchedFileHandler"
# This is for when launching yunohost-api in debug mode, we want to display stuff in the console
if debug:

View file

@ -193,7 +193,9 @@ def app_info(app, full=False):
)
local_manifest = _get_manifest_of_app(os.path.join(APPS_SETTING_PATH, app))
permissions = user_permission_list(full=True, absolute_urls=True, apps=[app])["permissions"]
permissions = user_permission_list(full=True, absolute_urls=True, apps=[app])[
"permissions"
]
settings = _get_app_settings(app)
@ -325,7 +327,9 @@ def app_map(app=None, raw=False, user=None):
else:
apps = _installed_apps()
permissions = user_permission_list(full=True, absolute_urls=True, apps=apps)["permissions"]
permissions = user_permission_list(full=True, absolute_urls=True, apps=apps)[
"permissions"
]
for app_id in apps:
app_settings = _get_app_settings(app_id)
if not app_settings:
@ -782,6 +786,7 @@ def app_manifest(app):
return manifest
@is_unit_operation()
def app_install(
operation_logger,
@ -1106,10 +1111,7 @@ def app_install(
permission_sync_to_user()
raise YunohostError(
failure_message_with_debug_instructions,
raw_msg=True
)
raise YunohostError(failure_message_with_debug_instructions, raw_msg=True)
# Clean hooks and add new ones
hook_remove(app_instance_name)
@ -2232,9 +2234,13 @@ def _extract_app_from_file(path):
extracted_app_folder = _make_tmp_workdir_for_app()
if ".zip" in path:
extract_result = os.system(f"unzip '{path}' -d {extracted_app_folder} > /dev/null 2>&1")
extract_result = os.system(
f"unzip '{path}' -d {extracted_app_folder} > /dev/null 2>&1"
)
elif ".tar" in path:
extract_result = os.system(f"tar -xf '{path}' -C {extracted_app_folder} > /dev/null 2>&1")
extract_result = os.system(
f"tar -xf '{path}' -C {extracted_app_folder} > /dev/null 2>&1"
)
elif os.path.isdir(path):
shutil.rmtree(extracted_app_folder)
if path[-1] != "/":
@ -2746,7 +2752,9 @@ class YunoHostArgumentFormatParser(object):
# we don't have an answer, check optional and default_value
if question.value is None or question.value == "":
if not question.optional and question.default is None:
raise YunohostValidationError("app_argument_required", name=question.name)
raise YunohostValidationError(
"app_argument_required", name=question.name
)
else:
question.value = (
getattr(self, "default_value", None)
@ -2804,7 +2812,9 @@ class PasswordArgumentParser(YunoHostArgumentFormatParser):
)
if question.default is not None:
raise YunohostValidationError("app_argument_password_no_default", name=question.name)
raise YunohostValidationError(
"app_argument_password_no_default", name=question.name
)
return question
@ -3114,7 +3124,9 @@ def _assert_no_conflicting_apps(domain, path, ignore_app=None, full_domain=False
if full_domain:
raise YunohostValidationError("app_full_domain_unavailable", domain=domain)
else:
raise YunohostValidationError("app_location_unavailable", apps="\n".join(apps))
raise YunohostValidationError(
"app_location_unavailable", apps="\n".join(apps)
)
def _make_environment_for_app_script(app, args={}, args_prefix="APP_ARG_"):
@ -3340,6 +3352,7 @@ def _load_apps_catalog():
# ############################### #
#
def _make_tmp_workdir_for_app(app=None):
# Create parent dir if it doesn't exists yet
@ -3425,15 +3438,27 @@ def _assert_system_is_sane_for_app(manifest, when):
if not any(s for s in services if service_status(s)["status"] == "reloading"):
break
time.sleep(0.5)
test_nb+=1
test_nb += 1
# List services currently down and raise an exception if any are found
services_status = {s:service_status(s) for s in services}
faulty_services = [f"{s} ({status['status']})" for s, status in services_status.items() if status['status'] != "running"]
services_status = {s: service_status(s) for s in services}
faulty_services = [
f"{s} ({status['status']})"
for s, status in services_status.items()
if status["status"] != "running"
]
# Stupid tmp fix to try to track why the tests are failing
if "php7.3-fpm" in [s for s, status in services_status.items() if status['status'] != "running"]:
logger.info([status for s, status in services_status.items() if status['status'] != "running"])
if "php7.3-fpm" in [
s for s, status in services_status.items() if status["status"] != "running"
]:
logger.info(
[
status
for s, status in services_status.items()
if status["status"] != "running"
]
)
os.system("journalctl -u php7.3-fpm -n 300 --no-hostname --no-pager")
if faulty_services:
@ -3609,7 +3634,7 @@ def _patch_legacy_helpers(app_folder):
content = read_file(filename)
except MoulinetteError:
continue
replaced_stuff = False
show_warning = False

View file

@ -53,7 +53,7 @@ from yunohost.app import (
_patch_legacy_php_versions,
_patch_legacy_php_versions_in_settings,
LEGACY_PHP_VERSION_REPLACEMENTS,
_make_tmp_workdir_for_app
_make_tmp_workdir_for_app,
)
from yunohost.hook import (
hook_list,
@ -62,7 +62,11 @@ from yunohost.hook import (
hook_exec,
CUSTOM_HOOK_FOLDER,
)
from yunohost.tools import tools_postinstall, _tools_migrations_run_after_system_restore, _tools_migrations_run_before_app_restore
from yunohost.tools import (
tools_postinstall,
_tools_migrations_run_after_system_restore,
_tools_migrations_run_before_app_restore,
)
from yunohost.regenconf import regen_conf
from yunohost.log import OperationLogger, is_unit_operation
from yunohost.utils.error import YunohostError, YunohostValidationError
@ -716,7 +720,9 @@ class BackupManager:
hook_exec(
f"{tmp_workdir_for_app}/scripts/backup",
raise_on_error=True, chdir=tmp_app_bkp_dir, env=env_dict
raise_on_error=True,
chdir=tmp_app_bkp_dir,
env=env_dict,
)[0]
self._import_to_list_to_backup(env_dict["YNH_BACKUP_CSV"])
@ -724,10 +730,7 @@ class BackupManager:
# backup permissions
logger.debug(m18n.n("backup_permission", app=app))
permissions = user_permission_list(full=True, apps=[app])["permissions"]
this_app_permissions = {
name: infos
for name, infos in permissions.items()
}
this_app_permissions = {name: infos for name, infos in permissions.items()}
write_to_yaml("%s/permissions.yml" % settings_dir, this_app_permissions)
except Exception:
@ -857,7 +860,9 @@ class RestoreManager:
# FIXME this way to get the info is not compatible with copy or custom
# backup methods
self.info = backup_info(name, with_details=True)
if not self.info["from_yunohost_version"] or version.parse(self.info["from_yunohost_version"]) < version.parse("3.8.0"):
if not self.info["from_yunohost_version"] or version.parse(
self.info["from_yunohost_version"]
) < version.parse("3.8.0"):
raise YunohostValidationError("restore_backup_too_old")
self.archive_path = self.info["path"]
@ -1279,7 +1284,9 @@ class RestoreManager:
regen_conf()
_tools_migrations_run_after_system_restore(backup_version=self.info["from_yunohost_version"])
_tools_migrations_run_after_system_restore(
backup_version=self.info["from_yunohost_version"]
)
# Remove all permission for all app still in the LDAP
for permission_name in user_permission_list(ignore_system_perms=True)[
@ -1409,7 +1416,9 @@ class RestoreManager:
# Restore permissions
if not os.path.isfile("%s/permissions.yml" % app_settings_new_path):
raise YunohostError("Didnt find a permssions.yml for the app !?", raw_msg=True)
raise YunohostError(
"Didnt find a permssions.yml for the app !?", raw_msg=True
)
permissions = read_yaml("%s/permissions.yml" % app_settings_new_path)
existing_groups = user_group_list()["groups"]
@ -1424,9 +1433,7 @@ class RestoreManager:
should_be_allowed = ["all_users"]
else:
should_be_allowed = [
g
for g in permission_infos["allowed"]
if g in existing_groups
g for g in permission_infos["allowed"] if g in existing_groups
]
perm_name = permission_name.split(".")[1]
@ -1448,9 +1455,13 @@ class RestoreManager:
os.remove("%s/permissions.yml" % app_settings_new_path)
_tools_migrations_run_before_app_restore(backup_version=self.info["from_yunohost_version"], app_id=app_instance_name)
_tools_migrations_run_before_app_restore(
backup_version=self.info["from_yunohost_version"],
app_id=app_instance_name,
)
except Exception:
import traceback
error = m18n.n("unexpected_error", error="\n" + traceback.format_exc())
msg = m18n.n("app_restore_failed", app=app_instance_name, error=error)
logger.error(msg)
@ -1493,20 +1504,27 @@ class RestoreManager:
restore_failed = True if restore_retcode != 0 else False
if restore_failed:
error = m18n.n("app_restore_script_failed")
logger.error(m18n.n("app_restore_failed", app=app_instance_name, error=error))
logger.error(
m18n.n("app_restore_failed", app=app_instance_name, error=error)
)
failure_message_with_debug_instructions = operation_logger.error(error)
if msettings.get("interface") != "api":
dump_app_log_extract_for_debugging(operation_logger)
# Script got manually interrupted ... N.B. : KeyboardInterrupt does not inherit from Exception
except (KeyboardInterrupt, EOFError):
error = m18n.n("operation_interrupted")
logger.error(m18n.n("app_restore_failed", app=app_instance_name, error=error))
logger.error(
m18n.n("app_restore_failed", app=app_instance_name, error=error)
)
failure_message_with_debug_instructions = operation_logger.error(error)
# Something wrong happened in Yunohost's code (most probably hook_exec)
except Exception:
import traceback
error = m18n.n("unexpected_error", error="\n" + traceback.format_exc())
logger.error(m18n.n("app_restore_failed", app=app_instance_name, error=error))
logger.error(
m18n.n("app_restore_failed", app=app_instance_name, error=error)
)
failure_message_with_debug_instructions = operation_logger.error(error)
finally:
# Cleaning temporary scripts directory
@ -1551,6 +1569,7 @@ class RestoreManager:
logger.error(failure_message_with_debug_instructions)
#
# Backup methods #
#
@ -2163,7 +2182,13 @@ class CustomBackupMethod(BackupMethod):
@is_unit_operation()
def backup_create(
operation_logger,
name=None, description=None, methods=[], output_directory=None, system=[], apps=[], dry_run=False
name=None,
description=None,
methods=[],
output_directory=None,
system=[],
apps=[],
dry_run=False,
):
"""
Create a backup local archive
@ -2248,12 +2273,17 @@ def backup_create(
if dry_run:
return {
"size": backup_manager.size,
"size_details": backup_manager.size_details
"size_details": backup_manager.size_details,
}
# Apply backup methods on prepared files
logger.info(m18n.n("backup_actually_backuping"))
logger.info(m18n.n("backup_create_size_estimation", size=binary_to_human(backup_manager.size) + "B"))
logger.info(
m18n.n(
"backup_create_size_estimation",
size=binary_to_human(backup_manager.size) + "B",
)
)
backup_manager.backup()
logger.success(m18n.n("backup_created"))
@ -2291,9 +2321,9 @@ def backup_restore(name, system=[], apps=[], force=False):
#
if name.endswith(".tar.gz"):
name = name[:-len(".tar.gz")]
name = name[: -len(".tar.gz")]
elif name.endswith(".tar"):
name = name[:-len(".tar")]
name = name[: -len(".tar")]
restore_manager = RestoreManager(name)
@ -2407,7 +2437,9 @@ def backup_download(name):
# Raise exception if link is broken (e.g. on unmounted external storage)
if not os.path.exists(archive_file):
raise YunohostValidationError("backup_archive_broken_link", path=archive_file)
raise YunohostValidationError(
"backup_archive_broken_link", path=archive_file
)
# We return a raw bottle HTTPresponse (instead of serializable data like
# list/dict, ...), which is gonna be picked and used directly by moulinette
@ -2429,9 +2461,9 @@ def backup_info(name, with_details=False, human_readable=False):
"""
if name.endswith(".tar.gz"):
name = name[:-len(".tar.gz")]
name = name[: -len(".tar.gz")]
elif name.endswith(".tar"):
name = name[:-len(".tar")]
name = name[: -len(".tar")]
archive_file = "%s/%s.tar" % (ARCHIVES_PATH, name)
@ -2447,7 +2479,9 @@ def backup_info(name, with_details=False, human_readable=False):
# Raise exception if link is broken (e.g. on unmounted external storage)
if not os.path.exists(archive_file):
raise YunohostValidationError("backup_archive_broken_link", path=archive_file)
raise YunohostValidationError(
"backup_archive_broken_link", path=archive_file
)
info_file = "%s/%s.info.json" % (ARCHIVES_PATH, name)

View file

@ -455,6 +455,7 @@ def certificate_renew(
# Back-end stuff #
#
def _email_renewing_failed(domain, exception_message, stack=""):
from_ = "certmanager@%s (Certificate Manager)" % domain
to_ = "root"
@ -872,7 +873,9 @@ def _check_domain_is_ready_for_ACME(domain):
)
if not dnsrecords or not httpreachable:
raise YunohostValidationError("certmanager_domain_not_diagnosed_yet", domain=domain)
raise YunohostValidationError(
"certmanager_domain_not_diagnosed_yet", domain=domain
)
# Check if IP from DNS matches public IP
if not dnsrecords.get("status") in [
@ -885,7 +888,9 @@ def _check_domain_is_ready_for_ACME(domain):
# Check if domain seems to be accessible through HTTP?
if not httpreachable.get("status") == "SUCCESS":
raise YunohostValidationError("certmanager_domain_http_not_working", domain=domain)
raise YunohostValidationError(
"certmanager_domain_http_not_working", domain=domain
)
# FIXME / TODO : ideally this should not be needed. There should be a proper

View file

@ -9,7 +9,7 @@ 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')
logger = getActionLogger("yunohost.migration")
###################################################
# Tools used also for restoration
@ -18,7 +18,7 @@ logger = getActionLogger('yunohost.migration')
class MyMigration(Migration):
"""
Add new permissions around SSH/SFTP features
Add new permissions around SSH/SFTP features
"""
introduced_in_version = "4.2.2"
@ -28,38 +28,60 @@ class MyMigration(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]
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
ldap_map = read_yaml('/usr/share/yunohost/yunohost-config/moulinette/ldap_scheme.yml')
ldap_map = read_yaml(
"/usr/share/yunohost/yunohost-config/moulinette/ldap_scheme.yml"
)
if "sftp.main" not in existing_perms:
ldap.add("cn=sftp.main,ou=permission", ldap_map['depends_children']["cn=sftp.main,ou=permission"])
ldap.add(
"cn=sftp.main,ou=permission",
ldap_map["depends_children"]["cn=sftp.main,ou=permission"],
)
if "ssh.main" not in existing_perms:
ldap.add("cn=ssh.main,ou=permission", ldap_map['depends_children']["cn=ssh.main,ou=permission"])
ldap.add(
"cn=ssh.main,ou=permission",
ldap_map["depends_children"]["cn=ssh.main,ou=permission"],
)
# Add a bash terminal to each users
users = ldap.search('ou=users,dc=yunohost,dc=org', filter="(loginShell=*)", attrs=["dn", "uid", "loginShell"])
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']})
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)
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'])
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'))
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

@ -59,7 +59,9 @@ def diagnosis_get(category, item):
all_categories_names = [c for c, _ in all_categories]
if category not in all_categories_names:
raise YunohostValidationError("diagnosis_unknown_categories", categories=category)
raise YunohostValidationError(
"diagnosis_unknown_categories", categories=category
)
if isinstance(item, list):
if any("=" not in criteria for criteria in item):

View file

@ -122,7 +122,7 @@ def domain_add(operation_logger, domain, dyndns=False):
# Do not allow to subscribe to multiple dyndns domains...
if _guess_current_dyndns_domain("dyndns.yunohost.org") != (None, None):
raise YunohostValidationError('domain_dyndns_already_subscribed')
raise YunohostValidationError("domain_dyndns_already_subscribed")
# Check that this domain can effectively be provided by
# dyndns.yunohost.org. (i.e. is it a nohost.me / noho.st)
@ -133,6 +133,7 @@ def domain_add(operation_logger, domain, dyndns=False):
if dyndns:
from yunohost.dyndns import dyndns_subscribe
# Actually subscribe
dyndns_subscribe(domain=domain)
@ -197,8 +198,8 @@ def domain_remove(operation_logger, domain, remove_apps=False, force=False):
# the 'force' here is related to the exception happening in domain_add ...
# we don't want to check the domain exists because the ldap add may have
# failed
if not force and domain not in domain_list()['domains']:
raise YunohostValidationError('domain_name_unknown', domain=domain)
if not force and domain not in domain_list()["domains"]:
raise YunohostValidationError("domain_name_unknown", domain=domain)
# Check domain is not the main domain
if domain == _get_maindomain():
@ -212,7 +213,9 @@ def domain_remove(operation_logger, domain, remove_apps=False, force=False):
other_domains="\n * " + ("\n * ".join(other_domains)),
)
else:
raise YunohostValidationError("domain_cannot_remove_main_add_new_one", domain=domain)
raise YunohostValidationError(
"domain_cannot_remove_main_add_new_one", domain=domain
)
# Check if apps are installed on the domain
apps_on_that_domain = []
@ -221,21 +224,37 @@ def domain_remove(operation_logger, domain, remove_apps=False, force=False):
settings = _get_app_settings(app)
label = app_info(app)["name"]
if settings.get("domain") == domain:
apps_on_that_domain.append((app, " - %s \"%s\" on https://%s%s" % (app, label, domain, settings["path"]) if "path" in settings else app))
apps_on_that_domain.append(
(
app,
' - %s "%s" on https://%s%s'
% (app, label, domain, settings["path"])
if "path" in settings
else app,
)
)
if apps_on_that_domain:
if remove_apps:
if msettings.get('interface') == "cli" and not force:
answer = msignals.prompt(m18n.n('domain_remove_confirm_apps_removal',
apps="\n".join([x[1] for x in apps_on_that_domain]),
answers='y/N'), color="yellow")
if msettings.get("interface") == "cli" and not force:
answer = msignals.prompt(
m18n.n(
"domain_remove_confirm_apps_removal",
apps="\n".join([x[1] for x in apps_on_that_domain]),
answers="y/N",
),
color="yellow",
)
if answer.upper() != "Y":
raise YunohostError("aborting")
for app, _ in apps_on_that_domain:
app_remove(app)
else:
raise YunohostValidationError('domain_uninstall_app_first', apps="\n".join([x[1] for x in apps_on_that_domain]))
raise YunohostValidationError(
"domain_uninstall_app_first",
apps="\n".join([x[1] for x in apps_on_that_domain]),
)
operation_logger.start()
@ -248,7 +267,7 @@ def domain_remove(operation_logger, domain, remove_apps=False, force=False):
os.system("rm -rf /etc/yunohost/certs/%s" % domain)
# Delete dyndns keys for this domain (if any)
os.system('rm -rf /etc/yunohost/dyndns/K%s.+*' % domain)
os.system("rm -rf /etc/yunohost/dyndns/K%s.+*" % domain)
# Sometime we have weird issues with the regenconf where some files
# appears as manually modified even though they weren't touched ...

View file

@ -124,7 +124,7 @@ def dyndns_subscribe(
"""
if _guess_current_dyndns_domain(subscribe_host) != (None, None):
raise YunohostValidationError('domain_dyndns_already_subscribed')
raise YunohostValidationError("domain_dyndns_already_subscribed")
if domain is None:
domain = _get_maindomain()
@ -192,12 +192,14 @@ def dyndns_subscribe(
# Add some dyndns update in 2 and 4 minutes from now such that user should
# not have to wait 10ish minutes for the conf to propagate
cmd = "at -M now + {t} >/dev/null 2>&1 <<< \"/bin/bash -c 'yunohost dyndns update'\""
cmd = (
"at -M now + {t} >/dev/null 2>&1 <<< \"/bin/bash -c 'yunohost dyndns update'\""
)
# For some reason subprocess doesn't like the redirections so we have to use bash -c explicity...
subprocess.check_call(["bash", "-c", cmd.format(t="2 min")])
subprocess.check_call(["bash", "-c", cmd.format(t="4 min")])
logger.success(m18n.n('dyndns_registered'))
logger.success(m18n.n("dyndns_registered"))
@is_unit_operation()
@ -231,7 +233,7 @@ def dyndns_update(
(domain, key) = _guess_current_dyndns_domain(dyn_host)
if domain is None:
raise YunohostValidationError('dyndns_no_domain_registered')
raise YunohostValidationError("dyndns_no_domain_registered")
# If key is not given, pick the first file we find with the domain given
else:
@ -374,11 +376,15 @@ 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'.")
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'.")
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):

View file

@ -188,11 +188,17 @@ def firewall_list(raw=False, by_ip_version=False, list_forwarded=False):
for i in ["ipv4", "ipv6"]:
f = firewall[i]
# Combine TCP and UDP ports
ports[i] = sorted(set(f["TCP"]) | set(f["UDP"]), key=lambda p: int(p.split(':')[0]) if isinstance(p, str) else p)
ports[i] = sorted(
set(f["TCP"]) | set(f["UDP"]),
key=lambda p: int(p.split(":")[0]) if isinstance(p, str) else p,
)
if not by_ip_version:
# Combine IPv4 and IPv6 ports
ports = sorted(set(ports["ipv4"]) | set(ports["ipv6"]), key=lambda p: int(p.split(':')[0]) if isinstance(p, str) else p)
ports = sorted(
set(ports["ipv4"]) | set(ports["ipv6"]),
key=lambda p: int(p.split(":")[0]) if isinstance(p, str) else p,
)
# Format returned dict
ret = {"opened_ports": ports}
@ -200,7 +206,7 @@ def firewall_list(raw=False, by_ip_version=False, list_forwarded=False):
# Combine TCP and UDP forwarded ports
ret["forwarded_ports"] = sorted(
set(firewall["uPnP"]["TCP"]) | set(firewall["uPnP"]["UDP"]),
key=lambda p: int(p.split(':')[0]) if isinstance(p, str) else p
key=lambda p: int(p.split(":")[0]) if isinstance(p, str) else p,
)
return ret

View file

@ -414,8 +414,15 @@ class RedactingFormatter(Formatter):
# This matches stuff like db_pwd=the_secret or admin_password=other_secret
# (the secret part being at least 3 chars to avoid catching some lines like just "db_pwd=")
# Some names like "key" or "manifest_key" are ignored, used in helpers like ynh_app_setting_set or ynh_read_manifest
match = re.search(r'(pwd|pass|password|passphrase|secret\w*|\w+key|token)=(\S{3,})$', record.strip())
if match and match.group(2) not in self.data_to_redact and match.group(1) not in ["key", "manifest_key"]:
match = re.search(
r"(pwd|pass|password|passphrase|secret\w*|\w+key|token)=(\S{3,})$",
record.strip(),
)
if (
match
and match.group(2) not in self.data_to_redact
and match.group(1) not in ["key", "manifest_key"]
):
self.data_to_redact.append(match.group(2))
except Exception as e:
logger.warning(
@ -636,7 +643,11 @@ class OperationLogger(object):
# we want to inject the log ref in the exception, such that it may be
# transmitted to the webadmin which can then redirect to the appropriate
# log page
if self.started_at and isinstance(error, Exception) and not isinstance(error, YunohostValidationError):
if (
self.started_at
and isinstance(error, Exception)
and not isinstance(error, YunohostValidationError)
):
error.log_ref = self.name
if self.ended_at is not None or self.started_at is None:

View file

@ -80,7 +80,9 @@ def user_permission_list(
apps_base_path = {
app: app_setting(app, "domain") + app_setting(app, "path")
for app in apps
if app in installed_apps and app_setting(app, "domain") and app_setting(app, "path")
if app in installed_apps
and app_setting(app, "domain")
and app_setting(app, "path")
}
permissions = {}
@ -179,7 +181,9 @@ def user_permission_update(
# Refuse to add "visitors" to mail, xmpp ... they require an account to make sense.
if add and "visitors" in add and permission.split(".")[0] in SYSTEM_PERMS:
raise YunohostValidationError("permission_require_account", permission=permission)
raise YunohostValidationError(
"permission_require_account", permission=permission
)
# Refuse to add "visitors" to protected permission
if (
@ -189,8 +193,14 @@ def user_permission_update(
raise YunohostValidationError("permission_protected", permission=permission)
# Refuse to add "all_users" to ssh/sftp permissions
if permission.split(".")[0] in ["ssh", "sftp"] and (add and "all_users" in add) and not force:
raise YunohostValidationError("permission_cant_add_to_all_users", permission=permission)
if (
permission.split(".")[0] in ["ssh", "sftp"]
and (add and "all_users" in add)
and not force
):
raise YunohostValidationError(
"permission_cant_add_to_all_users", permission=permission
)
# Fetch currently allowed groups for this permission

View file

@ -103,6 +103,7 @@ DEFAULTS = OrderedDict(
]
)
def settings_get(key, full=False):
"""
Get an entry value in the settings
@ -114,7 +115,9 @@ def settings_get(key, full=False):
settings = _get_settings()
if key not in settings:
raise YunohostValidationError("global_settings_key_doesnt_exists", settings_key=key)
raise YunohostValidationError(
"global_settings_key_doesnt_exists", settings_key=key
)
if full:
return settings[key]
@ -142,7 +145,9 @@ def settings_set(key, value):
settings = _get_settings()
if key not in settings:
raise YunohostValidationError("global_settings_key_doesnt_exists", settings_key=key)
raise YunohostValidationError(
"global_settings_key_doesnt_exists", settings_key=key
)
key_type = settings[key]["type"]
@ -219,7 +224,9 @@ def settings_reset(key):
settings = _get_settings()
if key not in settings:
raise YunohostValidationError("global_settings_key_doesnt_exists", settings_key=key)
raise YunohostValidationError(
"global_settings_key_doesnt_exists", settings_key=key
)
settings[key]["value"] = settings[key]["default"]
_save_settings(settings)
@ -381,6 +388,7 @@ def trigger_post_change_hook(setting_name, old_value, new_value):
#
# ===========================================
@post_change_hook("ssowat.panel_overlay.enabled")
@post_change_hook("security.nginx.compatibility")
def reconfigure_nginx(setting_name, old_value, new_value):

View file

@ -99,18 +99,16 @@ def user_ssh_remove_key(username, key):
if not os.path.exists(authorized_keys_file):
raise YunohostValidationError(
"this key doesn't exists ({} dosesn't exists)".format(authorized_keys_file),
raw_msg=True
raw_msg=True,
)
authorized_keys_content = read_file(authorized_keys_file)
if key not in authorized_keys_content:
raise YunohostValidationError(
"Key '{}' is not present in authorized_keys".format(key),
raw_msg=True
"Key '{}' is not present in authorized_keys".format(key), raw_msg=True
)
# don't delete the previous comment because we can't verify if it's legit
# this regex approach failed for some reasons and I don't know why :(

View file

@ -56,7 +56,9 @@ def clean():
shutil.rmtree(folderpath, ignore_errors=True)
os.system("bash -c \"mysql -B 2>/dev/null <<< 'DROP DATABASE %s' \"" % test_app)
os.system("bash -c \"mysql -B 2>/dev/null <<< 'DROP USER %s@localhost'\"" % test_app)
os.system(
"bash -c \"mysql -B 2>/dev/null <<< 'DROP USER %s@localhost'\"" % test_app
)
# Reset failed quota for service to avoid running into start-limit rate ?
os.system("systemctl reset-failed nginx")

View file

@ -30,7 +30,7 @@ def setup_function(function):
def teardown_function(function):
os.system("mv /etc/yunohost/settings.json.saved /etc/yunohost/settings.json")
for filename in glob.glob("/etc/yunohost/settings-*.json"):
os.remove(filename)
os.remove(filename)
def test_settings_get_bool():

View file

@ -413,7 +413,9 @@ def tools_update(target=None, apps=False, system=False):
# 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)")
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:
@ -425,7 +427,10 @@ def tools_update(target=None, apps=False, system=False):
target = "all"
if target not in ["system", "apps", "all"]:
raise YunohostError("Unknown target %s, should be 'system', 'apps' or 'all'" % target, raw_msg=True)
raise YunohostError(
"Unknown target %s, should be 'system', 'apps' or 'all'" % target,
raw_msg=True,
)
upgradable_system_packages = []
if target in ["system", "all"]:
@ -548,7 +553,9 @@ def tools_upgrade(
# 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)")
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")
@ -559,7 +566,9 @@ def tools_upgrade(
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")
raise Exception(
"Uhoh ?! tools_upgrade should have 'apps' or 'system' value for argument target"
)
#
# Apps
@ -914,9 +923,13 @@ def tools_migrations_run(
pending = [t.id for t in targets if t.state == "pending"]
if skip and done:
raise YunohostValidationError("migrations_not_pending_cant_skip", ids=", ".join(done))
raise YunohostValidationError(
"migrations_not_pending_cant_skip", ids=", ".join(done)
)
if force_rerun and pending:
raise YunohostValidationError("migrations_pending_cant_rerun", ids=", ".join(pending))
raise YunohostValidationError(
"migrations_pending_cant_rerun", ids=", ".join(pending)
)
if not (skip or force_rerun) and done:
raise YunohostValidationError("migrations_already_ran", ids=", ".join(done))
@ -1129,9 +1142,11 @@ def _tools_migrations_run_after_system_restore(backup_version):
return
for migration in all_migrations:
if hasattr(migration, "introduced_in_version") \
and version.parse(migration.introduced_in_version) > backup_version \
and hasattr(migration, "run_after_system_restore"):
if (
hasattr(migration, "introduced_in_version")
and version.parse(migration.introduced_in_version) > backup_version
and hasattr(migration, "run_after_system_restore")
):
try:
logger.info(m18n.n("migrations_running_forward", id=migration.id))
migration.run_after_system_restore()
@ -1154,9 +1169,11 @@ def _tools_migrations_run_before_app_restore(backup_version, app_id):
return
for migration in all_migrations:
if hasattr(migration, "introduced_in_version") \
and version.parse(migration.introduced_in_version) > backup_version \
and hasattr(migration, "run_before_app_restore"):
if (
hasattr(migration, "introduced_in_version")
and version.parse(migration.introduced_in_version) > backup_version
and hasattr(migration, "run_before_app_restore")
):
try:
logger.info(m18n.n("migrations_running_forward", id=migration.id))
migration.run_before_app_restore(app_id)
@ -1167,6 +1184,7 @@ def _tools_migrations_run_before_app_restore(backup_version, app_id):
logger.error(msg, exc_info=1)
raise
class Migration(object):
# Those are to be implemented by daughter classes
@ -1193,7 +1211,6 @@ class Migration(object):
return m18n.n("migration_description_%s" % self.id)
def ldap_migration(run):
def func(self):
# Backup LDAP before the migration
@ -1206,7 +1223,9 @@ class Migration(object):
os.system("systemctl stop slapd")
os.system(f"cp -r --preserve /etc/ldap {backup_folder}/ldap_config")
os.system(f"cp -r --preserve /var/lib/ldap {backup_folder}/ldap_db")
os.system(f"cp -r --preserve /etc/yunohost/apps {backup_folder}/apps_settings")
os.system(
f"cp -r --preserve /etc/yunohost/apps {backup_folder}/apps_settings"
)
except Exception as e:
raise YunohostError(
"migration_ldap_can_not_backup_before_migration", error=str(e)
@ -1217,13 +1236,17 @@ class Migration(object):
try:
run(self, backup_folder)
except Exception:
logger.warning(m18n.n("migration_ldap_migration_failed_trying_to_rollback"))
logger.warning(
m18n.n("migration_ldap_migration_failed_trying_to_rollback")
)
os.system("systemctl stop slapd")
# To be sure that we don't keep some part of the old config
os.system("rm -r /etc/ldap/slapd.d")
os.system(f"cp -r --preserve {backup_folder}/ldap_config/. /etc/ldap/")
os.system(f"cp -r --preserve {backup_folder}/ldap_db/. /var/lib/ldap/")
os.system(f"cp -r --preserve {backup_folder}/apps_settings/. /etc/yunohost/apps/")
os.system(
f"cp -r --preserve {backup_folder}/apps_settings/. /etc/yunohost/apps/"
)
os.system("systemctl start slapd")
os.system(f"rm -r {backup_folder}")
logger.info(m18n.n("migration_ldap_rollback_success"))

View file

@ -118,7 +118,9 @@ def user_create(
# Validate domain used for email address/xmpp account
if domain is None:
if msettings.get("interface") == "api":
raise YunohostValidationError("Invalid usage, you should specify a domain argument")
raise YunohostValidationError(
"Invalid usage, you should specify a domain argument"
)
else:
# On affiche les differents domaines possibles
msignals.display(m18n.n("domains_available"))
@ -223,7 +225,9 @@ def user_create(
logger.warning(m18n.n("user_home_creation_failed"), exc_info=1)
try:
subprocess.check_call(["setfacl", "-m", "g:all_users:---", "/home/%s" % username])
subprocess.check_call(
["setfacl", "-m", "g:all_users:---", "/home/%s" % username]
)
except subprocess.CalledProcessError:
logger.warning("Failed to protect /home/%s" % username, exc_info=1)
@ -412,7 +416,9 @@ def user_update(
try:
ldap.validate_uniqueness({"mail": mail})
except Exception as e:
raise YunohostValidationError("user_update_failed", user=username, error=e)
raise YunohostValidationError(
"user_update_failed", user=username, error=e
)
if mail[mail.find("@") + 1 :] not in domains:
raise YunohostValidationError(
"mail_domain_unknown", domain=mail[mail.find("@") + 1 :]
@ -649,7 +655,9 @@ def user_group_create(
"sed --in-place '/^%s:/d' /etc/group" % groupname, shell=True
)
else:
raise YunohostValidationError("group_already_exist_on_system", group=groupname)
raise YunohostValidationError(
"group_already_exist_on_system", group=groupname
)
if not gid:
# Get random GID
@ -758,7 +766,9 @@ def user_group_update(
elif groupname == "visitors":
raise YunohostValidationError("group_cannot_edit_visitors")
elif groupname in existing_users:
raise YunohostValidationError("group_cannot_edit_primary_group", group=groupname)
raise YunohostValidationError(
"group_cannot_edit_primary_group", group=groupname
)
# We extract the uid for each member of the group to keep a simple flat list of members
current_group = user_group_info(groupname)["members"]
@ -864,9 +874,7 @@ def user_group_add(groupname, usernames, force=False, sync_perm=True):
usernames -- User(s) to add in the group
"""
return user_group_update(
groupname, add=usernames, force=force, sync_perm=sync_perm
)
return user_group_update(groupname, add=usernames, force=force, sync_perm=sync_perm)
def user_group_remove(groupname, usernames, force=False, sync_perm=True):
@ -891,7 +899,9 @@ def user_group_remove(groupname, usernames, force=False, sync_perm=True):
def user_permission_list(short=False, full=False, apps=[]):
import yunohost.permission
return yunohost.permission.user_permission_list(short, full, absolute_urls=True, apps=apps)
return yunohost.permission.user_permission_list(
short, full, absolute_urls=True, apps=apps
)
def user_permission_update(permission, label=None, show_tile=None, sync_perm=True):
@ -902,9 +912,7 @@ def user_permission_update(permission, label=None, show_tile=None, sync_perm=Tru
)
def user_permission_add(
permission, names, protected=None, force=False, sync_perm=True
):
def user_permission_add(permission, names, protected=None, force=False, sync_perm=True):
import yunohost.permission
return yunohost.permission.user_permission_update(