#!/usr/bin/python3 # SPDX-License-Identifier: AGPL-3.0-or-later """ Configuration helper for WordPress. """ import argparse import os import pathlib import random import shutil import string import subprocess import augeas from plinth import action_utils from plinth.modules.wordpress import PUBLIC_ACCESS_FILE _config_file_path = pathlib.Path('/etc/wordpress/config-default.php') _db_file_path = pathlib.Path('/etc/wordpress/database.php') _db_backup_file = pathlib.Path( '/var/lib/plinth/backups-data/wordpress-database.sql') DB_HOST = 'localhost' DB_NAME = 'wordpress_fbx' DB_USER = 'wordpress_fbx' def parse_arguments(): """Return parsed command line arguments as dictionary.""" parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(dest='subcommand', help='Sub command') subparsers.add_parser('setup', help='Create initial configuration and database') subparsers.add_parser('dump-database', help='Dump database to file') subparsers.add_parser('restore-database', help='Restore database from file') subparser = subparsers.add_parser('set-public', help='Allow/disallow public access') subparser.add_argument('--enable', choices=('True', 'False'), help='Whether to enable or disable public acceess') subparsers.required = True return parser.parse_args() def subcommand_setup(_): """Create initial configuration and database for WordPress.""" if _db_file_path.exists() or _config_file_path.exists(): return db_password = _generate_secret_key(16) _create_config_file(DB_HOST, DB_NAME, DB_USER, db_password) _create_database(DB_NAME) _set_privileges(DB_HOST, DB_NAME, DB_USER, db_password) def _create_config_file(db_host, db_name, db_user, db_password): """Create a PHP configuration file included by WordPress.""" secret_keys = [_generate_secret_key() for _ in range(8)] config_contents = f'''~`+=,.:/?|') rand = random.SystemRandom() return ''.join(rand.choice(chars) for _ in range(length)) def subcommand_set_public(arguments): """Allow/disallow public access.""" public_access_file = pathlib.Path(PUBLIC_ACCESS_FILE) if arguments.enable == 'True': public_access_file.touch() else: public_access_file.unlink(missing_ok=True) action_utils.service_reload('apache2') def subcommand_dump_database(_): """Dump database to file.""" _db_backup_file.parent.mkdir(parents=True, exist_ok=True) with _db_backup_file.open('w') as file_handle: subprocess.run([ 'mysqldump', '--add-drop-database', '--add-drop-table', '--add-drop-trigger', '--user', 'root', '--databases', DB_NAME ], stdout=file_handle, check=True) def subcommand_restore_database(_): """Restore database from file.""" with _db_backup_file.open('r') as file_handle: subprocess.run(['mysql', '--user', 'root'], stdin=file_handle, check=True) _set_privileges(DB_HOST, DB_NAME, DB_USER, _read_db_password()) def _read_db_password(): """Return the password stored in the DB configuration file.""" aug = _load_augeas() return aug.get('./$dbpass').strip('\'"') def _load_augeas(): """Initialize augeas.""" aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD) aug.transform('Phpvars', str(_db_file_path)) aug.set('/augeas/context', '/files' + str(_db_file_path)) aug.load() return aug def main(): """Parse arguments and perform all duties.""" arguments = parse_arguments() subcommand = arguments.subcommand.replace('-', '_') subcommand_method = globals()['subcommand_' + subcommand] subcommand_method(arguments) if __name__ == '__main__': main()