mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-05-27 10:44:33 +00:00
- When app is disabled, it can't be setup as it requires database server and connecting to the database. - If app is disabled, we don't show configuration any more, so redirection to setup page is also not needed. This results in neither setup nor configuration being shown when app is disabled. - During uninstall process, app is disable for first. So, the workaround implemented in is_configured() is no longer needed. Tests: - Install zoph. Setup page is shown. Disable the app by disabling the apache configuration for it and restart service. Setup is no longer shown. - Uninstall zoph. During the uninstall setup, when page is refreshing, setup page is not shown. Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
121 lines
3.9 KiB
Python
121 lines
3.9 KiB
Python
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
"""Configuration helper for Zoph server."""
|
|
|
|
import configparser
|
|
import os
|
|
import re
|
|
import subprocess
|
|
|
|
from plinth import action_utils
|
|
from plinth.actions import privileged
|
|
|
|
APACHE_CONF = '/etc/apache2/conf-available/zoph.conf'
|
|
DB_BACKUP_FILE = '/var/lib/plinth/backups-data/zoph-database.sql'
|
|
|
|
|
|
@privileged
|
|
def pre_install():
|
|
"""Preseed debconf values before packages are installed."""
|
|
action_utils.debconf_set_selections([
|
|
'zoph zoph/dbconfig-install boolean true',
|
|
'zoph zoph/mysql/admin-user string root'
|
|
])
|
|
|
|
|
|
@privileged
|
|
def get_configuration() -> dict[str, str]:
|
|
"""Return the current configuration."""
|
|
configuration = {}
|
|
process = subprocess.run(['zoph', '--dump-config'], stdout=subprocess.PIPE,
|
|
check=True)
|
|
for line in process.stdout.decode().splitlines():
|
|
name, value = line.partition(':')[::2]
|
|
configuration[name.strip()] = value[1:]
|
|
|
|
return configuration
|
|
|
|
|
|
def _zoph_configure(key, value):
|
|
"""Set a configure value in Zoph."""
|
|
subprocess.run(['zoph', '--config', key, value], check=True)
|
|
|
|
|
|
@privileged
|
|
def setup():
|
|
"""Setup Zoph configuration.
|
|
|
|
May be called when app is disabled.
|
|
"""
|
|
with action_utils.service_ensure_running('mysql'):
|
|
_zoph_configure('import.enable', 'true')
|
|
_zoph_configure('import.upload', 'true')
|
|
_zoph_configure('import.rotate', 'true')
|
|
_zoph_configure('path.unzip', 'unzip')
|
|
_zoph_configure('path.untar', 'tar xvf')
|
|
_zoph_configure('path.ungz', 'gunzip')
|
|
|
|
# Maps using OpenStreetMap is enabled by default.
|
|
_zoph_configure('maps.provider', 'osm')
|
|
|
|
|
|
def _get_db_name():
|
|
"""Return the name of the database configured by dbconfig."""
|
|
config = configparser.ConfigParser()
|
|
with open('/etc/zoph.ini', 'r', encoding='utf-8') as file_handle:
|
|
config.read_file(file_handle)
|
|
|
|
return config['zoph']['db_name'].strip('"')
|
|
|
|
|
|
@privileged
|
|
def set_configuration(enable_osm: bool | None = None,
|
|
admin_user: str | None = None):
|
|
"""Setup Zoph Apache configuration."""
|
|
_zoph_configure('interface.user.remote', 'true')
|
|
|
|
# Note that using OpenSteetmap as a mapping provider is a very nice
|
|
# feature, but some people may regard its use as a privacy issue
|
|
if enable_osm is not None:
|
|
value = 'osm' if enable_osm else ''
|
|
_zoph_configure('maps.provider', value)
|
|
|
|
if admin_user:
|
|
# Edit the database to rename the admin user to FreedomBox admin user.
|
|
if not re.match(r'^[\w.@][\w.@-]+\Z', admin_user, flags=re.ASCII):
|
|
# Check to avoid SQL injection
|
|
raise ValueError('Invalid username')
|
|
|
|
query = f"UPDATE zoph_users SET user_name='{admin_user}' \
|
|
WHERE user_name='admin';"
|
|
|
|
subprocess.run(['mysql', _get_db_name()], input=query.encode(),
|
|
check=True)
|
|
|
|
|
|
@privileged
|
|
def is_configured() -> bool | None:
|
|
"""Return whether zoph app is configured."""
|
|
process = subprocess.run(['zoph', '--get-config', 'interface.user.remote'],
|
|
stdout=subprocess.PIPE, check=True)
|
|
return process.stdout.decode().strip() == 'true'
|
|
|
|
|
|
@privileged
|
|
def dump_database():
|
|
"""Dump database to file."""
|
|
db_name = _get_db_name()
|
|
os.makedirs(os.path.dirname(DB_BACKUP_FILE), exist_ok=True)
|
|
with open(DB_BACKUP_FILE, 'w', encoding='utf-8') as db_backup_file:
|
|
subprocess.run(['mysqldump', db_name], stdout=db_backup_file,
|
|
check=True)
|
|
|
|
|
|
@privileged
|
|
def restore_database():
|
|
"""Restore database from file."""
|
|
db_name = _get_db_name()
|
|
subprocess.run(['mysqladmin', '--force', 'drop', db_name], check=False)
|
|
subprocess.run(['mysqladmin', 'create', db_name], check=True)
|
|
with open(DB_BACKUP_FILE, 'r', encoding='utf-8') as db_restore_file:
|
|
subprocess.run(['mysql', db_name], stdin=db_restore_file, check=True)
|