wordpress: Use privileged decorator for actions

Tests:

- Functional tests work (when libpam-tmpdir is removed)
  - Backup and restore of database works
- Initial setup work
  - Configuration file is created
  - Database is created
  - Website is accessible
- Enabling/disabling public access works
  - Configuration file created/deleted
  - App page show proper status

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2022-08-26 15:19:35 -07:00 committed by James Valleroy
parent 0c936512c4
commit d68a84d245
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
3 changed files with 29 additions and 65 deletions

View File

@ -1,11 +1,8 @@
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
""" """FreedomBox app to configure WordPress."""
FreedomBox app to configure WordPress.
"""
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from plinth import actions
from plinth import app as app_module from plinth import app as app_module
from plinth import cfg, frontpage, menu from plinth import cfg, frontpage, menu
from plinth.daemon import Daemon from plinth.daemon import Daemon
@ -15,9 +12,7 @@ from plinth.modules.firewall.components import Firewall
from plinth.package import Packages from plinth.package import Packages
from plinth.utils import format_lazy from plinth.utils import format_lazy
from . import manifest from . import manifest, privileged
PUBLIC_ACCESS_FILE = '/etc/wordpress/is_public'
_description = [ _description = [
_('WordPress is a popular way to create and manage websites and blogs. ' _('WordPress is a popular way to create and manage websites and blogs. '
@ -106,7 +101,7 @@ class WordPressApp(app_module.App):
def setup(self, old_version): def setup(self, old_version):
"""Install and configure the app.""" """Install and configure the app."""
super().setup(old_version) super().setup(old_version)
actions.superuser_run('wordpress', ['setup']) privileged.setup()
if not old_version: if not old_version:
self.enable() self.enable()
elif old_version < 3: elif old_version < 3:
@ -120,9 +115,9 @@ class WordPressBackupRestore(BackupRestore):
def backup_pre(self, packet): def backup_pre(self, packet):
"""Save database contents.""" """Save database contents."""
super().backup_pre(packet) super().backup_pre(packet)
actions.superuser_run('wordpress', ['dump-database']) privileged.dump_database()
def restore_post(self, packet): def restore_post(self, packet):
"""Restore database contents.""" """Restore database contents."""
super().restore_post(packet) super().restore_post(packet)
actions.superuser_run('wordpress', ['restore-database']) privileged.restore_database()

View File

@ -1,10 +1,6 @@
#!/usr/bin/python3
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
""" """Configuration helper for WordPress."""
Configuration helper for WordPress.
"""
import argparse
import os import os
import pathlib import pathlib
import random import random
@ -15,7 +11,9 @@ import subprocess
import augeas import augeas
from plinth import action_utils from plinth import action_utils
from plinth.modules.wordpress import PUBLIC_ACCESS_FILE from plinth.actions import privileged
PUBLIC_ACCESS_FILE = '/etc/wordpress/is_public'
_config_file_path = pathlib.Path('/etc/wordpress/config-default.php') _config_file_path = pathlib.Path('/etc/wordpress/config-default.php')
_static_config_file_path = pathlib.Path('/etc/wordpress/freedombox-static.php') _static_config_file_path = pathlib.Path('/etc/wordpress/freedombox-static.php')
@ -27,26 +25,8 @@ DB_NAME = 'wordpress_fbx'
DB_USER = 'wordpress_fbx' DB_USER = 'wordpress_fbx'
def parse_arguments(): @privileged
"""Return parsed command line arguments as dictionary.""" def setup():
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.""" """Create initial configuration and database for WordPress."""
if _db_file_path.exists() or _config_file_path.exists(): if _db_file_path.exists() or _config_file_path.exists():
if _config_file_path.exists(): if _config_file_path.exists():
@ -144,10 +124,11 @@ def _upgrade_config_file():
_config_file_path.write_text('\n'.join(lines), encoding='utf-8') _config_file_path.write_text('\n'.join(lines), encoding='utf-8')
def subcommand_set_public(arguments): @privileged
def set_public(enable: bool):
"""Allow/disallow public access.""" """Allow/disallow public access."""
public_access_file = pathlib.Path(PUBLIC_ACCESS_FILE) public_access_file = pathlib.Path(PUBLIC_ACCESS_FILE)
if arguments.enable == 'True': if enable:
public_access_file.touch() public_access_file.touch()
else: else:
public_access_file.unlink(missing_ok=True) public_access_file.unlink(missing_ok=True)
@ -155,7 +136,13 @@ def subcommand_set_public(arguments):
action_utils.service_reload('apache2') action_utils.service_reload('apache2')
def subcommand_dump_database(_): def is_public() -> bool:
"""Return whether public access is enabled."""
return pathlib.Path(PUBLIC_ACCESS_FILE).exists()
@privileged
def dump_database():
"""Dump database to file.""" """Dump database to file."""
_db_backup_file.parent.mkdir(parents=True, exist_ok=True) _db_backup_file.parent.mkdir(parents=True, exist_ok=True)
with _db_backup_file.open('w', encoding='utf-8') as file_handle: with _db_backup_file.open('w', encoding='utf-8') as file_handle:
@ -165,7 +152,8 @@ def subcommand_dump_database(_):
], stdout=file_handle, check=True) ], stdout=file_handle, check=True)
def subcommand_restore_database(_): @privileged
def restore_database():
"""Restore database from file.""" """Restore database from file."""
with _db_backup_file.open('r', encoding='utf-8') as file_handle: with _db_backup_file.open('r', encoding='utf-8') as file_handle:
subprocess.run(['mysql', '--user', 'root'], stdin=file_handle, subprocess.run(['mysql', '--user', 'root'], stdin=file_handle,
@ -189,16 +177,3 @@ def _load_augeas():
aug.load() aug.load()
return aug 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()

View File

@ -1,28 +1,25 @@
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
""" """FreedomBox app for configuring WordPress."""
FreedomBox app for configuring WordPress.
"""
import pathlib
from django.contrib import messages from django.contrib import messages
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from plinth import actions, views from plinth import views
from . import PUBLIC_ACCESS_FILE from . import privileged
from .forms import WordPressForm from .forms import WordPressForm
class WordPressAppView(views.AppView): class WordPressAppView(views.AppView):
"""Serve configuration page.""" """Serve configuration page."""
form_class = WordPressForm form_class = WordPressForm
app_id = 'wordpress' app_id = 'wordpress'
def get_initial(self): def get_initial(self):
"""Get the current WordPress settings.""" """Get the current WordPress settings."""
status = super().get_initial() status = super().get_initial()
status['is_public'] = pathlib.Path(PUBLIC_ACCESS_FILE).exists() status['is_public'] = privileged.is_public()
return status return status
def form_valid(self, form): def form_valid(self, form):
@ -30,10 +27,7 @@ class WordPressAppView(views.AppView):
old_status = form.initial old_status = form.initial
new_status = form.cleaned_data new_status = form.cleaned_data
if old_status['is_public'] != new_status['is_public']: if old_status['is_public'] != new_status['is_public']:
actions.superuser_run( privileged.set_public(new_status['is_public'])
'wordpress',
['set-public', '--enable',
str(new_status['is_public'])])
messages.success(self.request, _('Configuration updated')) messages.success(self.request, _('Configuration updated'))
return super().form_valid(form) return super().form_valid(form)