mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
- Done automatically by running isort . in top level directory. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
191 lines
5.8 KiB
Python
Executable File
191 lines
5.8 KiB
Python
Executable File
#!/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'''<?php
|
|
# Created by FreedomBox
|
|
include_once('{_db_file_path}');
|
|
define('DB_NAME', $dbname);
|
|
define('DB_USER', $dbuser);
|
|
define('DB_PASSWORD', $dbpass);
|
|
define('DB_HOST', $dbserver);
|
|
|
|
define('AUTH_KEY', '{secret_keys[0]}');
|
|
define('SECURE_AUTH_KEY', '{secret_keys[1]}');
|
|
define('LOGGED_IN_KEY', '{secret_keys[2]}');
|
|
define('NONCE_KEY', '{secret_keys[3]}');
|
|
define('AUTH_SALT', '{secret_keys[4]}');
|
|
define('SECURE_AUTH_SALT', '{secret_keys[5]}');
|
|
define('LOGGED_IN_SALT', '{secret_keys[6]}');
|
|
define('NONCE_SALT', '{secret_keys[7]}');
|
|
|
|
define('WP_CONTENT_DIR', '/var/lib/wordpress/wp-content');
|
|
|
|
define('DISABLE_WP_CRON', true);
|
|
'''
|
|
_config_file_path.write_text(config_contents)
|
|
|
|
db_contents = f'''<?php
|
|
# Created by FreedomBox
|
|
$dbuser='{db_user}';
|
|
$dbpass='{db_password}';
|
|
$dbname='{db_name}';
|
|
$dbserver='{db_host}';
|
|
'''
|
|
old_umask = os.umask(0o037)
|
|
try:
|
|
_db_file_path.write_text(db_contents)
|
|
finally:
|
|
os.umask(old_umask)
|
|
|
|
shutil.chown(_db_file_path, group='www-data')
|
|
|
|
|
|
def _create_database(db_name):
|
|
"""Create an empty MySQL database for WordPress."""
|
|
# Wordpress' install.php creates the tables.
|
|
# SQL injection is avoided due to known input.
|
|
query = f'''CREATE DATABASE {db_name};'''
|
|
subprocess.run(['mysql', '--user', 'root'], input=query.encode(),
|
|
check=True)
|
|
|
|
|
|
def _set_privileges(db_host, db_name, db_user, db_password):
|
|
"""Create user, set password and provide permissions on the database."""
|
|
# SQL injection is avoided due to known input.
|
|
query = f'''GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,ALTER
|
|
ON {db_name}.*
|
|
TO {db_user}@{db_host}
|
|
IDENTIFIED BY '{db_password}';
|
|
FLUSH PRIVILEGES;
|
|
'''
|
|
subprocess.run(['mysql', '--user', 'root'], input=query.encode(),
|
|
check=True)
|
|
|
|
|
|
def _generate_secret_key(length=64, chars=None):
|
|
"""Generate a new random secret key for use with WordPress."""
|
|
chars = chars or (string.ascii_letters + string.digits +
|
|
'!@#$%^&*()-_ []{}<>~`+=,.:/?|')
|
|
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()
|